{"id":20129356,"url":"https://github.com/ryanmorr/sonic","last_synced_at":"2025-04-09T16:09:52.036Z","repository":{"id":70575152,"uuid":"64800587","full_name":"ryanmorr/sonic","owner":"ryanmorr","description":"A modern, context-aware, and extendable CSS selector engine built on top of querySelectorAll","archived":false,"fork":false,"pushed_at":"2024-06-18T15:46:14.000Z","size":395,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T16:09:40.766Z","etag":null,"topics":["dom","javascript","selector"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryanmorr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2016-08-03T00:02:28.000Z","updated_at":"2024-06-18T15:46:11.000Z","dependencies_parsed_at":null,"dependency_job_id":"f6f486a4-f522-46a2-9d6d-252fac797aad","html_url":"https://github.com/ryanmorr/sonic","commit_stats":{"total_commits":79,"total_committers":1,"mean_commits":79.0,"dds":0.0,"last_synced_commit":"9c555639cd223118c7c83457cad54689bc98b3eb"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fsonic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fsonic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fsonic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryanmorr%2Fsonic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryanmorr","download_url":"https://codeload.github.com/ryanmorr/sonic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065283,"owners_count":21041871,"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","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":["dom","javascript","selector"],"created_at":"2024-11-13T20:33:51.639Z","updated_at":"2025-04-09T16:09:52.013Z","avatar_url":"https://github.com/ryanmorr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sonic\n\n[![Version Badge][version-image]][project-url]\n[![License][license-image]][license-url]\n[![Build Status][build-image]][build-url]\n\n\u003e A modern, context-aware, and extendable CSS selector engine built on top of `querySelectorAll`.\n\n## Install\n\nDownload the [CJS](https://github.com/ryanmorr/sonic/raw/master/dist/cjs/sonic.js), [ESM](https://github.com/ryanmorr/sonic/raw/master/dist/esm/sonic.js), [UMD](https://github.com/ryanmorr/sonic/raw/master/dist/umd/sonic.js) versions or install via NPM:\n\n``` sh\nnpm install @ryanmorr/sonic\n```\n\n## Usage\n\nFind a single element:\n\n``` javascript\nimport { find } from '@ryanmorr/sonic';\n\n// Returns the matching element or null if no match is found\nconst element = find('#container');\n```\n\nQuery for multiple elements:\n\n``` javascript\nimport { query } from '@ryanmorr/sonic';\n\n// Returns an array of all matching elements\nconst elements = query('.items');\n```\n\nCheck if an element matches a selector string:\n\n``` javascript\nimport { is } from '@ryanmorr/sonic';\n\nconst isMatch = is(element, 'div.class[attr=value]');\n```\n\nProvide an element or selector string as an optional second argument as the root of the query:\n\n``` javascript\nconst element = find('[attr]', element);\nconst elements = query(':first-child', '#header');\n```\n\nUse leading combinators:\n\n``` javascript\nconst divs = query('\u003e div');\nconst blocks = query('+ .block');\nconst checked = query('~ :checked');\n```\n\nExtend by creating custom pseudo-class selectors (must return a boolean):\n\n``` javascript\nimport { find, query, pseudos } from '@ryanmorr/sonic';\n\npseudos.foo = (element) =\u003e {\n    return element.hasAttribute('foo');\n};\n\npseudos.bar = (element, value) =\u003e {\n    return element.hasAttribute(value);\n};\n\nconst element = find(':foo');\nconst elements = query(':bar(class)');\n```\n\n## Context-Aware\n\nSonic addresses the long-standing flaw in `querySelector` and `querySelectorAll` that sees element-rooted queries search relative to the document and not the element itself:\n\n``` html\n\u003csection id=\"container\"\u003e\n    \u003cem\u003eLevel 1\u003c/em\u003e\n    \u003csection\u003e\n        \u003cem\u003eLevel 2\u003c/em\u003e\n    \u003c/section\u003e\n\u003c/section\u003e\n```\n\n``` javascript\n// Expected \u003cem\u003eLevel 2\u003c/em\u003e, but returns \u003cem\u003eLevel 1\u003c/em\u003e, doh!\ndocument.querySelector('#container').querySelector('section em');\n```\n\nApparently, this behavior is purported to be correct given how long it has endured. Sonic, on the other hand, abides by the principle of least surprise and gives you exactly what you expect.\n\n``` javascript\n// Returns \u003cem\u003eLevel 2\u003c/em\u003e as expected, hooray!\nconst elements = query('section em', '#container');\n```\n\n## License\n\nThis project is dedicated to the public domain as described by the [Unlicense](http://unlicense.org/).\n\n[project-url]: https://github.com/ryanmorr/sonic\n[version-image]: https://img.shields.io/github/package-json/v/ryanmorr/sonic?color=blue\u0026style=flat-square\n[build-url]: https://github.com/ryanmorr/sonic/actions\n[build-image]: https://img.shields.io/github/actions/workflow/status/ryanmorr/sonic/node.js.yml?style=flat-square\n[license-image]: https://img.shields.io/github/license/ryanmorr/sonic?color=blue\u0026style=flat-square\n[license-url]: UNLICENSE","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanmorr%2Fsonic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryanmorr%2Fsonic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryanmorr%2Fsonic/lists"}