{"id":20079549,"url":"https://github.com/transpect/css-tools","last_synced_at":"2025-05-05T23:30:27.992Z","repository":{"id":48175706,"uuid":"45345839","full_name":"transpect/css-tools","owner":"transpect","description":"Parse styles in an XHTML document and expand as XML attributes (CSSa)","archived":false,"fork":false,"pushed_at":"2024-10-16T09:06:36.000Z","size":651,"stargazers_count":8,"open_issues_count":2,"forks_count":2,"subscribers_count":16,"default_branch":"master","last_synced_at":"2024-10-17T21:54:24.666Z","etag":null,"topics":["css"],"latest_commit_sha":null,"homepage":"","language":"XSLT","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/transpect.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2015-11-01T15:30:09.000Z","updated_at":"2024-10-16T09:06:40.000Z","dependencies_parsed_at":"2024-01-04T20:26:06.481Z","dependency_job_id":"d29bd725-b37f-4f0b-adc0-d25c9e38d7cc","html_url":"https://github.com/transpect/css-tools","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transpect%2Fcss-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transpect%2Fcss-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transpect%2Fcss-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transpect%2Fcss-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/transpect","download_url":"https://codeload.github.com/transpect/css-tools/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252592753,"owners_count":21773327,"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"],"created_at":"2024-11-13T15:23:23.034Z","updated_at":"2025-05-05T23:30:27.615Z","avatar_url":"https://github.com/transpect.png","language":"XSLT","funding_links":[],"categories":[],"sub_categories":[],"readme":"# css:expand\n\nParse CSS styles of an XHTML document and expand them as XML attributes ([CSSa](https://github.com/le-tex/CSSa))\n\n## Example 1\n\nConsider this document as input:\n\n```html\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\"\u003e\n  \u003chead\u003e\n    \u003ctitle\u003ecss-expand expample\u003c/title\u003e\n    \u003cstyle type=\"text/css\"\u003e\n      .red {color:red}\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cp class=\"red\"\u003eThis text has the color red.\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n\n```\n\nInvoke `css:expand` in your XProc pipeline. Please note \nthat you have to include [xproc-utils](https://github.com/transpect/xproc-util).\n\nSee [test-css-expand.xpl](https://github.com/transpect/css-tools/blob/master/xpl/test-css-expand.xpl) for an example pipeline.\n\n\nAfter running `css-expand`, internal and external CSS style information are expanded as XML attributes.\n```html\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\" \n  xmlns:css=\"http://www.w3.org/1996/css\"\u003e\n  \u003chead\u003e\n    \u003ctitle\u003ecss-expand expample\u003c/title\u003e\n    \u003cstyle type=\"text/css\"\u003e\n      .red {color:red}\n    \u003c/style\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cp class=\"red\" css:color=\"red\"\u003eThis text has the color red.\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Example 2\n\nThis example contains an `xml-stylesheet` processing instruction as an additional CSS source. It also demonstrates the handling of \nshorthand properties and pseudo elements.\n\nSee [example2.xhtml](https://github.com/transpect/css-tools/blob/master/example/example2.xhtml) and [style2.css](https://github.com/transpect/css-tools/blob/master/example/style2.css)\n\nExpanded output (`body` only):\n\n```html\n\u003cbody css:background-color=\"#eec\"\u003e\n  \u003cdiv id=\"grid\"\u003e\n    \u003cdiv id=\"reference-overlapped-red\" css:color=\"red\" css:font-style=\"normal\" css:font-variant=\"normal\" css:font-weight=\"normal\" css:font-stretch=\"normal\" css:font-size=\"100px\" css:line-height=\"1\" css:font-family=\"Ahem\" css:grid-row=\"1\" css:grid-column=\"1\"\u003eR\u003c/div\u003e\n    \u003cdiv id=\"test-overlapping-green\" css:background-color=\"green\" css:width=\"100px\" css:height=\"100px\" css:grid-row=\"1\" css:grid-column=\"1\" css:font-style=\"normal\" css:font-variant=\"normal\" css:font-weight=\"bold\" css:font-stretch=\"normal\" css:font-size=\"12px\" css:line-height=\"120%\" css:font-family=\"sans-serif\"/\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"foo\" css:font-style=\"normal\" css:font-variant=\"normal\" css:font-weight=\"400\" css:font-stretch=\"normal\" css:font-size=\"80%\" css:line-height=\"normal\" css:font-family=\"'New Century Schoolbook', \u0026#34;Palatino Linotype\u0026#34;, serif\"\u003e\n    \u003cp css:pseudo-after_content=\"' styled by style element'\" css:pseudo-before_content=\"'styled by PI '\" css:font-style=\"italic\" css:font-variant=\"normal\" css:font-weight=\"normal\" css:font-stretch=\"normal\" css:font-size=\"80%\" css:line-height=\"normal\" css:font-family=\"serif\"\u003eTest\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/body\u003e\n```\n\n## Example 3: Styling XML\n\nAgain using an `xml-stylesheet` processing instruction.\n\nSee [example3.xml](https://github.com/transpect/css-tools/blob/master/example/example3.xml) and [style3.css](https://github.com/transpect/css-tools/blob/master/example/style3.css)\n\nExpanded output:\n\n```xml\n\u003cdoc xmlns:css=\"http://www.w3.org/1996/css\"\u003e\n  \u003csec id=\"intro\"\u003e\n    \u003ctitle css:color=\"grey\"\u003eIntroduction\u003c/title\u003e\n    \u003cp\u003ePara\u003c/p\u003e\n  \u003c/sec\u003e\n  \u003csec id=\"sec1\"\u003e\n    \u003ctitle\u003eSection\u003c/title\u003e\n    \u003cp\u003eFirst \u003cseg type=\"foo\" css:pseudo-after_content=\"']'\" css:pseudo-after_color=\"red\" css:pseudo-before_content=\"'['\" css:pseudo-before_color=\"red\" css:color=\"red\"\u003epara\u003c/seg\u003e\u003c/p\u003e\n    \u003cp\u003eLast para\u003c/p\u003e\n  \u003c/sec\u003e\n\u003c/doc\u003e\n```\n\nYou can then postprocess the `@css:pseudo.…` attributes in order to actually prepend/append the `::before` and `::after` pseudo element content to the element’s text.\n\n\n# css:parse\n\nThere is also a step `css:parse` in the same css.xpl library. This will only generate an XML representation from the CSS that was included per `link` or `style` elements (note that the input is expected to be in XHTML namespace; will add reading HTML5-serialized input later). \n\nThe output, as generated by the [REx](http://bottlecaps.de/rex/)-generated parser for above `style`, looks like:\n\n```xml\n\u003cparser-results xml:base=\"file:/C:/path/to/file.xhtml\"\u003e\n   \u003ccss origin=\"file://internal\"\u003e\n      \u003cS\u003e\n      \u003c/S\u003e\n      \u003crule\u003e\n         \u003cselectors_group\u003e\n            \u003cselector\u003e\n               \u003csimple_selector_sequence\u003e\n                  \u003cclass\u003e\n                     \u003cTOKEN\u003e.\u003c/TOKEN\u003e\n                     \u003cIDENT\u003ered\u003c/IDENT\u003e\n                  \u003c/class\u003e\n               \u003c/simple_selector_sequence\u003e\n            \u003c/selector\u003e\n         \u003c/selectors_group\u003e\n         \u003cS\u003e \u003c/S\u003e\n         \u003cTOKEN\u003e{\u003c/TOKEN\u003e\n         \u003cdeclaration\u003e\n            \u003cproperty\u003e\n               \u003cIDENT\u003ecolor\u003c/IDENT\u003e\n            \u003c/property\u003e\n            \u003cTOKEN\u003e:\u003c/TOKEN\u003e\n            \u003cvalues\u003e\n               \u003cvalue\u003e\n                  \u003cIDENT\u003ered\u003c/IDENT\u003e\n               \u003c/value\u003e\n            \u003c/values\u003e\n         \u003c/declaration\u003e\n         \u003cTOKEN\u003e}\u003c/TOKEN\u003e\n      \u003c/rule\u003e\n      \u003cS\u003e\n    \u003c/S\u003e\n   \u003c/css\u003e\n\u003c/parser-results\u003e\n```\n\nThis parser output will then be transformed to an XML representation like this:\n\n```xml\n\u003ccss xmlns=\"http://www.w3.org/1996/css\"\u003e\n   \u003cruleset origin=\"file://internal\"\u003e\n      \u003craw-css xml:space=\"preserve\"\u003e\n        .red {color:red}\n      \u003c/raw-css\u003e\n      \u003cselector priority=\"0,0,1,0\" position=\"1\" raw-selector=\".red\"\u003ekey('class', 'red')\u003c/selector\u003e\n      \u003cdeclaration property=\"color\" value=\"red\"/\u003e\n   \u003c/ruleset\u003e\n\u003c/css\u003e\n```\n\nThere is no schema yet for this XML representation.\n\nThe text content of the selector elements are XPath expressions that will be used generating \nan XSLT stylesheet that, when applied to the input document, will yield the expanded document.\n\nThe purpose of expansion is to find out the actual styling that is applied to a document location, for example prior to Schematron checks for device compatibility or accessibility. Of course checking and possibly filtering the parsed CSS alone may be sufficient for quality control. In our EPUB builder, the CSS will be parsed and re-serialized by default. \n\n## Rationale for switching to an EBNF-based parser\n\nWe wanted to be able to parse stuff like `calc()`, `scale()`, `translateX()`, `rgba()` in a less cumbersome way than with regexes. \n\n\n## Comments and whitespace\n\nThere are customers who want to retain the comments in the re-serialized CSS. Comments in rules (in selectors and properties) have proved to be particularly difficult to handle. With the previous regex-based approach, we just split between the rules and if there were comments anywhere within a rule, they were pulled out of it and went immediately before it in the serialization. However, this is no longer possible with the REx-generated parser. \n\nREx knows a pragma, [`/* ws:definition */`](https://github.com/transpect/css-tools/commit/9e62b1da02856e72a02d07e60fa9c14be9eecc89#diff-2d7bf9880e9266456c02e71a533a4755L59), that allows to treat any named production rules as ignorable whitespace. We tried that, but apart from not allowing retention of comments, it conflicted with the descendant combinator, which happens to be just whitespace. So we (@fr4nze and @gimsieke) tried to use the [`/* ws:explicit */`] pragma in selectors, but this led to lexical ambiguities when comments were also part of the ignorable whitespace rules. If we solved this problem, we would still be losing the comments. So we now tried this: Whitespace is significant, but allowed in many places. Comments are allowed in less places, in particular not in the middle of a selector or in properties. If the parser encounters such a comment, it will raise an error. [This error will be caught](https://github.com/transpect/css-tools/commit/9e62b1da02856e72a02d07e60fa9c14be9eecc89#diff-b9619c16ea8c9baad938469e14e126aaR74), and the CSS input will be resubmitted with all comments stripped away by means of a regex. An appropriate error message will be produced on the report port, allowing users to move comments to safer places in the input. If comments may be ignored altogether, then also this error message may be ignored. \n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftranspect%2Fcss-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftranspect%2Fcss-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftranspect%2Fcss-tools/lists"}