{"id":17678675,"url":"https://github.com/eprev/specificity","last_synced_at":"2025-10-26T02:07:40.834Z","repository":{"id":24217449,"uuid":"27609468","full_name":"eprev/specificity","owner":"eprev","description":"CSS Explorer","archived":false,"fork":false,"pushed_at":"2015-05-28T19:28:19.000Z","size":1512,"stargazers_count":22,"open_issues_count":8,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-23T22:41:59.177Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/eprev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-05T20:47:02.000Z","updated_at":"2020-01-11T08:41:19.000Z","dependencies_parsed_at":"2022-09-02T23:31:42.347Z","dependency_job_id":null,"html_url":"https://github.com/eprev/specificity","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/eprev/specificity","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eprev%2Fspecificity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eprev%2Fspecificity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eprev%2Fspecificity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eprev%2Fspecificity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eprev","download_url":"https://codeload.github.com/eprev/specificity/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eprev%2Fspecificity/sbom","scorecard":{"id":379225,"data":{"date":"2025-08-11","repo":{"name":"github.com/eprev/specificity","commit":"530f75d2790dfe7dd0102dc568e25e7aafc85592"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T14:59:43.211Z","repository_id":24217449,"created_at":"2025-08-18T14:59:43.212Z","updated_at":"2025-08-18T14:59:43.212Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281047743,"owners_count":26435124,"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-10-26T02:00:06.575Z","response_time":61,"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":[],"created_at":"2024-10-24T08:05:27.916Z","updated_at":"2025-10-26T02:07:40.812Z","avatar_url":"https://github.com/eprev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Specificity [![Build Status](https://travis-ci.org/eprev/specificity.svg?branch=master)](https://travis-ci.org/eprev/specificity) [![NPM Version](https://img.shields.io/npm/v/node-specificity.svg?style=flat)](https://www.npmjs.org/package/node-specificity)\n\nExplore your CSS through visualization! Specificity parses your CSS files, collects information about selectors specificity and saves it as profiles. You can use different reports to explore these profiles or write your own.\n\n## Using\n\nInstalling:\n\n```\n$ npm install -g node-specificity\n```\n\nSpecificy provides the following commands:\n\n* Firstly, you need to create a profile. Run `parse` command to create it and specify one or more CSS files. Profile is a regular JSON file (you can see its structure below).\n* Next, since you have created the profile, you can explore it by using `explore` command. You just need to specify the report.\n\n* And finally, you might be interested in running queries against the selectors. For instance, which selectors have specificity higher than `1,0,0`. So, there is the `query` command.\n\nIf you type `node-specificity parse --help`, `node-specificty explore --help` or `node-specificty query --help` you will get some usage examples.\n\nSpecificity supports the following reports: `inspect` (is used by default), `server` and `json`.\n\n### `inspect`\n\nPrints the list of selectors, specificity, using of `!important` directive and location of selectors in the file. Prints max, min, average and median values of specificity in the summary. Outputs the specificty distribution histogram.\n\n### `server`\n\nStarts a local web server that allows you to explore the specified profiles in any browser.\n\n![](docs/server-distribution.png)\n\n### `json`\n\nPrints out the contents of the profile.\n\n### Example\n\nIn the example below `specificity` creates a profile and outputs it to the standart input of another `specificty` process that prints out the default report results.\n\n```\n$ pwd\n/deploy/static/\n\n$ node-specificity parse --directory=css **/*.css | node-specificity explore -\nFile: -\n\n  Working directory: /deploy/static/css\n\n  ┌───────────────────────────────────────────────────┬─────────────┬───┬────────────────┐\n  │ selector                                          │ specificity │ ! │ location       │\n  ├───────────────────────────────────────────────────┼─────────────┼───┼────────────────┤\n  │ h5                                                │       0,0,1 │ 0 │ main.css:117   │\n  │ input                                             │       0,0,1 │ 0 │ main.css:11    │\n  │ h6                                                │       0,0,1 │ 0 │ main.css:122   │\n  │ body                                              │       0,0,1 │ 0 │ main.css:6     │\n  ...\n  │ .post__content pre .smalltalk .class              │       0,3,1 │ 0 │ main.css:422   │\n  │ .post__content pre .clojure .attribute            │       0,3,1 │ 0 │ main.css:468   │\n  │ .post__content pre .rules .value .number          │       0,4,1 │ 0 │ main.css:422   │\n  │ .post__content pre .ruby .symbol .string          │       0,4,1 │ 0 │ main.css:422   │\n  └───────────────────────────────────────────────────┴─────────────┴───┴────────────────┘\n\n  ┌─────┬────────────────┬────────┬────────┬────────┬────────┐\n  │     │    specificity │      a │      b │      c │      ! │\n  ├─────┼────────────────┼────────┼────────┼────────┼────────┤\n  │ max │          0,4,1 │      0 │      4 │      3 │      0 │\n  │ avg │    0,1.71,0.85 │      0 │   1.71 │   0.85 │      0 │\n  │ med │          0,2,1 │      0 │      2 │      1 │      0 │\n  └─────┴────────────────┴────────┴────────┴────────┴────────┘\n\n  0,0,1 | ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙                       | 32\n  0,0,2 | ∙                                                            | 1\n  0,0,3 | ∙                                                            | 1\n  0,1,0 | ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙                         | 30\n  0,1,1 | ∙∙                                                           | 2\n  0,1,2 | ∙∙∙∙                                                         | 3\n  0,2,0 | ∙∙                                                           | 2\n  0,2,1 | ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙      | 46\n  0,3,1 | ∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙ | 50\n  0,4,1 | ∙∙                                                           | 2\n```\n\n## Profile structure\n\nSpecificity parses your CSS files and collects information about selectors specificity. As a result you get JSON with the following structure:\n\n```js\n{\n    files: {\n        '*': FILE,   // Container of the specific file. Pseudo-file '*' refers to the data of all files.\n        'main.css': FILE,\n        /* ... */\n        'print.css': FILE,\n    },\n    options: {\n        cwd  : '/deploy/static/css', // Working directory. All files have names relative to this directory.\n        label: '2014-12', // You can assign an arbitrary label to each profile.\n        uniqueSelectors: false // If set to True, then the profile doesn't contain repeating selectors.\n    }\n}\n```\n\n`FILE`’s structure:\n\n```js\n{\n    series: SERIES // Sorted out selectors by their specificity\n    important: {   // Using of `!important` directive\n        min: 0,    // Min value (number of selector)\n        max: 0,    // Max value (number of selector)\n        avg: 0,    // Average value (number of selector)\n        med: 0     // Median (number of selector)\n    },\n    weight_a: {    // Using of IDs in selectors\n        /* --//-- */\n    },\n    weight_b: {    // Using of classes, pseudo-classes and attributes in selectors\n        /* --//-- */\n    },\n    weight_c: {    // Using of elements and pseudo-elements in selectors\n        /* --//-- */\n    },\n    weight:  {     // Contains min, max, average and median specificity\n        /* --//-- */\n    },\n    distrib: { // Specificity distribution (specificity =\u003e number of selectors)\n        '0,0,1': 1,\n        '0,0,2': 1,\n        '0,1,0': 1,\n        /* ... */\n        '1,0,0': 1,\n        '2,3,3': 1\n    }\n}\n```\n\n`SERIES` is an array of objects:\n\n```js\n{\n    selector: 'a', // Selector\n    important: 0,  // Number of its rules with the `!important` directive\n    weight: [ 0, 0, 1 ], // It’s specificity\n    file: 'main.css',    // Name of the file where this selector has been found\n    start: { line: 1, column: 1 }, // Start offset within the file\n    end: { line: 1, column: 4 } }  // End offset\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feprev%2Fspecificity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feprev%2Fspecificity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feprev%2Fspecificity/lists"}