CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
1# API Documentation2 3*Please use only this documented API when working with the parser. Methods4not documented here are subject to change at any point.*5 6## `parser` function7 8This is the module's main entry point.9 10```js11const parser = require('postcss-selector-parser');12```13 14### `parser([transform], [options])`15 16Creates a new `processor` instance17 18```js19const processor = parser();20```21 22Or, with optional transform function23 24```js25const transform = selectors => {26    selectors.walkUniversals(selector => {27        selector.remove();28    });29};30 31const processor = parser(transform)32 33// Example34const result = processor.processSync('*.class');35// => .class36```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```js50parser.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```js63parser.className({value: 'button'});64// => .button65```66 67Arguments:68 69* `props (object)`: The new node's properties.70 71### `parser.combinator([props])`72 73Creates a new selector combinator.74 75```js76parser.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 the86  parser always just a single space (`" "`). For descendant selectors with no87  comments, additional space is now stored in `node.spaces.before`. Depending88  on the location of comments, additional spaces may be stored in89  `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. The92  `node.value` is name after being unescaped and normalized as lowercase. The93  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```js101parser.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```js114parser.id({value: 'search'});115// => #search116```117 118Arguments:119 120* `props (object)`: The new node's properties.121 122### `parser.nesting([props])`123 124Creates a new nesting selector.125 126```js127parser.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```js140parser.pseudo({value: '::before'});141// => ::before142```143 144Arguments:145 146* `props (object)`: The new node's properties.147 148### `parser.root([props])`149 150Creates a new root node.151 152```js153parser.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```js166parser.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```js179parser.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```js192parser.tag({value: 'button'});193// => button194```195 196Arguments:197 198* `props (object)`: The new node's properties.199 200### `parser.universal([props])`201 202Creates a new universal selector.203 204```js205parser.universal();206// => *207```208 209Arguments:210 211* `props (object)`: The new node's properties.212 213## Node types214 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 for221example you can get `id` by querying `parser.ID`.222 223```js224parser.attribute({attribute: 'href'}).type;225// => 'attribute'226```227 228### `node.parent`229 230Returns the parent node.231 232```js233root.nodes[0].parent === root;234```235 236### `node.toString()`, `String(node)`, or `'' + node`237 238Returns a string representation of the node.239 240```js241const id = parser.id({value: 'search'});242console.log(String(id));243// => #search244```245 246### `node.next()` & `node.prev()`247 248Returns the next/previous child of the parent node.249 250```js251const 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```js262const 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```js276if (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 the284original might have had.285 286```js287const cloned = parser.id({value: 'search'});288String(cloned);289 290// => #search291```292 293### `node.isAtPosition(line, column)`294 295Return a `boolean` indicating whether this node includes the character at the296position of the given line and column. Returns `undefined` if the nodes lack297sufficient 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` and307`node.spaces.after`. So for example, these spaces will be moved as they have308no semantic meaning:309 310```css311      h1     ,     h2   {}312```313 314For descendent selectors, the value is always a single space.315 316```css317h1        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```css329.foo,330  .bar {}331```332 333... will contain the following `source` object.334 335```js336source: {337    start: {338        line: 2,339        column: 3340    },341    end: {342        line: 2,343        column: 6344    }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```css355.foo, .bar, .baz {}356```357 358## Container types359 360The `root`, `selector`, and `pseudo` nodes have some helper methods for working361with their children.362 363### `container.nodes`364 365An array of the container's children.366 367```js368// Input: h1 h2369selectors.at(0).nodes.length   // => 3370selectors.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```js379selector.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```js388selector.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```js401selector.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```js414selector.index(selector.nodes[2]) // => 2415```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```js426container.length === container.nodes.length427```428 429### `container` Array iterators430 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; recursive441iteration 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```js449let 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 adding459or 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 are469`container` types.470 471```js472selectors.walk((selector, index) => {473    // all nodes474});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` proxies486 487The container class provides proxy methods for iterating over types of nodes,488so that it is easier to write modules that target specific selectors. Those489methods 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` from504a callback. It returns an array of arrays, where each inner array corresponds505to the groups that you created via the callback.506 507```js508// (input) => h1 h2>>h3509const 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 set524the parent property of the node to this container.525 526```js527const 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```js540selectors.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 use556`node.remove()` if you would like to remove just a single node.557 558```js559selector.length // => 2560selector.remove(id)561selector.length // => 1;562id.parent       // undefined563```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```js574selector.removeAll();575selector.length // => 0576```577 578## Root nodes579 580A root node represents a comma separated list of selectors. Indeed, all581a 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 to587support parsing of legacy CSS hacks.588 589## Selector nodes590 591A selector node represents a single complex selector. For example, this592selector string `h1 h2 h3, [href] > p`, is represented as two selector nodes.593It has no special functionality of its own.594 595## Pseudo nodes596 597A pseudo selector extends a container node; if it has any parameters of its598own (such as `h1:not(h2, h3)`), they will be its children. Note that the pseudo599`value` will always contain the colons preceding the pseudo identifier. This600is so that both `:before` and `::before` are properly represented in the AST.601 602## Attribute nodes603 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```css610[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 the623 start of the node of the output string. This is useful in raising624 error messages about a specific part of the attribute, especially625 in combination with `attribute.sourceIndex`.626 627 Returns `-1` if the name is invalid or the value doesn't exist in this628 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 name635 * `"attributeNS"` - the start of the attribute or its namespace636 * `"operator"` - the match operator of the attribute637 * `"value"` - The value (string or identifier)638 * `"insensitive"` - the case insensitivity flag639 640### `attribute.raws.unquoted`641 642Returns the unquoted content of the attribute's value.643Remains `undefined` if there is no attribute value.644 645```css646[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 spaces655around the element, the parts of the attribute can also have spaces before656and after them. The for each of `attribute`, `operator`, `value` and657`insensitive` there is corresponding property of the same nam in658`node.spaces` that has an optional `before` or `after` string containing only659whitespace.660 661Note that corresponding values in `attributes.raws.spaces` contain values662including any comments. If set, these values will override the663`attribute.spaces` value. Take care to remove them if changing664`attribute.spaces`.665 666### `attribute.raws`667 668The raws object stores comments and other information necessary to re-render669the 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 attribute675then 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 the680raws 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```js685{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 postcss716  `Rule` node instead of a string, then that Rule's selector is updated717  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 selector724will be updated with the resulting string.725 726**Example:**727 728```js729const parser = require("postcss-selector-parser");730const processor = parser();731 732let result = processor.processSync(' .class');733console.log(result);734// =>  .class735 736// Asynchronous operation737let promise = processor.process(' .class').then(result => {738    console.log(result)739    // => .class740});741 742// To have the parser normalize whitespace values, utilize the options743result = processor.processSync('  .class  ', {lossless: false});744console.log(result);745// => .class746 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,.class753    console.log("rule:", rule.selector);754    // => rule: #foo>a,.class755})756```757 758Arguments:759 760* `selectors (string|postcss.Rule)`: Either a selector string or a PostCSS Rule761  node.762* `[options] (object)`: Process options763 764 765### `ast|astSync(selectors, [options])`766 767Like `process()` and `processSync()` but after768processing the `selectors` these methods return the `Root` node of the result769instead of a string.770 771Note: when the `updateSelector` option is set, the rule's selector772will be updated with the resulting string.773 774### `transform|transformSync(selectors, [options])`775 776Like `process()` and `processSync()` but after777processing the `selectors` these methods return the value returned by the778processor callback.779 780Note: when the `updateSelector` option is set, the rule's selector781will be updated with the resulting string.782 783### Error Handling Within Selector Processors784 785The root node passed to the selector processor callback786has a method `error(message, options)` that returns an787error object. This method should always be used to raise788errors relating to the syntax of selectors. The options789to this method are passed to postcss's error constructor790([documentation](http://api.postcss.org/Container.html#error)).791 792#### Async Error Example793 794```js795let 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.value803                }));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 them829//830// > 1 | .foo-bar {831//     |     ^832//   2 |   color: red;833//   3 | }834```835 836#### Synchronous Error Example837 838```js839let 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.value846            });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 them868//869// > 1 | .foo-bar {870//     |     ^871//   2 |   color: red;872//   3 | }873```874