{"id":13726450,"url":"https://github.com/cssinjs/istf-spec","last_synced_at":"2025-05-07T21:32:39.035Z","repository":{"id":66086205,"uuid":"92170227","full_name":"cssinjs/istf-spec","owner":"cssinjs","description":"Interoperable Style Transfer Format [DRAFT]","archived":false,"fork":false,"pushed_at":"2018-01-03T18:34:21.000Z","size":32,"stargazers_count":247,"open_issues_count":13,"forks_count":8,"subscribers_count":23,"default_branch":"master","last_synced_at":"2024-08-03T01:28:53.696Z","etag":null,"topics":["css"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cssinjs.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}},"created_at":"2017-05-23T12:27:08.000Z","updated_at":"2023-10-12T05:43:45.000Z","dependencies_parsed_at":"2023-02-23T06:30:47.724Z","dependency_job_id":null,"html_url":"https://github.com/cssinjs/istf-spec","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/cssinjs%2Fistf-spec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssinjs%2Fistf-spec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssinjs%2Fistf-spec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cssinjs%2Fistf-spec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cssinjs","download_url":"https://codeload.github.com/cssinjs/istf-spec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224654284,"owners_count":17347715,"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-08-03T01:03:05.238Z","updated_at":"2024-11-14T16:33:52.616Z","avatar_url":"https://github.com/cssinjs.png","language":null,"readme":"## Interoperable Style Transfer Format [DRAFT].\n\nThe biggest issue at scale we currently have with all CSSinJS implementations is that they are not sharable without the runtime.\n\nUsing regular CSS doesn't support all features we need. CSS notation is designed for humans and is too slow for parsing.\n\nThis format is [blazingly fast](https://esbench.com/bench/592d599e99634800a03483d8) to parse and will support all needs of the current CSSinJS implementations.\n\nPackage maintainers will be able to publish JavaScript files to NPM in this format instead of plain CSS or any variation of objects notation.\n\nDo not confuse this format with an AST. It is designed purely for interoperability and publishing. Using this format you can build an AST or regular CSS or any other structure.\n\n### Glossary\n\nThe following are some terms that are used throughout the spec, or are relevant when discussing the spec.\n\n- **ISTF array:** Array containing ISTF Rules\n- **ISTF rule:** Subset of ISTF array, containing rule selector and declaration\n- **ISTF selector:** Subset of ISTF rule, containing only rule selector\n- **ISTF declaration:** Subset of ISTF rule, containing only properties and values\n- **ISTF property:** Subset of ISTF rule declarations, containing only properties\n- **ISTF values:** Subset of ISTF rule declarations, containing only values\n- **Markers:** Like nodes in an AST format, these tuples indicate significant literals and values (See [Markers](#markers))\n- **References:** References to primitives in the host language, typically known as \"interpolations\" in tagged template literals in JavaScript\n- **Parsing:** The process of converting the input to an ISTF array\n- **Transformation:** The act of changing an ISTF array\n- **Runtime:** The user environment wherein ISTF is turned into CSS and rendered\n- **Preprocessing:** Transforming ISTF arrays to make it ready for distribution and transformation\n- **Postprocessing:** Last transformation steps of ISTF during runtime, like autoprefixing\n- **Evaluation:** Evaluating references to be able to put them into the CSS string during stringification\n- **Stringification:** Turning ISTF into regular CSS, which might involve evaluating references\n- **Rendering:** Using the resulting CSS and displaying the result\n\n### Markers\n\nExamples are using constant names instead of values for readability within the spec. The resulting format will use their values.\n\n```js\nconst RULE_START = 0\nconst RULE_END = 1\nconst RULE_NAME = 2\nconst SELECTOR = 3\nconst PARENT_SELECTOR = 4\nconst UNIVERSAL_SELECTOR = 5\nconst COMPOUND_SELECTOR_START = 6\nconst COMPOUND_SELECTOR_END = 7\nconst SPACE_COMBINATOR = 8\nconst DOUBLED_CHILD_COMBINATOR = 9\nconst CHILD_COMBINATOR = 10\nconst NEXT_SIBLING_COMBINATOR = 11\nconst SUBSEQUENT_SIBLING_COMBINATOR = 12\nconst PROPERTY = 13\nconst VALUE = 14\nconst COMPOUND_VALUE_START = 15\nconst COMPOUND_VALUE_END = 16\nconst CONDITION = 17\nconst FUNCTION_START = 18\nconst FUNCTION_END = 19\nconst ANIMATION_NAME = 20\nconst SELECTOR_REF = 21\nconst PROPERTY_REF = 22\nconst VALUE_REF = 23\nconst PARTIAL_REF = 24\nconst STRING_START = 25\nconst STRING_END = 26\n```\n\n#### Rule start\n\n`[RULE_START, \u003ctype\u003e]`\n\nMarker `RULE_START` specifies the beginning of a rule, has a rule type.\n\nAll rule types from https://wiki.csswg.org/spec/cssom-constants\n\n```\n1 STYLE_RULE CSSOM\n2 CHARSET_RULE CSSOM\n3 IMPORT_RULE CSSOM\n4 MEDIA_RULE CSSOM\n5 FONT_FACE_RULE CSSOM\n6 PAGE_RULE CSSOM\n7 KEYFRAMES_RULE css3-animations\n8 KEYFRAME_RULE css3-animations\n9 MARGIN_RULE CSSOM\n10 NAMESPACE_RULE CSSOM\n11 COUNTER_STYLE_RULE css3-lists\n12 SUPPORTS_RULE css3-conditional\n13 DOCUMENT_RULE css3-conditional\n14 FONT_FEATURE_VALUES_RULE css3-fonts\n15 VIEWPORT_RULE css-device-adapt\n16 REGION_STYLE_RULE proposed for css3-regions\n17 CUSTOM_MEDIA_RULE mediaqueries\n```\n\n#### Rule end\n\n`[RULE_END]`\n\nMarker `RULE_END` specifies the end of a rule.\n\n#### Named rule.\n\n`[RULE_NAME, \u003cname\u003e]`\n\nMarker `RULE_NAME` specifies a rule name.\n\nInstead of using a selector, a rule can be identified by a name. This is a preferred way instead of using hardcoded selectors. Consumer library will generate a selector for the rule and user can access it by name.\nWe rely on the JavaScript module scope. Name should be unique within that module scope.\n\n#### Selector\n\n`[SELECTOR, \u003cselector\u003e]`\n\nMarker `SELECTOR` specifies a selector.\n\nSelector e.g. `.foo` =\u003e `[SELECTOR, '.foo']`\n\nSelector list e.g. `.foo, .bar` =\u003e `[SELECTOR, '.foo'], [SELECTOR, '.bar']`\n\n#### Compound selector\n\n`[COMPOUND_SELECTOR_START], [SELECTOR, \u003cselector\u003e]+, [*COMBINATOR]?, [COMPOUND_SELECTOR_END]`\n\n[Compound](https://drafts.csswg.org/selectors/#compound) selector consists of simple selectors which might be separated by [combinators](https://drafts.csswg.org/selectors/#combinators).\n\nSelector compound without combinators e.g. `.foo.bar` =\u003e\n\n```js\n[SELECTOR_COMPOUND_START],\n  [SELECTOR, '.foo'],\n  [SELECTOR, '.bar'],\n[SELECTOR_COMPOUND_END]\n```\n\nSelector compound with space combinator e.g. `.foo .bar` =\u003e\n\n```js\n[SELECTOR_COMPOUND_START],\n  [SELECTOR, '.foo'],\n  [SPACE_COMBINATOR],\n  [SELECTOR, '.bar'],\n[SELECTOR_COMPOUND_END]\n```\n\nSelector compound with next sibling combinator e.g. `.foo + .bar` =\u003e\n\n```js\n[SELECTOR_COMPOUND_START],\n  [SELECTOR, '.foo'],\n  [NEXT_SIBLING_COMBINATOR],\n  [SELECTOR, '.bar'],\n[SELECTOR_COMPOUND_END]\n```\n\n#### Parent selector\n\n`[PARENT_SELECTOR]`\n\nMarker `PARENT_SELECTOR` specifies a selector, which is a reference to the parent selector, `\u0026`.\nUseful for nesting.\n\nE.g.: `\u0026:hover` =\u003e\n\n```js\n[COMPOUND_SELECTOR_START]\n  [PARENT_SELECTOR],\n  [SELECTOR, ':hover'],\n[COMPOUND_SELECTOR_END]\n```\n\n\n#### Universal selector\n\n`[UNIVERSAL_SELECTOR]`\n\nMarker `UNIVERSAL_SELECTOR` specifies a selector, which is a reference to the universal selector, `*`.\n\nE.g.: `*.red` =\u003e\n\n```js\n[COMPOUND_SELECTOR_START]\n  [UNIVERSAL_SELECTOR],\n  [SELECTOR, '.red'],\n[COMPOUND_SELECTOR_END]\n```\n\n#### Property name\n\n`[PROPERTY, \u003cproperty\u003e]`\n\nMarker `PROPERTY` specifies a property name e.g.: `color` =\u003e `[PROPERTY, 'color']`.\n\n#### Simple value\n\n`[VALUE, \u003cvalue\u003e]`\n\nMarker `VALUE` specifies a property value e.g.: `red` =\u003e `[VALUE, 'red']`.\n\n#### Values list\n\n`[VALUE, 'red']+`\n\nA comma separated list of simple values e.g.: `red, green` =\u003e `[VALUE, 'red'], [VALUE, 'green']`.\n\n\n#### Compound value\n\n`[COMPOUND_VALUE_START], [VALUE, \u003cvalue\u003e]+, [COMPOUND_VALUE_END]`\n\nA value that consists of multiple space separated simple values: e.g.: `10px 20px` =\u003e\n\n```js\n[COMPOUND_VALUE_START],\n  [VALUE, '10px'],\n  [VALUE, '20px'],\n[COMPOUND_VALUE_END]\n```\n#### Function\n\n`[FUNCTION_START, \u003cname\u003e], [SELECTOR|VALUE, \u003cargument\u003e], [FUNCTION_END]`\n\nFunction specifies [functional pseudo class](https://drafts.csswg.org/selectors/#functional-pseudo-class) as well as [functional notation](https://drafts.csswg.org/css-values-4/#functional-notation).\n\nFunctional pseudo class e.g. `.foo:matches(:hover, :focus)` =\u003e\n\n```js\n[SELECTOR_COMPOUND_START],\n  [SELECTOR, '.foo'],\n  [FUNCTION_START, ':matches'],\n    [SELECTOR, ':hover'],\n    [SELECTOR, ':focus'],\n  [FUNCTION_END],\n[SELECTOR_COMPOUND_END]\n```\n\nFunctional value notation e.g.: `color: rgb(100, 200, 50)` =\u003e\n\n```js\n[PROPERTY, 'color'],\n[FUNCTION_START, 'rgb'],\n  [VALUE, 100],\n  [VALUE, 200],\n  [VALUE, 50],\n[FUNCTION_END]\n```\n\n### Condition\n\n`[CONDITION, \u003ccondition\u003e]`\n\nMarker `CONDITION` specifies a condition for conditional rules.\n\nE.g. `@media all` =\u003e `[RULE_START, 4], [CONDITION, 'all']`\n\n#### Value reference\n\n`[VALUE_REF, ref]`\n\nVariable `ref` can be ISTF values, a string or a function returning any of those. Using ISTF values gives more power to post-processors. Using string value results in better performance.\n\n`border: red, green` =\u003e\n\n```js\n// Using ISTF values:\n[PROPERTY, 'border'],\n[VALUE_REF, () =\u003e [\n  [VALUE, 'red'],\n  [VALUE, 'green'],\n]]\n\n// Using a string value:\n[VALUE_REF, () =\u003e 'red, green']\n```\n\n#### Property reference\n\n`[PROPERTY_REF, ref]`\n\nVariable `ref` is a string or a function which returns a string.\n\n`border: red` =\u003e\n\n```js\n[PROPERTY_REF, () =\u003e 'border'],\n[VALUE, 'red']\n```\n\n#### Selector reference\n\n`[SELECTOR_REF, ref]`\n\nVariable `ref` is a string or a function which returns a string.\n\nSimple selector: `.foo` =\u003e `[SELECTOR_REF, () =\u003e '.foo']`\nCompound selector: `.foo.bar` =\u003e\n\n```js\n[COMPOUND_SELECTOR_START]\n  [SELECTOR, '.foo'],\n  [SELECTOR_REF, () =\u003e '.bar'],\n[COMPOUND_SELECTOR_END]\n```\n\n#### Partial reference\n\n`[PARTIAL_REF, ref]`\n\nVariable `ref` is an ISTF array or a function which returns an ISTF array.\n\n```css\n.foo {\n  color: red;\n}\n.partial {\n  color: green;\n}\n```\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red'],\n  [RULE_END],\n  [PARTIAL_REF, () =\u003e [\n    [RULE_START, 1],\n      [SELECTOR, '.partial'],\n      [PROPERTY, 'color'],\n      [VALUE, 'green'],\n    [RULE_END],    \n  ]]\n]\n```\n\n## Examples\n\n### Global tag selector\n\n```css\nbody {\n  color: red\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, 'body'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red']\n  [RULE_END]\n]\n```\n\n### Selectors list\n\n```css\nbody, .foo {\n  color: red\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, 'body'],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red']\n  [RULE_END]\n]\n```\n\n### Multiple values\n\n```css\n.foo {\n  border-color: red, green\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'border'],\n    [VALUE, 'red'],\n    [VALUE, 'green'],\n  [RULE_END]\n]\n```\n\n### Fallbacks\n\n```css\n.foo {\n  color: red;\n  color: palevioletred;\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red'],\n    [PROPERTY, 'color'],\n    [VALUE, 'palevioletred'],\n  [RULE_END]\n]\n```\n\n### Compound strings\n\n`[STRING_START, \u003cquote\u003e], [VALUE|VALUE_REF, \u003cargument\u003e], [STRING_END]`\n\nWhen a string in CSS contains an interpolation, e.g. `\"hello, ${name}\"`, the string should be split up into its values and\nvalue references. This is because compound values are unsuitable to represent strings, since all values and value references should be joined without a separating whitespace. Also how the references should be escaped changes for strings, due to their quotes.\n\n```js\n[\n  [STRING_START, '\"'],\n    [VALUE, 'hello, '],\n    [VALUE_REF, name],\n  [STRING_END]\n]\n```\n\nThe quotes of the string will not be part of the values, but part of the `STRING_START` marker. When the ISTF is turned back into CSS, the quote will need to be escaped inside the value references.\n\n### Conditionals\n\n```css\n@media all {\n  .foo {\n    color: red;\n  }\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [CONDITION, 'all'],\n    [RULE_START, 1],\n      [SELECTOR, '.foo'],\n      [PROPERTY, 'color'],\n      [VALUE, 'red'],\n    [RULE_END],\n  [RULE_END]\n]\n```\n\n### Nesting\n\n```css\n.foo {\n  color: red;\n  \u0026:hover {\n    color: green;\n  }\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red'],\n    [RULE_START, 1],\n      [COMPOUND_SELECTOR_START],\n        [PARENT_SELECTOR],\n        [SELECTOR, ':hover'],\n      [COMPOUND_SELECTOR_END],\n      [PROPERTY, 'color'],\n      [VALUE, 'green'],\n    [RULE_END],\n  [RULE_END]\n]\n```\n\n### Nesting with a compound selector\n\n```css\n.foo {\n  color: red;\n  \u0026.bar.baz .bla {\n    color: green;\n  }\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red'],\n    [RULE_START, 1],\n      [COMPOUND_SELECTOR_START],\n        [PARENT_SELECTOR],\n        [SELECTOR, '.bar'],\n        [SELECTOR, '.baz'],\n        [SPACE_COMBINATOR],\n        [SELECTOR, '.bla'],\n      [COMPOUND_SELECTOR_END],\n      [PROPERTY, 'color'],\n      [VALUE, 'green'],\n    [RULE_END],\n  [RULE_END]\n]\n```\n\n### Scoping or named rules\n\n```css\n.foo-123456 {\n  color: red\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [RULE_NAME, 'foo'],\n    [PROPERTY, 'color'],\n    [VALUE, 'red']\n  [RULE_END]\n]\n```\n\n### Functional pseudo class\n\n```css\n.foo:matches(:hover, :focus) {\n  color: red\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [COMPOUND_SELECTOR_START],\n      [SELECTOR, '.foo'],\n      [FUNCTION_START, ':matches'],\n        [SELECTOR, ':hover'],\n        [SELECTOR, ':focus'],\n      [FUNCTION_END],\n    [COMPOUND_SELECTOR_END],\n    [PROPERTY, 'color'],\n    [VALUE, 'red']\n  [RULE_END]  \n]\n```\n\n### Functional value notation\n\n```css\n.foo {\n  background: url(http://www.example.org/image);\n  color: rgb(100, 200, 50);\n  content: counter(list-item) \". \";\n  width: calc(50% - 2em);\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [SELECTOR, '.foo'],\n    [PROPERTY, 'background'],\n    [FUNCTION_START, 'url'],\n      [VALUE, 'http://www.example.org/image']\n    [FUNCTION_END],\n    [PROPERTY, 'color'],\n    [FUNCTION_START, 'rgb'],\n      [VALUE, 100],\n      [VALUE, 200],\n      [VALUE, 50]\n    [FUNCTION_END],    \n    [PROPERTY, 'content'],\n    [COMPOUND_VALUE_START],\n      [FUNCTION_START, 'counter'],\n        [VALUE, 'list-item']\n      [FUNCTION_END],     \n      [VALUE, '\". \"']\n    [COMPOUND_VALUE_END],\n    [PROPERTY, 'width'],\n    [FUNCTION_START, 'calc'],\n      [VALUE, '50% - 2em'],\n    [FUNCTION_END],\n  [RULE_END]  \n]\n```\n\n#### Value, Selector and Partial using a function\n\n```css\n.foo.bar {\n  color: red;\n  margin: 10px 20px;\n  border: green, red;\n}\n.partial {\n  color: green;\n}\n```\n\n```js\n[\n  [RULE_START, 1],\n    [COMPOUND_SELECTOR_START],\n      [SELECTOR, '.foo'],\n      [SELECTOR_REF, () =\u003e '.bar'],\n    [COMPOUND_SELECTOR_END],\n    [PROPERTY, 'color'],\n    [VALUE_REF, () =\u003e [\n      [VALUE, 'red']\n    ]],\n    [PROPERTY, 'margin'],\n    [VALUE_REF, () =\u003e [\n      [COMPOUND_VALUE_START],\n        [VALUE, '10px'],\n        [VALUE, '20px'],\n      [COMPOUND_VALUE_END]\n    ]],\n    [PROPERTY, 'border'],\n    [VALUE_REF, () =\u003e [\n      [VALUE, 'green'],\n      [VALUE, 'red']\n    ]],    \n  [RULE_END],\n  [PARTIAL_REF, () =\u003e [\n    [RULE_START, 1],\n      [SELECTOR, '.partial']\n      [PROPERTY, 'color'],\n      [VALUE, 'green'],\n    [RULE_END],    \n  ]]\n]\n```\n\n#### Keyframes\n\n```css\n@keyframes fadeIn {\n  from {\n    opacity: 0;\n  }\n  to {\n    opacity: 1;\n  }\n}\n```\n\n```js\n[\n  [RULE_START, 7],\n    [ANIMATION_NAME, 'fadeIn'],\n    [RULE_START, 8],\n      [RULE_NAME, 'from'],\n      [PROPERTY, 'opacity'],\n      [VALUE, 0],\n    [RULE_END],\n    [RULE_START, 8],\n      [RULE_NAME, 'to'],\n      [PROPERTY, 'opacity'],\n      [VALUE, 1],\n    [RULE_END],\n  [RULE_END]\n]\n```\n\n#### Media query\n\n```css\n@media all {\n  .foo {\n    color: red;\n  }\n}\n```\n\n```js\n[\n  [RULE_START, 4],\n    [CONDITION, 'all'],\n    [RULE_START, 1],\n      [SELECTOR, '.foo'],\n      [PROPERTY, 'color'],\n      [VALUE, 'red'],\n    [RULE_END],\n  [RULE_END]\n]\n```\n","funding_links":[],"categories":["Others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcssinjs%2Fistf-spec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcssinjs%2Fistf-spec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcssinjs%2Fistf-spec/lists"}