summaryrefslogtreecommitdiff
path: root/node_modules/csso/cjs/restructure/1-mergeAtrule.cjs
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/csso/cjs/restructure/1-mergeAtrule.cjs')
-rw-r--r--node_modules/csso/cjs/restructure/1-mergeAtrule.cjs109
1 files changed, 109 insertions, 0 deletions
diff --git a/node_modules/csso/cjs/restructure/1-mergeAtrule.cjs b/node_modules/csso/cjs/restructure/1-mergeAtrule.cjs
new file mode 100644
index 00000000..308587a0
--- /dev/null
+++ b/node_modules/csso/cjs/restructure/1-mergeAtrule.cjs
@@ -0,0 +1,109 @@
+'use strict';
+
+const cssTree = require('css-tree');
+
+const { hasOwnProperty } = Object.prototype;
+
+function addRuleToMap(map, item, list, single) {
+ const node = item.data;
+ const name = cssTree.keyword(node.name).basename;
+ const id = node.name.toLowerCase() + '/' + (node.prelude ? node.prelude.id : null);
+
+ if (!hasOwnProperty.call(map, name)) {
+ map[name] = Object.create(null);
+ }
+
+ if (single) {
+ delete map[name][id];
+ }
+
+ if (!hasOwnProperty.call(map[name], id)) {
+ map[name][id] = new cssTree.List();
+ }
+
+ map[name][id].append(list.remove(item));
+}
+
+function relocateAtrules(ast, options) {
+ const collected = Object.create(null);
+ let topInjectPoint = null;
+
+ ast.children.forEach(function(node, item, list) {
+ if (node.type === 'Atrule') {
+ const name = cssTree.keyword(node.name).basename;
+
+ switch (name) {
+ case 'keyframes':
+ addRuleToMap(collected, item, list, true);
+ return;
+
+ case 'media':
+ if (options.forceMediaMerge) {
+ addRuleToMap(collected, item, list, false);
+ return;
+ }
+ break;
+ }
+
+ if (topInjectPoint === null &&
+ name !== 'charset' &&
+ name !== 'import') {
+ topInjectPoint = item;
+ }
+ } else {
+ if (topInjectPoint === null) {
+ topInjectPoint = item;
+ }
+ }
+ });
+
+ for (const atrule in collected) {
+ for (const id in collected[atrule]) {
+ ast.children.insertList(
+ collected[atrule][id],
+ atrule === 'media' ? null : topInjectPoint
+ );
+ }
+ }
+}
+function isMediaRule(node) {
+ return node.type === 'Atrule' && node.name === 'media';
+}
+
+function processAtrule(node, item, list) {
+ if (!isMediaRule(node)) {
+ return;
+ }
+
+ const prev = item.prev && item.prev.data;
+
+ if (!prev || !isMediaRule(prev)) {
+ return;
+ }
+
+ // merge @media with same query
+ if (node.prelude &&
+ prev.prelude &&
+ node.prelude.id === prev.prelude.id) {
+ prev.block.children.appendList(node.block.children);
+ list.remove(item);
+
+ // TODO: use it when we can refer to several points in source
+ // prev.loc = {
+ // primary: prev.loc,
+ // merged: node.loc
+ // };
+ }
+}
+
+function rejoinAtrule(ast, options) {
+ relocateAtrules(ast, options);
+
+ cssTree.walk(ast, {
+ visit: 'Atrule',
+ reverse: true,
+ enter: processAtrule
+ });
+}
+
+module.exports = rejoinAtrule;