source: frontend/node_modules/css-tree/lib/walker/create.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.9 KB
Line 
1var hasOwnProperty = Object.prototype.hasOwnProperty;
2var noop = function() {};
3
4function ensureFunction(value) {
5 return typeof value === 'function' ? value : noop;
6}
7
8function invokeForType(fn, type) {
9 return function(node, item, list) {
10 if (node.type === type) {
11 fn.call(this, node, item, list);
12 }
13 };
14}
15
16function getWalkersFromStructure(name, nodeType) {
17 var structure = nodeType.structure;
18 var walkers = [];
19
20 for (var key in structure) {
21 if (hasOwnProperty.call(structure, key) === false) {
22 continue;
23 }
24
25 var fieldTypes = structure[key];
26 var walker = {
27 name: key,
28 type: false,
29 nullable: false
30 };
31
32 if (!Array.isArray(structure[key])) {
33 fieldTypes = [structure[key]];
34 }
35
36 for (var i = 0; i < fieldTypes.length; i++) {
37 var fieldType = fieldTypes[i];
38 if (fieldType === null) {
39 walker.nullable = true;
40 } else if (typeof fieldType === 'string') {
41 walker.type = 'node';
42 } else if (Array.isArray(fieldType)) {
43 walker.type = 'list';
44 }
45 }
46
47 if (walker.type) {
48 walkers.push(walker);
49 }
50 }
51
52 if (walkers.length) {
53 return {
54 context: nodeType.walkContext,
55 fields: walkers
56 };
57 }
58
59 return null;
60}
61
62function getTypesFromConfig(config) {
63 var types = {};
64
65 for (var name in config.node) {
66 if (hasOwnProperty.call(config.node, name)) {
67 var nodeType = config.node[name];
68
69 if (!nodeType.structure) {
70 throw new Error('Missed `structure` field in `' + name + '` node type definition');
71 }
72
73 types[name] = getWalkersFromStructure(name, nodeType);
74 }
75 }
76
77 return types;
78}
79
80function createTypeIterator(config, reverse) {
81 var fields = config.fields.slice();
82 var contextName = config.context;
83 var useContext = typeof contextName === 'string';
84
85 if (reverse) {
86 fields.reverse();
87 }
88
89 return function(node, context, walk) {
90 var prevContextValue;
91
92 if (useContext) {
93 prevContextValue = context[contextName];
94 context[contextName] = node;
95 }
96
97 for (var i = 0; i < fields.length; i++) {
98 var field = fields[i];
99 var ref = node[field.name];
100
101 if (!field.nullable || ref) {
102 if (field.type === 'list') {
103 if (reverse) {
104 ref.forEachRight(walk);
105 } else {
106 ref.forEach(walk);
107 }
108 } else {
109 walk(ref);
110 }
111 }
112 }
113
114 if (useContext) {
115 context[contextName] = prevContextValue;
116 }
117 };
118}
119
120function createFastTraveralMap(iterators) {
121 return {
122 Atrule: {
123 StyleSheet: iterators.StyleSheet,
124 Atrule: iterators.Atrule,
125 Rule: iterators.Rule,
126 Block: iterators.Block
127 },
128 Rule: {
129 StyleSheet: iterators.StyleSheet,
130 Atrule: iterators.Atrule,
131 Rule: iterators.Rule,
132 Block: iterators.Block
133 },
134 Declaration: {
135 StyleSheet: iterators.StyleSheet,
136 Atrule: iterators.Atrule,
137 Rule: iterators.Rule,
138 Block: iterators.Block
139 }
140 };
141}
142
143module.exports = function createWalker(config) {
144 var types = getTypesFromConfig(config);
145 var iteratorsNatural = {};
146 var iteratorsReverse = {};
147
148 for (var name in types) {
149 if (hasOwnProperty.call(types, name) && types[name] !== null) {
150 iteratorsNatural[name] = createTypeIterator(types[name], false);
151 iteratorsReverse[name] = createTypeIterator(types[name], true);
152 }
153 }
154
155 var fastTraversalIteratorsNatural = createFastTraveralMap(iteratorsNatural);
156 var fastTraversalIteratorsReverse = createFastTraveralMap(iteratorsReverse);
157
158 var walk = function(root, options) {
159 function walkNode(node, item, list) {
160 enter.call(context, node, item, list);
161
162 if (iterators.hasOwnProperty(node.type)) {
163 iterators[node.type](node, context, walkNode);
164 }
165
166 leave.call(context, node, item, list);
167 }
168
169 var enter = noop;
170 var leave = noop;
171 var iterators = iteratorsNatural;
172 var context = {
173 root: root,
174 stylesheet: null,
175 atrule: null,
176 atrulePrelude: null,
177 rule: null,
178 selector: null,
179 block: null,
180 declaration: null,
181 function: null
182 };
183
184 if (typeof options === 'function') {
185 enter = options;
186 } else if (options) {
187 enter = ensureFunction(options.enter);
188 leave = ensureFunction(options.leave);
189
190 if (options.reverse) {
191 iterators = iteratorsReverse;
192 }
193
194 if (options.visit) {
195 if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) {
196 iterators = options.reverse
197 ? fastTraversalIteratorsReverse[options.visit]
198 : fastTraversalIteratorsNatural[options.visit];
199 } else if (!types.hasOwnProperty(options.visit)) {
200 throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).join(', ') + ')');
201 }
202
203 enter = invokeForType(enter, options.visit);
204 leave = invokeForType(leave, options.visit);
205 }
206 }
207
208 if (enter === noop && leave === noop) {
209 throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
210 }
211
212 // swap handlers in reverse mode to invert visit order
213 if (options.reverse) {
214 var tmp = enter;
215 enter = leave;
216 leave = tmp;
217 }
218
219 walkNode(root);
220 };
221
222 walk.find = function(ast, fn) {
223 var found = null;
224
225 walk(ast, function(node, item, list) {
226 if (found === null && fn.call(this, node, item, list)) {
227 found = node;
228 }
229 });
230
231 return found;
232 };
233
234 walk.findLast = function(ast, fn) {
235 var found = null;
236
237 walk(ast, {
238 reverse: true,
239 enter: function(node, item, list) {
240 if (found === null && fn.call(this, node, item, list)) {
241 found = node;
242 }
243 }
244 });
245
246 return found;
247 };
248
249 walk.findAll = function(ast, fn) {
250 var found = [];
251
252 walk(ast, function(node, item, list) {
253 if (fn.call(this, node, item, list)) {
254 found.push(node);
255 }
256 });
257
258 return found;
259 };
260
261 return walk;
262};
Note: See TracBrowser for help on using the repository browser.