source: trip-planner-front/node_modules/postcss-selector-parser/API.md@ 6c1585f

Last change on this file since 6c1585f was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 20.4 KB
Line 
1# API Documentation
2
3*Please use only this documented API when working with the parser. Methods
4not documented here are subject to change at any point.*
5
6## `parser` function
7
8This is the module's main entry point.
9
10```js
11const parser = require('postcss-selector-parser');
12```
13
14### `parser([transform], [options])`
15
16Creates a new `processor` instance
17
18```js
19const processor = parser();
20```
21
22Or, with optional transform function
23
24```js
25const transform = selectors => {
26 selectors.walkUniversals(selector => {
27 selector.remove();
28 });
29};
30
31const processor = parser(transform)
32
33// Example
34const result = processor.processSync('*.class');
35// => .class
36```
37
38[See processor documentation](#processor)
39
40Arguments:
41
42* `transform (function)`: Provide a function to work with the parsed AST.
43* `options (object)`: Provide default options for all calls on the returned `Processor`.
44
45### `parser.attribute([props])`
46
47Creates a new attribute selector.
48
49```js
50parser.attribute({attribute: 'href'});
51// => [href]
52```
53
54Arguments:
55
56* `props (object)`: The new node's properties.
57
58### `parser.className([props])`
59
60Creates a new class selector.
61
62```js
63parser.className({value: 'button'});
64// => .button
65```
66
67Arguments:
68
69* `props (object)`: The new node's properties.
70
71### `parser.combinator([props])`
72
73Creates a new selector combinator.
74
75```js
76parser.combinator({value: '+'});
77// => +
78```
79
80Arguments:
81
82* `props (object)`: The new node's properties.
83
84Notes:
85* **Descendant Combinators** The value of descendant combinators created by the
86 parser always just a single space (`" "`). For descendant selectors with no
87 comments, additional space is now stored in `node.spaces.before`. Depending
88 on the location of comments, additional spaces may be stored in
89 `node.raws.spaces.before`, `node.raws.spaces.after`, or `node.raws.value`.
90* **Named Combinators** Although, nonstandard and unlikely to ever become a standard,
91 named combinators like `/deep/` and `/for/` are parsed as combinators. The
92 `node.value` is name after being unescaped and normalized as lowercase. The
93 original value for the combinator name is stored in `node.raws.value`.
94
95
96### `parser.comment([props])`
97
98Creates a new comment.
99
100```js
101parser.comment({value: '/* Affirmative, Dave. I read you. */'});
102// => /* Affirmative, Dave. I read you. */
103```
104
105Arguments:
106
107* `props (object)`: The new node's properties.
108
109### `parser.id([props])`
110
111Creates a new id selector.
112
113```js
114parser.id({value: 'search'});
115// => #search
116```
117
118Arguments:
119
120* `props (object)`: The new node's properties.
121
122### `parser.nesting([props])`
123
124Creates a new nesting selector.
125
126```js
127parser.nesting();
128// => &
129```
130
131Arguments:
132
133* `props (object)`: The new node's properties.
134
135### `parser.pseudo([props])`
136
137Creates a new pseudo selector.
138
139```js
140parser.pseudo({value: '::before'});
141// => ::before
142```
143
144Arguments:
145
146* `props (object)`: The new node's properties.
147
148### `parser.root([props])`
149
150Creates a new root node.
151
152```js
153parser.root();
154// => (empty)
155```
156
157Arguments:
158
159* `props (object)`: The new node's properties.
160
161### `parser.selector([props])`
162
163Creates a new selector node.
164
165```js
166parser.selector();
167// => (empty)
168```
169
170Arguments:
171
172* `props (object)`: The new node's properties.
173
174### `parser.string([props])`
175
176Creates a new string node.
177
178```js
179parser.string();
180// => (empty)
181```
182
183Arguments:
184
185* `props (object)`: The new node's properties.
186
187### `parser.tag([props])`
188
189Creates a new tag selector.
190
191```js
192parser.tag({value: 'button'});
193// => button
194```
195
196Arguments:
197
198* `props (object)`: The new node's properties.
199
200### `parser.universal([props])`
201
202Creates a new universal selector.
203
204```js
205parser.universal();
206// => *
207```
208
209Arguments:
210
211* `props (object)`: The new node's properties.
212
213## Node types
214
215### `node.type`
216
217A string representation of the selector type. It can be one of the following;
218`attribute`, `class`, `combinator`, `comment`, `id`, `nesting`, `pseudo`,
219`root`, `selector`, `string`, `tag`, or `universal`. Note that for convenience,
220these constants are exposed on the main `parser` as uppercased keys. So for
221example you can get `id` by querying `parser.ID`.
222
223```js
224parser.attribute({attribute: 'href'}).type;
225// => 'attribute'
226```
227
228### `node.parent`
229
230Returns the parent node.
231
232```js
233root.nodes[0].parent === root;
234```
235
236### `node.toString()`, `String(node)`, or `'' + node`
237
238Returns a string representation of the node.
239
240```js
241const id = parser.id({value: 'search'});
242console.log(String(id));
243// => #search
244```
245
246### `node.next()` & `node.prev()`
247
248Returns the next/previous child of the parent node.
249
250```js
251const next = id.next();
252if (next && next.type !== 'combinator') {
253 throw new Error('Qualified IDs are not allowed!');
254}
255```
256
257### `node.replaceWith(node)`
258
259Replace a node with another.
260
261```js
262const attr = selectors.first.first;
263const className = parser.className({value: 'test'});
264attr.replaceWith(className);
265```
266
267Arguments:
268
269* `node`: The node to substitute the original with.
270
271### `node.remove()`
272
273Removes the node from its parent node.
274
275```js
276if (node.type === 'id') {
277 node.remove();
278}
279```
280
281### `node.clone()`
282
283Returns a copy of a node, detached from any parent containers that the
284original might have had.
285
286```js
287const cloned = parser.id({value: 'search'});
288String(cloned);
289
290// => #search
291```
292
293### `node.isAtPosition(line, column)`
294
295Return a `boolean` indicating whether this node includes the character at the
296position of the given line and column. Returns `undefined` if the nodes lack
297sufficient source metadata to determine the position.
298
299Arguments:
300
301* `line`: 1-index based line number relative to the start of the selector.
302* `column`: 1-index based column number relative to the start of the selector.
303
304### `node.spaces`
305
306Extra whitespaces around the node will be moved into `node.spaces.before` and
307`node.spaces.after`. So for example, these spaces will be moved as they have
308no semantic meaning:
309
310```css
311 h1 , h2 {}
312```
313
314For descendent selectors, the value is always a single space.
315
316```css
317h1 h2 {}
318```
319
320Additional whitespace is found in either the `node.spaces.before` and `node.spaces.after` depending on the presence of comments or other whitespace characters. If the actual whitespace does not start or end with a single space, the node's raw value is set to the actual space(s) found in the source.
321
322### `node.source`
323
324An object describing the node's start/end, line/column source position.
325
326Within the following CSS, the `.bar` class node ...
327
328```css
329.foo,
330 .bar {}
331```
332
333... will contain the following `source` object.
334
335```js
336source: {
337 start: {
338 line: 2,
339 column: 3
340 },
341 end: {
342 line: 2,
343 column: 6
344 }
345}
346```
347
348### `node.sourceIndex`
349
350The zero-based index of the node within the original source string.
351
352Within the following CSS, the `.baz` class node will have a `sourceIndex` of `12`.
353
354```css
355.foo, .bar, .baz {}
356```
357
358## Container types
359
360The `root`, `selector`, and `pseudo` nodes have some helper methods for working
361with their children.
362
363### `container.nodes`
364
365An array of the container's children.
366
367```js
368// Input: h1 h2
369selectors.at(0).nodes.length // => 3
370selectors.at(0).nodes[0].value // => 'h1'
371selectors.at(0).nodes[1].value // => ' '
372```
373
374### `container.first` & `container.last`
375
376The first/last child of the container.
377
378```js
379selector.first === selector.nodes[0];
380selector.last === selector.nodes[selector.nodes.length - 1];
381```
382
383### `container.at(index)`
384
385Returns the node at position `index`.
386
387```js
388selector.at(0) === selector.first;
389selector.at(0) === selector.nodes[0];
390```
391
392Arguments:
393
394* `index`: The index of the node to return.
395
396### `container.atPosition(line, column)`
397
398Returns the node at the source position `index`.
399
400```js
401selector.at(0) === selector.first;
402selector.at(0) === selector.nodes[0];
403```
404
405Arguments:
406
407* `index`: The index of the node to return.
408
409### `container.index(node)`
410
411Return the index of the node within its container.
412
413```js
414selector.index(selector.nodes[2]) // => 2
415```
416
417Arguments:
418
419* `node`: A node within the current container.
420
421### `container.length`
422
423Proxy to the length of the container's nodes.
424
425```js
426container.length === container.nodes.length
427```
428
429### `container` Array iterators
430
431The container class provides proxies to certain Array methods; these are:
432
433* `container.map === container.nodes.map`
434* `container.reduce === container.nodes.reduce`
435* `container.every === container.nodes.every`
436* `container.some === container.nodes.some`
437* `container.filter === container.nodes.filter`
438* `container.sort === container.nodes.sort`
439
440Note that these methods only work on a container's immediate children; recursive
441iteration is provided by `container.walk`.
442
443### `container.each(callback)`
444
445Iterate the container's immediate children, calling `callback` for each child.
446You may return `false` within the callback to break the iteration.
447
448```js
449let className;
450selectors.each((selector, index) => {
451 if (selector.type === 'class') {
452 className = selector.value;
453 return false;
454 }
455});
456```
457
458Note that unlike `Array#forEach()`, this iterator is safe to use whilst adding
459or removing nodes from the container.
460
461Arguments:
462
463* `callback (function)`: A function to call for each node, which receives `node`
464 and `index` arguments.
465
466### `container.walk(callback)`
467
468Like `container#each`, but will also iterate child nodes as long as they are
469`container` types.
470
471```js
472selectors.walk((selector, index) => {
473 // all nodes
474});
475```
476
477Arguments:
478
479* `callback (function)`: A function to call for each node, which receives `node`
480 and `index` arguments.
481
482This iterator is safe to use whilst mutating `container.nodes`,
483like `container#each`.
484
485### `container.walk` proxies
486
487The container class provides proxy methods for iterating over types of nodes,
488so that it is easier to write modules that target specific selectors. Those
489methods are:
490
491* `container.walkAttributes`
492* `container.walkClasses`
493* `container.walkCombinators`
494* `container.walkComments`
495* `container.walkIds`
496* `container.walkNesting`
497* `container.walkPseudos`
498* `container.walkTags`
499* `container.walkUniversals`
500
501### `container.split(callback)`
502
503This method allows you to split a group of nodes by returning `true` from
504a callback. It returns an array of arrays, where each inner array corresponds
505to the groups that you created via the callback.
506
507```js
508// (input) => h1 h2>>h3
509const list = selectors.first.split(selector => {
510 return selector.type === 'combinator';
511});
512
513// (node values) => [['h1', ' '], ['h2', '>>'], ['h3']]
514```
515
516Arguments:
517
518* `callback (function)`: A function to call for each node, which receives `node`
519 as an argument.
520
521### `container.prepend(node)` & `container.append(node)`
522
523Add a node to the start/end of the container. Note that doing so will set
524the parent property of the node to this container.
525
526```js
527const id = parser.id({value: 'search'});
528selector.append(id);
529```
530
531Arguments:
532
533* `node`: The node to add.
534
535### `container.insertBefore(old, new)` & `container.insertAfter(old, new)`
536
537Add a node before or after an existing node in a container:
538
539```js
540selectors.walk(selector => {
541 if (selector.type !== 'class') {
542 const className = parser.className({value: 'theme-name'});
543 selector.parent.insertAfter(selector, className);
544 }
545});
546```
547
548Arguments:
549
550* `old`: The existing node in the container.
551* `new`: The new node to add before/after the existing node.
552
553### `container.removeChild(node)`
554
555Remove the node from the container. Note that you can also use
556`node.remove()` if you would like to remove just a single node.
557
558```js
559selector.length // => 2
560selector.remove(id)
561selector.length // => 1;
562id.parent // undefined
563```
564
565Arguments:
566
567* `node`: The node to remove.
568
569### `container.removeAll()` or `container.empty()`
570
571Remove all children from the container.
572
573```js
574selector.removeAll();
575selector.length // => 0
576```
577
578## Root nodes
579
580A root node represents a comma separated list of selectors. Indeed, all
581a root's `toString()` method does is join its selector children with a ','.
582Other than this, it has no special functionality and acts like a container.
583
584### `root.trailingComma`
585
586This will be set to `true` if the input has a trailing comma, in order to
587support parsing of legacy CSS hacks.
588
589## Selector nodes
590
591A selector node represents a single complex selector. For example, this
592selector string `h1 h2 h3, [href] > p`, is represented as two selector nodes.
593It has no special functionality of its own.
594
595## Pseudo nodes
596
597A pseudo selector extends a container node; if it has any parameters of its
598own (such as `h1:not(h2, h3)`), they will be its children. Note that the pseudo
599`value` will always contain the colons preceding the pseudo identifier. This
600is so that both `:before` and `::before` are properly represented in the AST.
601
602## Attribute nodes
603
604### `attribute.quoted`
605
606Returns `true` if the attribute's value is wrapped in quotation marks, false if it is not.
607Remains `undefined` if there is no attribute value.
608
609```css
610[href=foo] /* false */
611[href='foo'] /* true */
612[href="foo"] /* true */
613[href] /* undefined */
614```
615
616### `attribute.qualifiedAttribute`
617
618Returns the attribute name qualified with the namespace if one is given.
619
620### `attribute.offsetOf(part)`
621
622 Returns the offset of the attribute part specified relative to the
623 start of the node of the output string. This is useful in raising
624 error messages about a specific part of the attribute, especially
625 in combination with `attribute.sourceIndex`.
626
627 Returns `-1` if the name is invalid or the value doesn't exist in this
628 attribute.
629
630 The legal values for `part` are:
631
632 * `"ns"` - alias for "namespace"
633 * `"namespace"` - the namespace if it exists.
634 * `"attribute"` - the attribute name
635 * `"attributeNS"` - the start of the attribute or its namespace
636 * `"operator"` - the match operator of the attribute
637 * `"value"` - The value (string or identifier)
638 * `"insensitive"` - the case insensitivity flag
639
640### `attribute.raws.unquoted`
641
642Returns the unquoted content of the attribute's value.
643Remains `undefined` if there is no attribute value.
644
645```css
646[href=foo] /* foo */
647[href='foo'] /* foo */
648[href="foo"] /* foo */
649[href] /* undefined */
650```
651
652### `attribute.spaces`
653
654Like `node.spaces` with the `before` and `after` values containing the spaces
655around the element, the parts of the attribute can also have spaces before
656and after them. The for each of `attribute`, `operator`, `value` and
657`insensitive` there is corresponding property of the same nam in
658`node.spaces` that has an optional `before` or `after` string containing only
659whitespace.
660
661Note that corresponding values in `attributes.raws.spaces` contain values
662including any comments. If set, these values will override the
663`attribute.spaces` value. Take care to remove them if changing
664`attribute.spaces`.
665
666### `attribute.raws`
667
668The raws object stores comments and other information necessary to re-render
669the node exactly as it was in the source.
670
671If a comment is embedded within the identifiers for the `namespace`, `attribute`
672or `value` then a property is placed in the raws for that value containing the full source of the propery including comments.
673
674If a comment is embedded within the space between parts of the attribute
675then the raw for that space is set accordingly.
676
677Setting an attribute's property `raws` value to be deleted.
678
679For now, changing the spaces required also updating or removing any of the
680raws values that override them.
681
682Example: `[ /*before*/ href /* after-attr */ = /* after-operator */ te/*inside-value*/st/* wow */ /*omg*/i/*bbq*/ /*whodoesthis*/]` would parse as:
683
684```js
685{
686 attribute: "href",
687 operator: "=",
688 value: "test",
689 spaces: {
690 before: '',
691 after: '',
692 attribute: { before: ' ', after: ' ' },
693 operator: { after: ' ' },
694 value: { after: ' ' },
695 insensitive: { after: ' ' }
696 },
697 raws: {
698 spaces: {
699 attribute: { before: ' /*before*/ ', after: ' /* after-attr */ ' },
700 operator: { after: ' /* after-operator */ ' },
701 value: { after: '/* wow */ /*omg*/' },
702 insensitive: { after: '/*bbq*/ /*whodoesthis*/' }
703 },
704 unquoted: 'test',
705 value: 'te/*inside-value*/st'
706 }
707}
708```
709
710## `Processor`
711
712### `ProcessorOptions`
713
714* `lossless` - When `true`, whitespace is preserved. Defaults to `true`.
715* `updateSelector` - When `true`, if any processor methods are passed a postcss
716 `Rule` node instead of a string, then that Rule's selector is updated
717 with the results of the processing. Defaults to `true`.
718
719### `process|processSync(selectors, [options])`
720
721Processes the `selectors`, returning a string from the result of processing.
722
723Note: when the `updateSelector` option is set, the rule's selector
724will be updated with the resulting string.
725
726**Example:**
727
728```js
729const parser = require("postcss-selector-parser");
730const processor = parser();
731
732let result = processor.processSync(' .class');
733console.log(result);
734// => .class
735
736// Asynchronous operation
737let promise = processor.process(' .class').then(result => {
738 console.log(result)
739 // => .class
740});
741
742// To have the parser normalize whitespace values, utilize the options
743result = processor.processSync(' .class ', {lossless: false});
744console.log(result);
745// => .class
746
747// For better syntax errors, pass a PostCSS Rule node.
748const postcss = require('postcss');
749rule = postcss.rule({selector: ' #foo > a, .class '});
750processor.process(rule, {lossless: false, updateSelector: true}).then(result => {
751 console.log(result);
752 // => #foo>a,.class
753 console.log("rule:", rule.selector);
754 // => rule: #foo>a,.class
755})
756```
757
758Arguments:
759
760* `selectors (string|postcss.Rule)`: Either a selector string or a PostCSS Rule
761 node.
762* `[options] (object)`: Process options
763
764
765### `ast|astSync(selectors, [options])`
766
767Like `process()` and `processSync()` but after
768processing the `selectors` these methods return the `Root` node of the result
769instead of a string.
770
771Note: when the `updateSelector` option is set, the rule's selector
772will be updated with the resulting string.
773
774### `transform|transformSync(selectors, [options])`
775
776Like `process()` and `processSync()` but after
777processing the `selectors` these methods return the value returned by the
778processor callback.
779
780Note: when the `updateSelector` option is set, the rule's selector
781will be updated with the resulting string.
782
783### Error Handling Within Selector Processors
784
785The root node passed to the selector processor callback
786has a method `error(message, options)` that returns an
787error object. This method should always be used to raise
788errors relating to the syntax of selectors. The options
789to this method are passed to postcss's error constructor
790([documentation](http://api.postcss.org/Container.html#error)).
791
792#### Async Error Example
793
794```js
795let processor = (root) => {
796 return new Promise((resolve, reject) => {
797 root.walkClasses((classNode) => {
798 if (/^(.*)[-_]/.test(classNode.value)) {
799 let msg = "classes may not have underscores or dashes in them";
800 reject(root.error(msg, {
801 index: classNode.sourceIndex + RegExp.$1.length + 1,
802 word: classNode.value
803 }));
804 }
805 });
806 resolve();
807 });
808};
809
810const postcss = require("postcss");
811const parser = require("postcss-selector-parser");
812const selectorProcessor = parser(processor);
813const plugin = postcss.plugin('classValidator', (options) => {
814 return (root) => {
815 let promises = [];
816 root.walkRules(rule => {
817 promises.push(selectorProcessor.process(rule));
818 });
819 return Promise.all(promises);
820 };
821});
822postcss(plugin()).process(`
823.foo-bar {
824 color: red;
825}
826`.trim(), {from: 'test.css'}).catch((e) => console.error(e.toString()));
827
828// CssSyntaxError: classValidator: ./test.css:1:5: classes may not have underscores or dashes in them
829//
830// > 1 | .foo-bar {
831// | ^
832// 2 | color: red;
833// 3 | }
834```
835
836#### Synchronous Error Example
837
838```js
839let processor = (root) => {
840 root.walkClasses((classNode) => {
841 if (/.*[-_]/.test(classNode.value)) {
842 let msg = "classes may not have underscores or dashes in them";
843 throw root.error(msg, {
844 index: classNode.sourceIndex,
845 word: classNode.value
846 });
847 }
848 });
849};
850
851const postcss = require("postcss");
852const parser = require("postcss-selector-parser");
853const selectorProcessor = parser(processor);
854const plugin = postcss.plugin('classValidator', (options) => {
855 return (root) => {
856 root.walkRules(rule => {
857 selectorProcessor.processSync(rule);
858 });
859 };
860});
861postcss(plugin()).process(`
862.foo-bar {
863 color: red;
864}
865`.trim(), {from: 'test.css'}).catch((e) => console.error(e.toString()));
866
867// CssSyntaxError: classValidator: ./test.css:1:5: classes may not have underscores or dashes in them
868//
869// > 1 | .foo-bar {
870// | ^
871// 2 | color: red;
872// 3 | }
873```
Note: See TracBrowser for help on using the repository browser.