1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = buildSelectorProfile;
|
7 |
|
8 | var _cssTree = _interopRequireDefault(require("css-tree"));
|
9 |
|
10 | var _debug = _interopRequireDefault(require("debug"));
|
11 |
|
12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
13 |
|
14 | const debuglog = (0, _debug.default)('penthouse:preformatting:selectors-profile');
|
15 | var pseudoSelectorsToKeep = [':before', ':after', ':visited', ':first-letter', ':first-line'];
|
16 |
|
17 | var pseudoSelectorsToKeepRegex = pseudoSelectorsToKeep.map(function (s) {
|
18 | return ':?' + s;
|
19 | }).join('|');
|
20 |
|
21 |
|
22 | var PSUEDO_SELECTOR_REGEXP = new RegExp(pseudoSelectorsToKeepRegex, 'g');
|
23 |
|
24 | function matchesSelectors(selector, selectors) {
|
25 | return selectors.some(function (toMatchSelector) {
|
26 | if (toMatchSelector.type === 'RegExp') {
|
27 | const {
|
28 | source,
|
29 | flags
|
30 | } = toMatchSelector;
|
31 | const re = new RegExp(source, flags);
|
32 | return re.test(selector);
|
33 | }
|
34 |
|
35 | return toMatchSelector.value === selector;
|
36 | });
|
37 | }
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | function normalizeSelector(selectorNode, forceInclude, forceExclude) {
|
44 | const selector = _cssTree.default.generate(selectorNode);
|
45 |
|
46 |
|
47 |
|
48 | let modifiedSelector = selector.trim();
|
49 |
|
50 | if (forceInclude && matchesSelectors(modifiedSelector, forceInclude)) {
|
51 | debuglog('forceInclude', modifiedSelector);
|
52 | return true;
|
53 | }
|
54 |
|
55 | if (forceExclude && matchesSelectors(modifiedSelector, forceExclude)) {
|
56 | debuglog('forceExclude', modifiedSelector);
|
57 | return false;
|
58 | }
|
59 |
|
60 | if (modifiedSelector.indexOf(':') > -1) {
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | if (/:?:(-moz-)?selection/.test(modifiedSelector)) {
|
66 | return false;
|
67 | }
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | modifiedSelector = modifiedSelector.replace(PSUEDO_SELECTOR_REGEXP, '');
|
74 |
|
75 |
|
76 | if (modifiedSelector.replace(/:[:]?([a-zA-Z0-9\-_])*/g, '').trim().length === 0) {
|
77 | return true;
|
78 | }
|
79 |
|
80 |
|
81 |
|
82 |
|
83 | modifiedSelector = modifiedSelector.replace(/:?:-[a-z-]*/g, '');
|
84 | }
|
85 |
|
86 | return modifiedSelector;
|
87 | }
|
88 |
|
89 | async function buildSelectorProfile(ast, forceInclude, forceExclude) {
|
90 | debuglog('buildSelectorProfile START');
|
91 | const selectors = new Set();
|
92 | const selectorNodeMap = new WeakMap();
|
93 |
|
94 | _cssTree.default.walk(ast, {
|
95 | visit: 'Rule',
|
96 | enter: function (rule, item, list) {
|
97 |
|
98 | if (this.atrule && _cssTree.default.keyword(this.atrule.name).basename === 'keyframes') {
|
99 | return;
|
100 | }
|
101 |
|
102 |
|
103 | if (rule.prelude.type !== 'SelectorList') {
|
104 | return;
|
105 | }
|
106 |
|
107 | const addedRule = rule.block.children.some(declarationNode => {
|
108 | if (declarationNode.property === 'grid-area') {
|
109 | const ruleSelectorList = _cssTree.default.generate(rule.prelude);
|
110 |
|
111 | debuglog('rule contains grid-area, keeping: ', ruleSelectorList);
|
112 | selectors.add(ruleSelectorList);
|
113 | selectorNodeMap.set(rule.prelude, ruleSelectorList);
|
114 | return true;
|
115 | }
|
116 | });
|
117 | if (addedRule) return;
|
118 |
|
119 | rule.prelude.children.each(selectorNode => {
|
120 | const selector = normalizeSelector(selectorNode, forceInclude, forceExclude);
|
121 |
|
122 | if (typeof selector === 'string') {
|
123 | selectors.add(selector);
|
124 | }
|
125 |
|
126 | selectorNodeMap.set(selectorNode, selector);
|
127 | });
|
128 | }
|
129 | });
|
130 |
|
131 | debuglog('buildSelectorProfile DONE');
|
132 | return {
|
133 | selectorNodeMap,
|
134 | selectors: Array.from(selectors)
|
135 | };
|
136 | } |
\ | No newline at end of file |