PageRenderTime 1595ms CodeModel.GetById 34ms RepoModel.GetById 4ms app.codeStats 0ms

/node_modules/less-middleware/node_modules/less/lib/less/to-css-visitor.js

https://gitlab.com/mba811/webAudio
JavaScript | 243 lines | 204 code | 28 blank | 11 comment | 52 complexity | a1818cbaa7950b08c82ec85186b7af24 MD5 | raw file
Possible License(s): Apache-2.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, 0BSD
  1. (function (tree) {
  2. tree.toCSSVisitor = function(env) {
  3. this._visitor = new tree.visitor(this);
  4. this._env = env;
  5. };
  6. tree.toCSSVisitor.prototype = {
  7. isReplacing: true,
  8. run: function (root) {
  9. return this._visitor.visit(root);
  10. },
  11. visitRule: function (ruleNode, visitArgs) {
  12. if (ruleNode.variable) {
  13. return [];
  14. }
  15. return ruleNode;
  16. },
  17. visitMixinDefinition: function (mixinNode, visitArgs) {
  18. // mixin definitions do not get eval'd - this means they keep state
  19. // so we have to clear that state here so it isn't used if toCSS is called twice
  20. mixinNode.frames = [];
  21. return [];
  22. },
  23. visitExtend: function (extendNode, visitArgs) {
  24. return [];
  25. },
  26. visitComment: function (commentNode, visitArgs) {
  27. if (commentNode.isSilent(this._env)) {
  28. return [];
  29. }
  30. return commentNode;
  31. },
  32. visitMedia: function(mediaNode, visitArgs) {
  33. mediaNode.accept(this._visitor);
  34. visitArgs.visitDeeper = false;
  35. if (!mediaNode.rules.length) {
  36. return [];
  37. }
  38. return mediaNode;
  39. },
  40. visitDirective: function(directiveNode, visitArgs) {
  41. if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
  42. return [];
  43. }
  44. if (directiveNode.name === "@charset") {
  45. // Only output the debug info together with subsequent @charset definitions
  46. // a comment (or @media statement) before the actual @charset directive would
  47. // be considered illegal css as it has to be on the first line
  48. if (this.charset) {
  49. if (directiveNode.debugInfo) {
  50. var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n");
  51. comment.debugInfo = directiveNode.debugInfo;
  52. return this._visitor.visit(comment);
  53. }
  54. return [];
  55. }
  56. this.charset = true;
  57. }
  58. if (directiveNode.rules && directiveNode.rules.rules) {
  59. this._mergeRules(directiveNode.rules.rules);
  60. }
  61. return directiveNode;
  62. },
  63. checkPropertiesInRoot: function(rules) {
  64. var ruleNode;
  65. for(var i = 0; i < rules.length; i++) {
  66. ruleNode = rules[i];
  67. if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
  68. throw { message: "properties must be inside selector blocks, they cannot be in the root.",
  69. index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
  70. }
  71. }
  72. },
  73. visitRuleset: function (rulesetNode, visitArgs) {
  74. var rule, rulesets = [];
  75. if (rulesetNode.firstRoot) {
  76. this.checkPropertiesInRoot(rulesetNode.rules);
  77. }
  78. if (! rulesetNode.root) {
  79. if (rulesetNode.paths) {
  80. rulesetNode.paths = rulesetNode.paths
  81. .filter(function(p) {
  82. var i;
  83. if (p[0].elements[0].combinator.value === ' ') {
  84. p[0].elements[0].combinator = new(tree.Combinator)('');
  85. }
  86. for(i = 0; i < p.length; i++) {
  87. if (p[i].getIsReferenced() && p[i].getIsOutput()) {
  88. return true;
  89. }
  90. }
  91. return false;
  92. });
  93. }
  94. // Compile rules and rulesets
  95. var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0;
  96. for (var i = 0; i < nodeRuleCnt; ) {
  97. rule = nodeRules[i];
  98. if (rule && rule.rules) {
  99. // visit because we are moving them out from being a child
  100. rulesets.push(this._visitor.visit(rule));
  101. nodeRules.splice(i, 1);
  102. nodeRuleCnt--;
  103. continue;
  104. }
  105. i++;
  106. }
  107. // accept the visitor to remove rules and refactor itself
  108. // then we can decide now whether we want it or not
  109. if (nodeRuleCnt > 0) {
  110. rulesetNode.accept(this._visitor);
  111. } else {
  112. rulesetNode.rules = null;
  113. }
  114. visitArgs.visitDeeper = false;
  115. nodeRules = rulesetNode.rules;
  116. if (nodeRules) {
  117. this._mergeRules(nodeRules);
  118. nodeRules = rulesetNode.rules;
  119. }
  120. if (nodeRules) {
  121. this._removeDuplicateRules(nodeRules);
  122. nodeRules = rulesetNode.rules;
  123. }
  124. // now decide whether we keep the ruleset
  125. if (nodeRules && nodeRules.length > 0 && rulesetNode.paths.length > 0) {
  126. rulesets.splice(0, 0, rulesetNode);
  127. }
  128. } else {
  129. rulesetNode.accept(this._visitor);
  130. visitArgs.visitDeeper = false;
  131. if (rulesetNode.firstRoot || (rulesetNode.rules && rulesetNode.rules.length > 0)) {
  132. rulesets.splice(0, 0, rulesetNode);
  133. }
  134. }
  135. if (rulesets.length === 1) {
  136. return rulesets[0];
  137. }
  138. return rulesets;
  139. },
  140. _removeDuplicateRules: function(rules) {
  141. if (!rules) { return; }
  142. // remove duplicates
  143. var ruleCache = {},
  144. ruleList, rule, i;
  145. for(i = rules.length - 1; i >= 0 ; i--) {
  146. rule = rules[i];
  147. if (rule instanceof tree.Rule) {
  148. if (!ruleCache[rule.name]) {
  149. ruleCache[rule.name] = rule;
  150. } else {
  151. ruleList = ruleCache[rule.name];
  152. if (ruleList instanceof tree.Rule) {
  153. ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)];
  154. }
  155. var ruleCSS = rule.toCSS(this._env);
  156. if (ruleList.indexOf(ruleCSS) !== -1) {
  157. rules.splice(i, 1);
  158. } else {
  159. ruleList.push(ruleCSS);
  160. }
  161. }
  162. }
  163. }
  164. },
  165. _mergeRules: function (rules) {
  166. if (!rules) { return; }
  167. var groups = {},
  168. parts,
  169. rule,
  170. key;
  171. for (var i = 0; i < rules.length; i++) {
  172. rule = rules[i];
  173. if ((rule instanceof tree.Rule) && rule.merge) {
  174. key = [rule.name,
  175. rule.important ? "!" : ""].join(",");
  176. if (!groups[key]) {
  177. groups[key] = [];
  178. } else {
  179. rules.splice(i--, 1);
  180. }
  181. groups[key].push(rule);
  182. }
  183. }
  184. Object.keys(groups).map(function (k) {
  185. function toExpression(values) {
  186. return new (tree.Expression)(values.map(function (p) {
  187. return p.value;
  188. }));
  189. }
  190. function toValue(values) {
  191. return new (tree.Value)(values.map(function (p) {
  192. return p;
  193. }));
  194. }
  195. parts = groups[k];
  196. if (parts.length > 1) {
  197. rule = parts[0];
  198. var spacedGroups = [];
  199. var lastSpacedGroup = [];
  200. parts.map(function (p) {
  201. if (p.merge==="+") {
  202. if (lastSpacedGroup.length > 0) {
  203. spacedGroups.push(toExpression(lastSpacedGroup));
  204. }
  205. lastSpacedGroup = [];
  206. }
  207. lastSpacedGroup.push(p);
  208. });
  209. spacedGroups.push(toExpression(lastSpacedGroup));
  210. rule.value = toValue(spacedGroups);
  211. }
  212. });
  213. }
  214. };
  215. })(require('./tree'));