{"_id":"selderee","_rev":"3970163","name":"selderee","description":"Selectors decision tree - choose matching selectors, fast","dist-tags":{"latest":"0.11.0"},"maintainers":[{"name":"killy.mxi","email":""}],"time":{"modified":"2025-09-01T01:55:52.000Z","created":"2021-05-06T14:25:20.370Z","0.11.0":"2023-02-23T19:53:15.635Z","0.10.0":"2022-12-02T19:03:55.216Z","0.9.0":"2022-02-03T22:41:09.631Z","0.8.1":"2021-12-06T17:08:11.270Z","0.8.0":"2021-12-05T21:44:56.871Z","0.7.0":"2021-11-10T23:05:09.589Z","0.6.0":"2021-05-10T16:57:14.798Z","0.5.0":"2021-05-06T14:25:20.370Z"},"users":{},"author":{"name":"KillyMXI"},"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"versions":{"0.11.0":{"name":"selderee","version":"0.11.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","typedocMain":"./src/selderee.ts","sideEffects":false,"scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.12.0"},"_id":"selderee@0.11.0","_nodeVersion":"14.20.0","_npmVersion":"6.14.17","dist":{"shasum":"6af0c7983e073ad3e35787ffe20cefd9daf0ec8a","size":9695,"noattachment":false,"key":"/selderee/-/selderee-0.11.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.11.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.11.0_1677181995433_0.9286500989388797"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2023-02-23T19:53:15.635Z","publish_time":1677181995635,"_cnpm_publish_time":1677181995635},"0.10.0":{"name":"selderee","version":"0.10.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","typedocMain":"./src/selderee.ts","sideEffects":false,"scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.11.0"},"_id":"selderee@0.10.0","_nodeVersion":"14.20.0","_npmVersion":"6.14.17","dist":{"shasum":"ec83d6044d9026668dc9bd2561acfde99a4e3a1c","size":9666,"noattachment":false,"key":"/selderee/-/selderee-0.10.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.10.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.10.0_1670007834940_0.5202512844788336"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2022-12-02T19:04:07.599Z","publish_time":1670007835216,"_cnpm_publish_time":1670007835216},"0.9.0":{"name":"selderee","version":"0.9.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","typedocMain":"./src/selderee.ts","sideEffects":false,"scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.10.0"},"gitHead":"af663f6947d2661e3f39471b4ef1976eca779cd6","_id":"selderee@0.9.0","_nodeVersion":"12.22.7","_npmVersion":"7.24.2","dist":{"shasum":"31b5d7b4dac0a51bb2bbfeaf5487ac2ce1604fa4","size":9187,"noattachment":false,"key":"/selderee/-/selderee-0.9.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.9.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.9.0_1643928069495_0.9741988475371555"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2022-02-03T22:41:21.754Z","publish_time":1643928069631,"_cnpm_publish_time":1643928069631},"0.8.1":{"name":"selderee","version":"0.8.1","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","sideEffects":false,"scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.9.1"},"_id":"selderee@0.8.1","_nodeVersion":"12.22.6","_npmVersion":"6.14.15","dist":{"shasum":"994681a5a144c191699433e34639d48c49c8ddf3","size":9539,"noattachment":false,"key":"/selderee/-/selderee-0.8.1.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.8.1.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.8.1_1638810491110_0.21670678463912307"},"_hasShrinkwrap":false,"publish_time":1638810491270,"_cnpm_publish_time":1638810491270,"_cnpmcore_publish_time":"2021-12-16T16:17:41.049Z"},"0.8.0":{"name":"selderee","version":"0.8.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","sideEffects":false,"scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.9.0"},"_id":"selderee@0.8.0","_nodeVersion":"12.22.6","_npmVersion":"6.14.15","dist":{"shasum":"9b9290171c675b16945476333fd99483e41e7329","size":9195,"noattachment":false,"key":"/selderee/-/selderee-0.8.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.8.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.8.0_1638740696734_0.9248772880487899"},"_hasShrinkwrap":false,"publish_time":1638740696871,"_cnpm_publish_time":1638740696871,"_cnpmcore_publish_time":"2021-12-16T16:17:41.255Z"},"0.7.0":{"name":"selderee","version":"0.7.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.8.0"},"_id":"selderee@0.7.0","_nodeVersion":"12.22.6","_npmVersion":"6.14.15","dist":{"shasum":"bd5a30c989e2238bc17fc1a18623aecd7526f2bb","size":9548,"noattachment":false,"key":"/selderee/-/selderee-0.7.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.7.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.7.0_1636585509407_0.6024082943777067"},"_hasShrinkwrap":false,"publish_time":1636585509589,"_cnpm_publish_time":1636585509589,"_cnpmcore_publish_time":"2021-12-16T16:17:41.553Z"},"0.6.0":{"name":"selderee","version":"0.6.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.7.0"},"_id":"selderee@0.6.0","_nodeVersion":"10.23.2","_npmVersion":"7.11.2","dist":{"shasum":"f3bee66cfebcb6f33df98e4a1df77388b42a96f7","size":9382,"noattachment":false,"key":"/selderee/-/selderee-0.6.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.6.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.6.0_1620665834651_0.6650116888104542"},"_hasShrinkwrap":false,"publish_time":1620665834798,"_cnpm_publish_time":1620665834798,"_cnpmcore_publish_time":"2021-12-16T16:17:41.864Z"},"0.5.0":{"name":"selderee","version":"0.5.0","description":"Selectors decision tree - choose matching selectors, fast","keywords":["CSS","selectors","decision tree","match"],"repository":{"type":"git","url":"git+https://github.com/mxxii/selderee.git"},"bugs":{"url":"https://github.com/mxxii/selderee/issues"},"homepage":"https://github.com/mxxii/selderee","author":{"name":"KillyMXI"},"funding":"https://ko-fi.com/killymxi","license":"MIT","exports":{"import":"./lib/selderee.mjs","require":"./lib/selderee.cjs"},"type":"module","main":"./lib/selderee.cjs","module":"./lib/selderee.mjs","types":"./lib/selderee.d.ts","scripts":{"build:rollup":"rollup -c","build:types":"tsc -d --emitDeclarationOnly --declarationDir ./lib","build":"npm run clean && npm run build:rollup && npm run build:types","clean":"rimraf lib"},"dependencies":{"parseley":"^0.7.0"},"_id":"selderee@0.5.0","_nodeVersion":"10.24.1","_npmVersion":"6.14.12","dist":{"shasum":"061742d5fbf9fb77d9bb3a8c85ad3a3ee4b6fd40","size":8779,"noattachment":false,"key":"/selderee/-/selderee-0.5.0.tgz","tarball":"http://registry.cnpm.dingdandao.com/selderee/download/selderee-0.5.0.tgz"},"_npmUser":{"name":"killy.mxi","email":"killy.mxi@gmail.com"},"directories":{},"maintainers":[{"name":"killy.mxi","email":""}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/selderee_0.5.0_1620311120244_0.8434911105664527"},"_hasShrinkwrap":false,"publish_time":1620311120370,"_cnpm_publish_time":1620311120370,"_cnpmcore_publish_time":"2021-12-16T16:17:42.289Z"}},"readme":"# selderee\n\n![lint status badge](https://github.com/mxxii/selderee/workflows/lint/badge.svg)\n![test status badge](https://github.com/mxxii/selderee/workflows/test/badge.svg)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/mxxii/selderee/blob/main/LICENSE)\n[![npm](https://img.shields.io/npm/dw/selderee?color=informational&logo=npm)](https://www.npmjs.com/package/selderee)\n\n**Sel**ectors **de**cision t**ree** - pick matching selectors, fast.\n\n----\n\n\n## What is it for\n\nThe problem statement: there are multiple CSS selectors with attached handlers, and a HTML DOM to process. For each HTML Element a matching handler has to be found and applied.\n\nThe naive approach is to walk through the DOM and test each and every selector against each Element. This means *O(n\\*m)* complexity.\n\nIt is pretty clear though that if we have selectors that share something in common then we can reduce the number of checks.\n\nThe main `selderee` package offers the selectors tree structure. Runnable decision functions for specific DOM implementations are built via plugins.\n\n\n## Limitations\n\n- Pseudo-classes and pseudo-elements are not supported by the underlying library [parseley](https://github.com/mxxii/parseley) (yet?);\n- General siblings (`~`), descendants (` `) and same column combinators (`||`) are also not supported.\n\n\n## `selderee` vs `css-select`\n\n[css-select](https://github.com/fb55/css-select) - a CSS selector compiler & engine.\n\n| Feature                               | `selderee` | `css-select` |\n| ------------------------------------- | :--------: | :----------: |\n| Support for `htmlparser2` DOM AST     | plugin     | +            |\n| \"Compiles\" into a function            | +          | +            |\n| Pick selector(s) for a given Element  | +          |              |\n| Query Element(s) for a given selector |            | +            |\n\n\n## Packages\n\n| Package   | Version   | Folder    | Changelog |\n| --------- | --------- | --------- | --------- |\n| [selderee](https://www.npmjs.com/package/selderee) | [![npm](https://img.shields.io/npm/v/selderee?logo=npm)](https://www.npmjs.com/package/selderee) | [/packages/selderee](https://github.com/mxxii/selderee/tree/main/packages/selderee/) | [changelog](https://github.com/mxxii/selderee/blob/main/packages/selderee/CHANGELOG.md) |\n| [@selderee/plugin-htmlparser2](https://www.npmjs.com/package/@selderee/plugin-htmlparser2) | [![npm](https://img.shields.io/npm/v/@selderee/plugin-htmlparser2?logo=npm)](https://www.npmjs.com/package/@selderee/plugin-htmlparser2) | [/packages/plugin-htmlparser2](https://github.com/mxxii/selderee/tree/main/packages/plugin-htmlparser2/) | [changelog](https://github.com/mxxii/selderee/blob/main/packages/plugin-htmlparser2/CHANGELOG.md) |\n\n\n## Install\n\n```shell\n> npm i selderee @selderee/plugin-htmlparser2\n```\n\n\n## Documentation\n\n- [API](https://github.com/mxxii/selderee/blob/main/docs/index.md)\n\n\n## Usage example\n\n```js\nconst htmlparser2 = require('htmlparser2');\nconst util = require('util');\n\nconst { DecisionTree, Treeify } = require('selderee');\nconst { hp2Builder } = require('@selderee/plugin-htmlparser2');\n\nconst selectorValuePairs = [\n  ['p', 'A'],\n  ['p.foo[bar]', 'B'],\n  ['p[class~=foo]', 'C'],\n  ['div.foo', 'D'],\n  ['div > p.foo', 'E'],\n  ['div > p', 'F'],\n  ['#baz', 'G']\n];\n\n// Make a tree structure from all given selectors.\nconst selectorsDecisionTree = new DecisionTree(selectorValuePairs);\n\n// `treeify` builder produces a string output for testing and debug purposes.\n// `treeify` expects string values attached to each selector.\nconst prettyTree = selectorsDecisionTree.build(Treeify.treeify);\nconsole.log(prettyTree);\n\nconst html = /*html*/`<html><body>\n  <div><p class=\"foo qux\">second</p></div>\n</body></html>`;\nconst dom = htmlparser2.parseDocument(html);\nconst element = dom.children[0].children[0].children[1].children[0];\n\n// `hp2Builder` produces a picker that can pick values\n// from the selectors tree.\nconst picker = selectorsDecisionTree.build(hp2Builder);\n\n// Get all matches\nconst allMatches = picker.pickAll(element);\nconsole.log(util.inspect(allMatches, { breakLength: 70, depth: null }));\n\n// or get the value from the most specific match.\nconst bestMatch = picker.pick1(element);\nconsole.log(`Best matched value: ${bestMatch}`);\n```\n\n<details><summary>Example output</summary>\n\n```text\n▽\n├─◻ Tag name\n│ ╟─◇ = p\n│ ║ ┠─▣ Attr value: class\n│ ║ ┃ ╙─◈ ~= \"foo\"\n│ ║ ┃   ┠─◨ Attr presence: bar\n│ ║ ┃   ┃ ┖─◁ #1 [0,2,1] B\n│ ║ ┃   ┠─◁ #2 [0,1,1] C\n│ ║ ┃   ┖─◉ Push element: >\n│ ║ ┃     └─◻ Tag name\n│ ║ ┃       ╙─◇ = div\n│ ║ ┃         ┖─◁ #4 [0,1,2] E\n│ ║ ┠─◁ #0 [0,0,1] A\n│ ║ ┖─◉ Push element: >\n│ ║   └─◻ Tag name\n│ ║     ╙─◇ = div\n│ ║       ┖─◁ #5 [0,0,2] F\n│ ╙─◇ = div\n│   ┖─▣ Attr value: class\n│     ╙─◈ ~= \"foo\"\n│       ┖─◁ #3 [0,1,1] D\n└─▣ Attr value: id\n  ╙─◈ = \"baz\"\n    ┖─◁ #6 [1,0,0] G\n[ { index: 2, value: 'C', specificity: [ 0, 1, 1 ] },\n  { index: 4, value: 'E', specificity: [ 0, 1, 2 ] },\n  { index: 0, value: 'A', specificity: [ 0, 0, 1 ] },\n  { index: 5, value: 'F', specificity: [ 0, 0, 2 ] } ]\nBest matched value: E\n```\n\n*Some gotcha: you may notice the check for `#baz` has to be performed every time the decision tree is called. If it happens to be `p#baz` or `div#baz` or even `.foo#baz` - it would be much better to write it like this. Deeper, narrower tree means less checks on average. (in case of `.foo#baz` the class check might finally outweigh the tag name check and rebalance the tree.)*\n\n</details>\n\n\n## Development\n\nTargeting Node.js version >=14.\n\nMonorepo uses NPM v7 workspaces (make sure v7 is installed when used with Node.js v14.)\n","_attachments":{},"homepage":"https://github.com/mxxii/selderee","bugs":{"url":"https://github.com/mxxii/selderee/issues"},"license":"MIT"}