{"id":15687170,"url":"https://github.com/danburzo/selery","last_synced_at":"2025-08-02T16:04:28.915Z","repository":{"id":56353382,"uuid":"309950632","full_name":"danburzo/selery","owner":"danburzo","description":"A CSS selector parser and DOM query engine.","archived":false,"fork":false,"pushed_at":"2024-05-07T19:41:22.000Z","size":235,"stargazers_count":9,"open_issues_count":7,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-28T06:37:25.714Z","etag":null,"topics":["ast","css","css-selectors","dom-querying","parser"],"latest_commit_sha":null,"homepage":"https://danburzo.ro/selery/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danburzo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-04T09:09:00.000Z","updated_at":"2024-05-07T19:41:25.000Z","dependencies_parsed_at":"2024-10-23T20:36:39.685Z","dependency_job_id":"45ab97ba-8f4e-4ac1-a258-ece3de503d24","html_url":"https://github.com/danburzo/selery","commit_stats":{"total_commits":61,"total_committers":2,"mean_commits":30.5,"dds":"0.016393442622950838","last_synced_commit":"e94f5323d75810b339bdc476e1aad40c388597cd"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/danburzo/selery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danburzo%2Fselery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danburzo%2Fselery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danburzo%2Fselery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danburzo%2Fselery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danburzo","download_url":"https://codeload.github.com/danburzo/selery/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danburzo%2Fselery/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268415858,"owners_count":24246811,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","css","css-selectors","dom-querying","parser"],"created_at":"2024-10-03T17:44:32.413Z","updated_at":"2025-08-02T16:04:28.804Z","avatar_url":"https://github.com/danburzo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![selery](./.github/selery.svg)\n\nSelery is a small, handwritten CSS selector parser and DOM query engine.\n\nIt aims to be compliant with the relevant specifications ([CSS Syntax Module Level 3](https://drafts.csswg.org/css-syntax-3/), [CSS Selectors Level 4](https://drafts.csswg.org/selectors-4/), and others), while remaining compact and understandable so that it can be used as a starting point to experiment with new CSS syntax.\n\nAn online playground is available at [danburzo.ro/selery/](https://danburzo.ro/selery/).\n\n## Getting started\n\n[![selery on npm](https://img.shields.io/npm/v/selery.svg?style=flat-square\u0026labelColor=50B888\u0026color=black)](https://www.npmjs.org/package/selery) [![selery on bundlephobia](https://img.shields.io/bundlephobia/minzip/selery?style=flat-square\u0026labelColor=50B888\u0026color=black)](https://bundlephobia.com/result?p=selery)\n\nYou can install Selery as an [npm package](https://npmjs.com/package/selery):\n\n```bash\nnpm install selery\n```\n\n## API reference\n\n#### tokenize(_selector_)\n\nTakes a string _selector_ and returns an array of tokens.\n\n```js\nlet { tokenize } = require('selery');\n\ntokenize('article a[href=\"#\"]');\n```\n\nA token is a plain object having a `type` property, along with other optional properties, which are documented in the [CSS token reference](#css-token-reference). For the sample selector `'article a[href=\"#\"]'` mentioned above, the resulting token array is:\n\n```js\n[\n\t{ type: 'ident', value: 'article', start: 0, end: 6 },\n\t{ type: 'whitespace', start: 7, end: 7 },\n\t{ type: 'ident', value: 'a', start: 8, end: 8 },\n\t{ type: '[', start: 9, end: 9 },\n\t{ type: 'ident', value: 'href', start: 10, end: 13 },\n\t{ type: 'delim', value: '=', start: 14, end: 14 },\n\t{ type: 'string', value: '#', start: 15, end: 17 },\n\t{ type: ']', start: 18, end: 18 }\n];\n```\n\nThe function will throw an erorr if the selector supplied does not follow generally valid CSS syntax.\n\n#### parse(_input_, _options_)\n\nAccepts an _input_ argument, which can be either an array of tokens obtained from the `tokenize()` function or, more conveniently, a string representing a selector. The latter is passed through `tokenize()` internally.\n\nIt produces an _abstract syntax tree_ (AST), also called a _parse tree_, for the provided input.\n\n```js\nlet { parse } = require('selery');\n\nlet tree = parse('div \u003e span:nth-child(3)');\n```\n\nAvailable options:\n\n**`syntaxes`** (_Object_) — provide custom microsyntaxes to various pseudo-classes and pseudo-elements. By default, the argument of `:nth-*()` pseudo-classes is parsed with the _An+B microsyntax_, while for the `:is()`, `:where()`, `:not()`, and `:has()`, the argument is parsed as a `SelectorList`.\n\nThe keys to the _syntaxes_ object are the identifier for the pseudo-class (prefixed by `:`) or pseudo-element (prefixed by `::`), and the values are either strings (one of `None`, `AnPlusB`, or `SelectorList`) or functions. Function values will receive an array of tokens and can return anything suitable for storing in the AST node's `argument` key.\n\n```js\nparse(':nth-child(3)', {\n\tsyntaxes: {\n\t\t/* Change the microsyntax of a pseudo-class */\n\t\t':nth-child': 'None',\n\n\t\t/* A microsyntax defined as a function */\n\t\t':magic': tokens =\u003e tokens.map(t =\u003e t.value).join('★')\n\t}\n});\n```\n\n#### serialize(_input_)\n\nConverts the input back into a string. The _input_ argument can be either an array of tokens, or an object representing a parse tree.\n\n### DOM API shims\n\nShims for selector-accepting DOM methods using simpler DOM primitives.\n\nAcross these methods:\n\n- the _selector_ argument can be a string (as with their native DOM counterparts), an array of tokens, or an object representing a parse tree;\n- the _options_ object accepts the following keys:\n  - _root_ (Element) — an optional _scoping root_;\n  - _scope_ (Element | Array) — an optional set of _:scope elements_.\n\n#### matches(_element_, _selector_, _options_)\n\nSee the [Element.matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) DOM method.\n\n#### closest(_element_, _selector_, _options_)\n\nSee the [Element.closest](https://developer.mozilla.org/en-US/docs/Web/API/Element/closest) DOM method.\n\n#### querySelector(_element_, _selector_, _options_)\n\nSee the [Element.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector) DOM method.\n\n#### querySelectorAll(_element_, _selector_, _options_)\n\nSee the [Element.querySelectorAll](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll) DOM method. While the native DOM method return a `NodeList`, our implementation of `querySelectorAll` returns an `Array`.\n\n## CSS token reference\n\nThe `tokenize()` function returns an Array of tokens with a `type` property. The list of `type` values is below:\n\n```js\nexport const Tokens = {\n\tAtKeyword: 'at-keyword',\n\tBadString: 'bad-string',\n\tBadUrl: 'bad-url',\n\tBraceClose: '}',\n\tBraceOpen: '{',\n\tBracketClose: ']',\n\tBracketOpen: '[',\n\tCDC: 'cdc',\n\tCDO: 'cdo',\n\tColon: 'colon',\n\tComma: 'comma',\n\tDelim: 'delim',\n\tDimension: 'dimension',\n\tFunction: 'function',\n\tHash: 'hash',\n\tIdent: 'ident',\n\tNumber: 'number',\n\tParenClose: ')',\n\tParenOpen: '(',\n\tPercentage: 'percentage',\n\tSemicolon: 'semicolon',\n\tString: 'string',\n\tUnicodeRange: 'unicode',\n\tUrl: 'url',\n\tWhitespace: 'whitespace'\n};\n```\n\nThe following token types include a `value` property: `at-keyword`, `bad-string`, `bad-url`, `delim`, `dimension`, `function`, `hash`, `ident`, `number`, `percentage`, `string`, `unicode`, `url`.\n\nSome token types may include specific properties:\n\n- `number` and `percentage` include a `sign` property;\n- `dimension` includes `sign` and `unit` properties;\n\nAll tokens include the positional `start` and `end` properties that delimit the token’s locarion in the input string.\n\n## CSS selector AST reference\n\nAll nodes in the AST contain a `type` property, and additional properties for each specific type, listed below.\n\nAll nodes also include the positional `start` and `end` properties that delimit the selector’s location in the input string.\n\n#### `SelectorList`\n\nThe topmost node in the AST.\n\n- `selectors` — an array of (possibly complex) selectors.\n\n#### `ComplexSelector`\n\nA complex selector represents a pair of selectors stringed together with combinators, such as `article \u003e p`.\n\n- `left` — the left-side (possibly complex, or compound) selector; `null` when the selector is relative, such as the `\u003e img` in `a:has(\u003e img)`;\n- `right` — the right-side (possibly complex, compound) selector;\n- `combinator` — one of ` `, `\u003e`, `~`, `+`, `||`\n\nLonger sequences of selectors are represented with nested `ComplexSelector` elements in the AST. For example, `article \u003e p span` is represented as:\n\n```js\n{\n\ttype: 'SelectorList',\n\tselectors: [{\n\t\ttype: 'ComplexSelector',\n\t\tleft: {\n\t\t\ttype: 'ComplexSelector',\n\t\t\tleft: {\n\t\t\t\ttype: 'TypeSelector',\n\t\t\t\tidentifier: 'article'\n\t\t\t},\n\t\t\tright: {\n\t\t\t\ttype: 'TypeSelector',\n\t\t\t\tidentifier: 'p'\n\t\t\t},\n\t\t\tcombinator: ' ',\n\t\t},\n\t\tright: {\n\t\t\ttype: 'TypeSelector',\n\t\t\tidentifier: 'span'\n\t\t},\n\t\tcombinator: ' '\n\t}]\n}\n```\n\n#### `CompoundSelector`\n\nA compound selector is a combination of simple selectors, all of which impose conditions on a single element, such as `a.external[href$=\".pdf\"]`.\n\n- `selectors` — an array of simple selectors.\n\n#### `TypeSelector`\n\nRepresents a type selector, such as `article`.\n\n- `identifier` (String) — the element type to match; can be `*` in the case of the universal selector;\n- `namespace` (String) — the namespace, if provided with the `namespace|type` syntax; an empty string corresponds to the `|type` syntax.\n\n#### `IdSelector`\n\nRepresents an ID selector, such as `#main`.\n\n- `identifier` (String) — the ID to match;\n\n#### `ClassSelector`\n\nRepresents a class selector, such as `.primary`.\n\n- `identifier` (String) — the class name to match;\n\n#### `AttributeSelector`\n\nRepresents an [attribute selector](https://drafts.csswg.org/selectors/#attribute-selectors), such as `[href^=\"http\"]`.\n\n- `identifier` (String) — the attribute to match;\n- `value` (String) — the value to match against;\n- `quotes` (Boolean) — `true` if the value is a string; otherwise absent for brevity;\n- `matcher` (String) — one of `=`, `^=`, `$=`, `*=`, `~=`, `|=`;\n- `modifier` (String) — either `s` or `i`, if any.\n\n#### `PseudoClassSelector` and `PseudoElementSelector`\n\nRepresents a pseudo-class selector (such as `:visited` or `:is(a, b, c)`) or a pseudo-element (such as `::before`), respectively.\n\nBoth types of nodes share a common structure:\n\n- `identifier` (String) — the pseudo-class or pseudo-element;\n- `argument` (Anything) — the argument to the pseudo-class / pseudo-element;\n\nIn CSS, there is more than one way to interpret the argument passed to pseudo-classes and pseudo-elements which expressed with the function notation. Some pseudo-classes, such as `:nth-*()`, use the `An+B microsyntax`, others accept a list of selectors.\n\nYou can control how the microsyntaxes get applied to the pseudo-classes and pseudo-elements with the `syntax` option on the `parse()` method.\n\n## Supported selectors\n\n- [x] [Logical combinations](https://drafts.csswg.org/selectors/#logical-combination) with `:has()`, `:not()`, `:is()`, `:where()` (and their legacy counterparts);\n- [x] [Combinators](https://drafts.csswg.org/selectors/#combinators) `A B`, `A \u003e B`, `A + B`, `A ~ B`, `A || B`, plus any custom combinators passed to `parse()`;\n\n## See also\n\nSelery is planned to power [qsx](https://github.com/danburzo/qsx), the query language based on CSS selectors, and [hred](https://github.com/danburzo/hred), the command-line tool to extract data from HTML and XML.\n\nYou may also want to check out these other CSS parsing projects:\n\n- [LeaVerou/parsel](https://github.com/LeaVerou/parsel)\n- [gajus/scalpel](https://github.com/gajus/scalpel)\n- [csstree/csstree](https://github.com/csstree/csstree)\n- [tabatkins/parse-css](https://github.com/tabatkins/parse-css)\n- [asamuzaK/domSelector](https://github.com/asamuzaK/domSelector)\n\n## Acknowledgements\n\nSelery’s tokenizer is much more robust thanks to the test suite imported from [parse-css](https://github.com/tabatkins/parse-css).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanburzo%2Fselery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanburzo%2Fselery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanburzo%2Fselery/lists"}