processSelector.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. var translate = require('../../../utils/translate.js');
  2. var specificity = require('./specificity.js');
  3. var nonFreezePseudoElements = {
  4. 'first-letter': true,
  5. 'first-line': true,
  6. 'after': true,
  7. 'before': true
  8. };
  9. var nonFreezePseudoClasses = {
  10. 'link': true,
  11. 'visited': true,
  12. 'hover': true,
  13. 'active': true,
  14. 'first-letter': true,
  15. 'first-line': true,
  16. 'after': true,
  17. 'before': true
  18. };
  19. module.exports = function freeze(node, usageData) {
  20. var pseudos = Object.create(null);
  21. var hasPseudo = false;
  22. node.selector.selectors.each(function(simpleSelector) {
  23. var tagName = '*';
  24. var scope = 0;
  25. simpleSelector.sequence.some(function(node) {
  26. switch (node.type) {
  27. case 'Class':
  28. if (usageData && usageData.scopes) {
  29. var classScope = usageData.scopes[node.name] || 0;
  30. if (scope !== 0 && classScope !== scope) {
  31. throw new Error('Selector can\'t has classes from different scopes: ' + translate(simpleSelector));
  32. }
  33. scope = classScope;
  34. }
  35. break;
  36. case 'PseudoClass':
  37. if (!nonFreezePseudoClasses.hasOwnProperty(node.name)) {
  38. pseudos[node.name] = true;
  39. hasPseudo = true;
  40. }
  41. break;
  42. case 'PseudoElement':
  43. if (!nonFreezePseudoElements.hasOwnProperty(node.name)) {
  44. pseudos[node.name] = true;
  45. hasPseudo = true;
  46. }
  47. break;
  48. case 'FunctionalPseudo':
  49. pseudos[node.name] = true;
  50. hasPseudo = true;
  51. break;
  52. case 'Negation':
  53. pseudos.not = true;
  54. hasPseudo = true;
  55. break;
  56. case 'Identifier':
  57. tagName = node.name;
  58. break;
  59. case 'Attribute':
  60. if (node.flags) {
  61. pseudos['[' + node.flags + ']'] = true;
  62. hasPseudo = true;
  63. }
  64. break;
  65. case 'Combinator':
  66. tagName = '*';
  67. break;
  68. }
  69. });
  70. simpleSelector.id = translate(simpleSelector);
  71. simpleSelector.compareMarker = specificity(simpleSelector).toString();
  72. if (scope) {
  73. simpleSelector.compareMarker += ':' + scope;
  74. }
  75. if (tagName !== '*') {
  76. simpleSelector.compareMarker += ',' + tagName;
  77. }
  78. });
  79. if (hasPseudo) {
  80. node.pseudoSignature = Object.keys(pseudos).sort().join(',');
  81. }
  82. };