{"id":20600970,"url":"https://github.com/hapytex/css-selectors","last_synced_at":"2025-04-15T01:37:15.660Z","repository":{"id":40994406,"uuid":"216409241","full_name":"hapytex/css-selectors","owner":"hapytex","description":"A library for parsing, manipulating, and rendering css selectors (not css files, just the selectors).","archived":false,"fork":false,"pushed_at":"2024-05-07T19:22:02.000Z","size":20890,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-28T13:37:34.301Z","etag":null,"topics":["css-selector","haskell","quasiquoter"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/css-selectors","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hapytex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"custom":"https://www.buymeacoffee.com/hapytex"}},"created_at":"2019-10-20T18:38:10.000Z","updated_at":"2023-07-09T18:20:11.000Z","dependencies_parsed_at":"2024-05-07T20:31:07.676Z","dependency_job_id":"bb33ce1c-d16f-4557-8b05-d04121392f2f","html_url":"https://github.com/hapytex/css-selectors","commit_stats":{"total_commits":163,"total_committers":2,"mean_commits":81.5,"dds":"0.030674846625766916","last_synced_commit":"ece9abedb0b80f66d5bac41442cb519ac3927099"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hapytex%2Fcss-selectors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hapytex%2Fcss-selectors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hapytex%2Fcss-selectors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hapytex%2Fcss-selectors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hapytex","download_url":"https://codeload.github.com/hapytex/css-selectors/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248571867,"owners_count":21126522,"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":["css-selector","haskell","quasiquoter"],"created_at":"2024-11-16T09:07:42.097Z","updated_at":"2025-04-15T01:37:15.642Z","avatar_url":"https://github.com/hapytex.png","language":"Haskell","funding_links":["https://www.buymeacoffee.com/hapytex"],"categories":[],"sub_categories":[],"readme":"# css-selectors\n\n[![Build Status of the package by GitHub actions](https://github.com/hapytex/css-selectors/actions/workflows/build-ci.yml/badge.svg)](https://github.com/hapytex/css-selectors/actions/workflows/build-ci.yml)\n[![Build Status of the package by Hackage](https://matrix.hackage.haskell.org/api/v2/packages/css-selectors/badge)](https://matrix.hackage.haskell.org/#/package/css-selectors)\n[![Hackage version badge](https://img.shields.io/hackage/v/css-selectors.svg)](https://hackage.haskell.org/package/css-selectors)\n\nA library for parsing, manipulating, and rendering css selectors (not css files,\njust the selectors).\n\nIt has a *quasiquoter* to enable Haskell to validate the css selector at compile\ntime.\n\nOne can furthermore calculate the specificity of a css-selector, and thus\nperform an analysis over what css-selector will take precedence.\n\nThe package documentation can be found on the [GitHub pages](https://hapytex.github.io/css-selectors/).\n\n## Selector structure\n\nA css selector has the following structure:\n\n  1. a `SelectorGroup` is a group of one or more `Selector`s, these are\n     *comma-separated*;\n  2. A `Selector` is a custom linked list implementation where the \"cons\" (the\n     `Combined` data constructor) contains a besides a reference to a\n     `PseudoSelectorSequence` (head) and a `Selector` (tail), it specifies what\n     `PseudoSelectorCombinator` is used. A `Selector` has at least one\n     `PseudoSelectorSequence`, this is constructoed with the `Selector` data\n     constructor;\n  3. A `PseudoSelectorSequence` is a `Selector` sequence with an *optional* `PseudoElement`, that\n     pseudo element is written at the end of the `PseudoSelectorSequence` when specified in the CSS\n     selector;\n  4. A `SelectorSequence` contains a `TypeSelector` (in case the `TypeSelector`\n     is `Universal`, this does not need to be part of the css-selector\n     expression); and a set of zero or more `SelectorFilter`s;\n  5. A `SelectorFilter` is a `Hash`, a `Class`, `Attrib`, `PseudoClass`, or a `Negation`;\n  6. Both a `TypeSelector` and an `AttributeName` have a namespace. A namespace\n     can be any (`*`), empty, or a namespace (which should be a valid\n     identifier);\n  7. A `Hash` is a valid identifier prepended with a number sign (`#`);\n  8. A `Class` is a valid identifier prepended with a dot (`.`);\n  9. An `Attribute` can be an `Exist` object that imposes a constraint that the\n     attribute should exist for the given tag, or an `Attrib` that specifies\n     that the attribute exists, and that the value for this attribute satisfies\n     a given constraint. This constraint is determined by the\n     `AttributeCombinator` and the value of the `Attrib` object;\n  10. A `Negation` is written in a css selector with `:not(…)`. It can contain a `TypeSelector`, `Hash`,\n      `Class` or `PseudoClass`, it can *not* contain a nested `:not(…)`.\n  11. A `PseudoClass` is an identifier after a single colon (`:`). Some pseudo classes\n     are functions that are then called with a parameter. For the `:nth-child(…)`, `:nth-last-child(…)`,\n     `:nth-last-of-type(…)`, and `:nth-of-type(…)` these functions take an `Nth` as parameter. This\n     parameter specifies which childs will be selected. The `:lang(…)` pseudo class\n     takes the name of a language, for example `en-US`;\n  12. An `Nth` describes what childs are selected, for example `4n+2`, this is used as a function\n      parameter for the `NthChild`, `NthLastChild`, `NthLastOfType` and `NthOfType` pseudo classes; and\n  13. A `PseudoElement` is an optional item at the end of a `SelectorSequence`. Usually pseudo elements are\n      written with two colons in front, for example `::before` and `::after`. For backwards compatibility,\n      these can also be written as `:before` and `:after`.\n\n## Quasiquoter\n\nThe main use of this package is a *quasiquoter*, that can be used both for\n*expressions* and *patterns*. We thus can construct a `SelectorGroup` in an\nexpression with:\n\n```haskell\nmyCssSelector :: SelectorGroup\nmyCssSelector = [csssel|* html .pun .inbox, * html .pun #bdrdmain, * html .pun .infldset|]\n```\n\nA less common use case is using the quasiquoter in a pattern to check if a given\n`SelectorGroup` matches *exactly* with a given css selector. For example:\n\n```haskell\nisMyCssSelector :: SelectorGroup -\u003e Bool\nisMyCssSelector [csssel|* html .pun .unbox|] = True\nisMyCssSelector _ = False\n```\n\nThe quasiquoter can be used in a type signature as well, but will always,\nregardless of the content, return the type for `SelectorGroup`. If you use the\nquasiquoter as a declaration, it will simply not generate any declarations. It\nwill raise a warning (not an error) about this.\n\nPerhaps in the (far) future, we will make more sensical implementations for the\ntype and declaration part of the quasiquoter.\n\nNote that you need to enable the `-XQuasiQuotes` pragma when you compile.\n\n## Selector normalization\n\nOne can turn equivalent css selectors in a \"normalized\" form. This is done by\nsorting the `Selector`s in a `Selector` group, and sorting the `SelectorFilter`s\nof a certain `SelectorSequence`.\n\nThe order is determined by the default instances of `Ord` of the sequences. This\nis thus not an \"inherent\" ordering of the css selector, but just an order that\nthe program constructed to convert multiple css selectors that are equivalent\nsame to a normal form in which these are equal.\n\nWe here do *not* optimize the css selector, for example by removing duplicate\nfilters, since that can have impact on the specificity of the selector.\n\n## Selector specificity\n\nThe specificity of a selector is defined by three numbers *a*, *b* and *c*.\nLater, one calculates the specificity level with *100 a + 10 b + c*. The higher\nthe specificity level, the more it takes precedence. If there are thus two\nselectors and the former selector has *14* as specificity level, and the latter\nhas *42* as specificity level, then rules defined in the latter, will \"overrule\"\nthe rules defined in the former, given these rules \"clash\".\n\nOne can calculate the specificity of a item with as type a member of the `ToCssSelector`\nclass with:\n\n```haskell\nspecificity :: ToCssSelector a =\u003e a -\u003e Int\n```\n\nor you can obtain a more detailed result with:\n\n```haskell\nspecificity' :: ToCssSelector a =\u003e a -\u003e SelectorSpecificity\n```\n\n## `ToMarkup`, `ToJSON`, and `ToJavascript` instances\n\nThe types that are members of the `ToCssSelector` are members of the `ToMarkup`,\n`ToJSON`, and `ToJavascript` type classes as well, such that we can conveniently\nuse these in blaze HTML and for example in *Hamlet*.\n\nThe `ToMarkup` instance will render the css selector as raw content. So if you\nadd this as an attribute, the css selector will appear, unescaped, in the\nrendered page. Note that it will be escaped, so `foo \u003e bar` will be generated as\n`foo \u0026gt; bar`.\n\nThe `ToJSON` instance will convert the given object in a JSON string that\ncontains the css selector.\n\nThe `ToJavascript` will render the content to a javascript *string*. So if you\nuse this in hamlet, you generate a string that contains the css-selector. This\nis often useful, since javascript itself has no syntax for css selectors, and\noften strings are used to represent these.\n\n## `Arbitrary` css selectors\n\nOne can generate arbitrary CSS selectors (and their subcomponents). It is\nhowever not advisable to use this for anything other than for validation\npurposes (like with `QuickCheck`).\n\n## `Binary` and `Hashable` instances\n\nThe css-elements are all members of the `Binary` and `Hashable` typeclasses,\nThe `Binary` typeclass converts the css selector to a compact binary format.\nThis is *not* standard format. This is more to write a css-selector to a\nbinary format and back.\n\ncss-elements are an instance of `Hashable` as well, for example to use as\nkeys in a `HashMap`.\n\n## `css-selectors` is not *safe* Haskell\n\nThere are not extensions that are used that make the library *itself*\nunsafe, but it makes use of `aeson`, `blaze-markup`, etc. and the packages are\nnot safe. Hence this package is not *safe Haskell*.\n\n## Future plans\n\nWe want to implement an extra quasiquoter with the ability to specify variables,\nthat can then be used in expressions, or in patterns.\n\n## Contribute\n\nYou can contribute by making a pull request on the [*GitHub\nrepository*](https://github.com/hapytex/css-selectors).\n\nYou can contact the package maintainer by sending a mail to\n[`hapytexeu+gh@gmail.com`](mailto:hapytexeu+gh@gmail.com).\n\n---\n\nThis package is dedicated in loving memory to my mother, *Veerle Dumon*\n(1958-2019), in the hope that eventually it will be as stylish as she was.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhapytex%2Fcss-selectors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhapytex%2Fcss-selectors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhapytex%2Fcss-selectors/lists"}