├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── index.bs ├── index.html └── w3c.json /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Platform Incubator Community Group 2 | 3 | This repository is being used for work in the W3C Web Platform Incubator Community Group, governed by the [W3C Community License 4 | Agreement (CLA)](http://www.w3.org/community/about/agreements/cla/). To make substantive contributions, 5 | you must join the CG. 6 | 7 | If you are not the sole contributor to a contribution (pull request), please identify all 8 | contributors in the pull request comment. 9 | 10 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 11 | 12 | ``` 13 | +@github_username 14 | ``` 15 | 16 | If you added a contributor by mistake, you can remove them in a comment with: 17 | 18 | ``` 19 | -@github_username 20 | ``` 21 | 22 | If you are making a pull request on behalf of someone else but you had no part in designing the 23 | feature, you can remove yourself with the above syntax. 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors 2 | under the 3 | [W3C Software and Document License](http://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 4 | 5 | Contributions to Specifications are made under the 6 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 7 | 8 | Contributions to Test Suites are made under the 9 | [W3C 3-clause BSD License](https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Overview 2 | The goal of this specification is to allow authors access to the engine's parser. 3 | There are two over-arching use cases: 4 | 1. Pass the parser a string receive and receive an object 5 | to work with instead of building custom parsing in JS. 6 | 2. Extend what the parser understands for fully polyfilling 7 | 8 | Desires for these APIs: 9 | * Build on top of the [TypedOM](https://drafts.css-houdini.org/css-typed-om/) and make modifications to that 10 | specification where necessary. 11 | * Be able to request varying levels of error handling by the parser 12 | 13 | ## Example: Parsing out a ruleset 14 | 15 | ``` 16 | var background = window.cssParse.rule("background: green"); 17 | console.log(background.styleMap.get("background").value) // "green" 18 | 19 | var styles = window.cssParse.ruleSet(".foo { background: green; margin: 5px; }"); 20 | console.log(styles.length) // 5 21 | console.log(styles[0].styleMap.get("margin-top").value) // 5 22 | console.log(styles[0].styleMap.get("margin-top").type) // "px" 23 | ``` 24 | 25 | ## Example: Parsing out a stylesheet 26 | 27 | ``` 28 | const style = fetch("style.css") 29 | .then(response=>CSS.parseStylesheet(response.body)); 30 | style.then(console.log); 31 | 32 | /* example of the object once we have it more refined */ 33 | ); 34 | ``` 35 | 36 | Use Cases 37 | ========= 38 | 39 | 1. Extending CSS in a more intrusive way than our hooks allow - most of the stylesheet is valid CSS, but you want to intercede on the unrecognized things and fix it up into valid CSS. (Probably don't want to do this - it collides with the custom property/function/at-rule case, but without the friendliness to future language extensions.) 40 | 2. Custom properties that are more complex than we allow you to specify - something that takes "` || `", for example. Right now your only choice is to give it the grammar `"*"` which just gives you a string that you have to parse yourself. Similar with custom functions (`--conic-gradient(...)`) and custom at-rules (`@--svg`) - these will *rarely* fit in our limited set of allowed grammars. 41 | 3. CSS-like languages that want to rely on CSS's generic syntax, like CAS or that one mapping language I forget the name of. These have nothing to do with CSS and will likely result in something other than a stylesheet: CAS turns into a series of querySelector() and setAttribute() calls; the mapping thing turns into some data structures specific to that application. 42 | 4. Extending HTML/SVG attributes that use a CSS-like syntax, like ``. If you wanted to add support for the `h` descriptor to `sizes`, you currently have to write your own full-feature CSS parser. (`sizes` is pretty complex; you shouldn't skimp.) Better to let the engine parse it as "generic CSS", then you can recognize the parts you need and do image selection yourself. 43 | 44 | Example of the problem 45 | ====================== 46 | 47 | Here is an example of some JS code that is wanting to parse out various CSS 48 | types and also seperate out the values from their units. 49 | 50 | ``` 51 | 52 | function parseValues(value,propertyName) { 53 | // Trim value on the edges 54 | value = value.trim(); 55 | 56 | // Normalize letter-casing 57 | value = value.toLowerCase(); 58 | 59 | // Map colors to a standard value (eg: white, blue, yellow) 60 | if (isKeywordColor(value)) { return ""; } 61 | 62 | value = value.replace(/[#][0-9a-fA-F]+/g, '#xxyyzz'); 63 | 64 | // Escapce identifiers containing numbers 65 | var numbers = ['ZERO','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']; 66 | 67 | value = value.replace( 68 | /([_a-z][-_a-z]|[_a-df-z])[0-9]+[-_a-z0-9]*/g, 69 | s=>numbers.reduce( 70 | (m,nstr,nint)=>m.replace(RegExp(nint,'g'),nstr), 71 | s 72 | ) 73 | ); 74 | 75 | // Remove any digits eg: 55px -> px, 1.5 -> 0.0, 1 -> 0 76 | value = value.replace(/(?:[+]|[-]|)(?:(?:[0-9]+)(?:[.][0-9]+|)|(?:[.][0-9]+))(?:[e](?:[+]|[-]|)(?:[0-9]+))?(%|e[a-z]+|[a-df-z][a-z]*)/g, "$1"); 77 | value = value.replace(/(?:[+]|[-]|)(?:[0-9]+)(?:[.][0-9]+)(?:[e](?:[+]|[-]|)(?:[0-9]+))?/g, " "); 78 | value = value.replace(/(?:[+]|[-]|)(?:[.][0-9]+)(?:[e](?:[+]|[-]|)(?:[0-9]+))?/g, " "); 79 | value = value.replace(/(?:[+]|[-]|)(?:[0-9]+)(?:[e](?:[+]|[-]|)(?:[0-9]+))/g, " "); 80 | value = value.replace(/(?:[+]|[-]|)(?:[0-9]+)/g, " "); 81 | 82 | // Unescapce identifiers containing numbers 83 | value = numbers.reduce( 84 | (m,nstr,nint)=>m.replace(RegExp(nstr,'g'),nint), 85 | value 86 | ) 87 | 88 | // Remove quotes 89 | value = value.replace(/('|‘|’|")/g, ""); 90 | 91 | // 92 | switch(propertyName) { 93 | case 'counter-increment': 94 | case 'counter-reset': 95 | // Anonymize the user identifier 96 | value = value.replace(/[-_a-zA-Z0-9]+/g,' '); 97 | break; 98 | case 'grid': 99 | case 'grid-template': 100 | case 'grid-template-rows': 101 | case 'grid-template-columns': 102 | case 'grid-template-areas': 103 | // Anonymize line names 104 | value = value.replace(/\[[-_a-zA-Z0-9 ]+\]/g,' '); 105 | break; 106 | case '--var': 107 | // Replace (...), {...} and [...] 108 | value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); 109 | value = value.replace(/[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]+|[(](?:[^()]*)[)])*[)])*[)])*[)])*[)]/g, " "); 110 | value = value.replace(/\[(?:[^()]+|\[(?:[^()]+|\[(?:[^()]+|\[(?:[^()]+|\[(?:[^()]*)\])*\])*\])*\])*\]/g, " "); 111 | value = value.replace(/\[(?:[^()]+|\[(?:[^()]+|\[(?:[^()]+|\[(?:[^()]+|\[(?:[^()]*)\])*\])*\])*\])*\]/g, " "); 112 | value = value.replace(/\{(?:[^()]+|\{(?:[^()]+|\{(?:[^()]+|\{(?:[^()]+|\{(?:[^()]*)\})*\})*\})*\})*\}/g, " "); 113 | value = value.replace(/\{(?:[^()]+|\{(?:[^()]+|\{(?:[^()]+|\{(?:[^()]+|\{(?:[^()]*)\})*\})*\})*\})*\}/g, " "); 114 | break; 115 | } 116 | 117 | return value.trim(); 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 | 14 | 15 | Introduction {#intro} 16 | ===================== 17 | 18 | Common data-interchange / parsing formats are very valuable 19 | for reducing the learning curve of new languages, 20 | as users get to lean on their existing knowledge of the format when authoring 21 | and only have to newly learn the specifics of the language. 22 | This is why generic parsing formats like XML or JSON have become so popular. 23 | 24 | The CSS language could benefit from this same treatment; 25 | a number of languages and tools rely on CSS-like syntax to express themselves, 26 | but they usually rely on ad-hoc parsing 27 | (often regex-based) 28 | which can be relatively fragile, 29 | and might break with CSS practices in interesting syntax corner cases. 30 | Similarly, CSS syntax is increasingly used in places like attribute values 31 | (such as the <{img/sizes}> attribute, 32 | or most of the SVG presentation attributes), 33 | and custom elements wanting to do the same thing 34 | similarly have to rely on ad-hoc parsing right now. 35 | 36 | To help with these sorts of cases, 37 | this spec exposes the [[!css-syntax-3]] parsing algorithms, 38 | and represents their results in a mildly-typed representation, 39 | simpler and more abstract than what [[css-typed-om-1]] does for CSS properties. 40 | 41 | Parsing API {#parsing-api} 42 | ========================== 43 | 44 |
 45 | typedef (DOMString or ReadableStream) CSSStringSource;
 46 | typedef (DOMString or CSSStyleValue or CSSParserValue) CSSToken;
 47 | 
 48 | partial namespace CSS {
 49 | 	Promise<sequence<CSSParserRule>> parseStylesheet(CSSStringSource css, optional CSSParserOptions options = {});
 50 | 	Promise<sequence<CSSParserRule>> parseRuleList(CSSStringSource css, optional CSSParserOptions options = {});
 51 | 	Promise<CSSParserRule> parseRule(CSSStringSource css, optional CSSParserOptions options = {});
 52 | 	Promise<sequence<CSSParserRule>> parseDeclarationList(CSSStringSource css, optional CSSParserOptions options = {});
 53 | 	CSSParserDeclaration parseDeclaration(DOMString css, optional CSSParserOptions options = {});
 54 | 	CSSToken parseValue(DOMString css);
 55 | 	sequence<CSSToken> parseValueList(DOMString css);
 56 | 	sequence<sequence<CSSToken>> parseCommaValueList(DOMString css);
 57 | };
 58 | 
 59 | dictionary CSSParserOptions {
 60 | 	object atRules;
 61 | 	/* dict of at-rule name => at-rule type
 62 | 	   (contains decls or contains qualified rules) */
 63 | };
 64 | 
65 | 66 | Issue: {{parseCommaValueList()}} is in Syntax, and thus here, 67 | because it's actually a very common operation. 68 | It's trivial to do yourself 69 | (just call {{parseValueList()}} and then split into an array on top-level commas), 70 | but comma-separated lists are so common 71 | that it was worthwhile to improve spec ergonomics 72 | by providing a shortcut for that functionality. 73 | Is it worth it to provide this to JS as well? 74 | 75 | Issue: Do we handle comments? 76 | Currently I don't; 77 | Syntax by default just drops comments, 78 | but allows an impl to preserve information about them if they want. 79 | Maybe add an option to preserve comments? 80 | If so, they can appear *anywhere*, 81 | in any API that returns a sequence. 82 | 83 | Issue: What do we do if an unknown at-rule 84 | (not appearing in the {{atRules}} option) 85 | shows up in the results? 86 | Default to decls or rules? 87 | Or treat it more simply as just a token sequence? 88 | 89 | Issue: Parsing stylesheets/rule lists should definitely be async, 90 | because stylesheets can be quite large. 91 | Parsing individual properties/value lists should definitely be sync, 92 | because they're small and it would be really annoying. 93 | Parsing a single rule, tho, is unclear-- 94 | is it large enough to be worth making async, 95 | or is it too annoying to be worth it? 96 | 97 | Parser Values {#parser-values} 98 | ============================== 99 | 100 |
101 | [Exposed=Window]
102 | interface CSSParserRule {
103 | 	/* Just a superclass. */
104 | };
105 | 
106 | [Exposed=Window]
107 | interface CSSParserAtRule : CSSParserRule {
108 | 	constructor(DOMString name, sequence<CSSToken> prelude, optional sequence<CSSParserRule>? body);
109 | 	readonly attribute DOMString name;
110 | 	readonly attribute FrozenArray<CSSParserValue> prelude;
111 | 	readonly attribute FrozenArray<CSSParserRule>? body;
112 | 	/* nullable to handle at-statements */
113 | 	stringifier;
114 | };
115 | 
116 | [Exposed=Window]
117 | interface CSSParserQualifiedRule : CSSParserRule {
118 | 	constructor(sequence<CSSToken> prelude, optional sequence<CSSParserRule>? body);
119 | 	readonly attribute FrozenArray<CSSParserValue> prelude;
120 | 	readonly attribute FrozenArray<CSSParserRule> body;
121 | 	stringifier;
122 | };
123 | 
124 | [Exposed=Window]
125 | interface CSSParserDeclaration : CSSParserRule {
126 | 	constructor(DOMString name, optional sequence<CSSParserRule> body);
127 | 	readonly attribute DOMString name;
128 | 	readonly attribute FrozenArray<CSSParserValue> body;
129 | 	stringifier;
130 | };
131 | 
132 | [Exposed=Window]
133 | interface CSSParserValue {
134 | 	/* Just a superclass. */
135 | };
136 | 
137 | [Exposed=Window]
138 | interface CSSParserBlock : CSSParserValue {
139 | 	constructor(DOMString name, sequence<CSSParserValue> body);
140 | 	readonly attribute DOMString name; /* "[]", "{}", or "()" */
141 | 	readonly attribute FrozenArray<CSSParserValue> body;
142 | 	stringifier;
143 | };
144 | 
145 | [Exposed=Window]
146 | interface CSSParserFunction : CSSParserValue {
147 | 	constructor(DOMString name, sequence<sequence<CSSParserValue>> args);
148 | 	readonly attribute DOMString name;
149 | 	readonly attribute FrozenArray<FrozenArray<CSSParserValue>> args;
150 | 	stringifier;
151 | };
152 | 
153 | 154 | Issue: Trying to be as useful as possible, 155 | without exposing so many details that we're unable to change tokenization in the future. 156 | In particular, whitespace and delims all get parsed into DOMStrings. 157 | Am I succeeding at this goal? 158 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CSS Parser API 6 | 7 | 8 | 9 | 10 | 11 | 12 | 74 | 183 | 212 | 253 | 263 | 315 | 378 | 568 | 569 |
570 |

571 |

CSS Parser API

572 |

Unofficial Proposal Draft,

573 |
574 |
575 |
This version: 576 |
https://drafts.css-houdini.org/css-parser-api/ 577 |
Feedback: 578 |
public-houdini@w3.org with subject line “[css-parser-api] … message topic …” (archives) 579 |
Issue Tracking: 580 |
GitHub 581 |
Inline In Spec 582 |
Editors: 583 |
Tab Atkins-Bittner 584 |
Greg Whitworth 585 |
586 |
587 |
588 | 589 |
590 |
591 |
592 |

Abstract

593 |

An API exposing the CSS parser more directly, 594 | 595 | for parsing arbitrary CSS-like languages into a mildly typed representation.

596 |
597 |

Status of this document

598 |
599 |

This section describes the status of this document at the time of its publication. 600 | Other documents may supersede this document. 601 | A list of current W3C publications 602 | and the latest revision of this technical report 603 | can be found in the W3C technical reports index at https://www.w3.org/TR/.

604 |

GitHub Issues are preferred for discussion of this specification. 605 | When filing an issue, 606 | please put the text “css-parser-api” in the title, 607 | preferably like this: 608 | “[css-parser-api] …summary of comment…”. 609 | All issues and comments are archived.

610 |

This document was published 611 | by the CSS Working Group and the Technical Architecture Group.

612 |

This document was produced by groups 613 | operating under the W3C Patent Policy. 614 | W3C maintains a public list of any patent disclosures (CSS) and a public list of any patent disclosures (Technical Architecture Group) made in connection with the deliverables of each group; 615 | these pages also include instructions for disclosing a patent. 616 | An individual who has actual knowledge of a patent 617 | which the individual believes contains Essential Claim(s) must disclose the information 618 | in accordance with section 6 of the W3C Patent Policy.

619 |

This document is governed by the 15 September 2020 W3C Process Document.

620 |

621 |
622 |
623 | 656 |
657 |

1. Introduction

658 |

Common data-interchange / parsing formats are very valuable 659 | for reducing the learning curve of new languages, 660 | as users get to lean on their existing knowledge of the format when authoring 661 | and only have to newly learn the specifics of the language. 662 | This is why generic parsing formats like XML or JSON have become so popular.

663 |

The CSS language could benefit from this same treatment; 664 | a number of languages and tools rely on CSS-like syntax to express themselves, 665 | but they usually rely on ad-hoc parsing 666 | (often regex-based) 667 | which can be relatively fragile, 668 | and might break with CSS practices in interesting syntax corner cases. 669 | Similarly, CSS syntax is increasingly used in places like attribute values 670 | (such as the sizes attribute, 671 | or most of the SVG presentation attributes), 672 | and custom elements wanting to do the same thing 673 | similarly have to rely on ad-hoc parsing right now.

674 |

To help with these sorts of cases, 675 | this spec exposes the [css-syntax-3] parsing algorithms, 676 | and represents their results in a mildly-typed representation, 677 | simpler and more abstract than what [css-typed-om-1] does for CSS properties.

678 |

2. Parsing API

679 |
typedef (DOMString or ReadableStream) CSSStringSource;
 680 | typedef (DOMString or CSSStyleValue or CSSParserValue) CSSToken;
 681 | 
 682 | partial namespace CSS {
 683 |   Promise<sequence<CSSParserRule>> parseStylesheet(CSSStringSource css, optional CSSParserOptions options = {});
 684 |   Promise<sequence<CSSParserRule>> parseRuleList(CSSStringSource css, optional CSSParserOptions options = {});
 685 |   Promise<CSSParserRule> parseRule(CSSStringSource css, optional CSSParserOptions options = {});
 686 |   Promise<sequence<CSSParserRule>> parseDeclarationList(CSSStringSource css, optional CSSParserOptions options = {});
 687 |   CSSParserDeclaration parseDeclaration(DOMString css, optional CSSParserOptions options = {});
 688 |   CSSToken parseValue(DOMString css);
 689 |   sequence<CSSToken> parseValueList(DOMString css);
 690 |   sequence<sequence<CSSToken>> parseCommaValueList(DOMString css);
 691 | };
 692 | 
 693 | dictionary CSSParserOptions {
 694 |   object atRules;
 695 |   /* dict of at-rule name => at-rule type
 696 |      (contains decls or contains qualified rules) */
 697 | };
 698 | 
699 |

parseCommaValueList() is in Syntax, and thus here, 700 | because it’s actually a very common operation. 701 | It’s trivial to do yourself 702 | (just call parseValueList() and then split into an array on top-level commas), 703 | but comma-separated lists are so common 704 | that it was worthwhile to improve spec ergonomics 705 | by providing a shortcut for that functionality. 706 | Is it worth it to provide this to JS as well?

707 |

Do we handle comments? 708 | Currently I don’t; 709 | Syntax by default just drops comments, 710 | but allows an impl to preserve information about them if they want. 711 | Maybe add an option to preserve comments? 712 | If so, they can appear *anywhere*, 713 | in any API that returns a sequence.

714 |

What do we do if an unknown at-rule 715 | (not appearing in the atRules option) 716 | shows up in the results? 717 | Default to decls or rules? 718 | Or treat it more simply as just a token sequence?

719 |

Parsing stylesheets/rule lists should definitely be async, 720 | because stylesheets can be quite large. 721 | Parsing individual properties/value lists should definitely be sync, 722 | because they’re small and it would be really annoying. 723 | Parsing a single rule, tho, is unclear—is it large enough to be worth making async, 724 | or is it too annoying to be worth it?

725 |

3. Parser Values

726 |
[Exposed=Window]
 727 | interface CSSParserRule {
 728 |   /* Just a superclass. */
 729 | };
 730 | 
 731 | [Exposed=Window]
 732 | interface CSSParserAtRule : CSSParserRule {
 733 |   constructor(DOMString name, sequence<CSSToken> prelude, optional sequence<CSSParserRule>? body);
 734 |   readonly attribute DOMString name;
 735 |   readonly attribute FrozenArray<CSSParserValue> prelude;
 736 |   readonly attribute FrozenArray<CSSParserRule>? body;
 737 |   /* nullable to handle at-statements */
 738 |   stringifier;
 739 | };
 740 | 
 741 | [Exposed=Window]
 742 | interface CSSParserQualifiedRule : CSSParserRule {
 743 |   constructor(sequence<CSSToken> prelude, optional sequence<CSSParserRule>? body);
 744 |   readonly attribute FrozenArray<CSSParserValue> prelude;
 745 |   readonly attribute FrozenArray<CSSParserRule> body;
 746 |   stringifier;
 747 | };
 748 | 
 749 | [Exposed=Window]
 750 | interface CSSParserDeclaration : CSSParserRule {
 751 |   constructor(DOMString name, optional sequence<CSSParserRule> body);
 752 |   readonly attribute DOMString name;
 753 |   readonly attribute FrozenArray<CSSParserValue> body;
 754 |   stringifier;
 755 | };
 756 | 
 757 | [Exposed=Window]
 758 | interface CSSParserValue {
 759 |   /* Just a superclass. */
 760 | };
 761 | 
 762 | [Exposed=Window]
 763 | interface CSSParserBlock : CSSParserValue {
 764 |   constructor(DOMString name, sequence<CSSParserValue> body);
 765 |   readonly attribute DOMString name; /* "[]", "{}", or "()" */
 766 |   readonly attribute FrozenArray<CSSParserValue> body;
 767 |   stringifier;
 768 | };
 769 | 
 770 | [Exposed=Window]
 771 | interface CSSParserFunction : CSSParserValue {
 772 |   constructor(DOMString name, sequence<sequence<CSSParserValue>> args);
 773 |   readonly attribute DOMString name;
 774 |   readonly attribute FrozenArray<FrozenArray<CSSParserValue>> args;
 775 |   stringifier;
 776 | };
 777 | 
778 |

Trying to be as useful as possible, 779 | without exposing so many details that we’re unable to change tokenization in the future. 780 | In particular, whitespace and delims all get parsed into DOMStrings. 781 | Am I succeeding at this goal?

782 |
783 |

Conformance

784 |

Document conventions

785 |

Conformance requirements are expressed with a combination of 786 | descriptive assertions and RFC 2119 terminology. The key words “MUST”, 787 | “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, 788 | “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this 789 | document are to be interpreted as described in RFC 2119. 790 | However, for readability, these words do not appear in all uppercase 791 | letters in this specification.

792 |

All of the text of this specification is normative except sections 793 | explicitly marked as non-normative, examples, and notes. [RFC2119]

794 |

Examples in this specification are introduced with the words “for example” 795 | or are set apart from the normative text with class="example", 796 | like this:

797 |
798 | 799 |

This is an example of an informative example.

800 |
801 |

Informative notes begin with the word “Note” and are set apart from the 802 | normative text with class="note", like this:

803 |

Note, this is an informative note.

804 |

Advisements are normative sections styled to evoke special attention and are 805 | set apart from other normative text with <strong class="advisement">, like 806 | this: UAs MUST provide an accessible alternative.

807 |

Conformance classes

808 |

Conformance to this specification 809 | is defined for three conformance classes:

810 |
811 |
style sheet 812 |
A CSS 813 | style sheet. 814 |
renderer 815 |
A UA that interprets the semantics of a style sheet and renders 816 | documents that use them. 817 |
authoring tool 818 |
A UA that writes a style sheet. 819 |
820 |

A style sheet is conformant to this specification 821 | if all of its statements that use syntax defined in this module are valid 822 | according to the generic CSS grammar and the individual grammars of each 823 | feature defined in this module.

824 |

A renderer is conformant to this specification 825 | if, in addition to interpreting the style sheet as defined by the 826 | appropriate specifications, it supports all the features defined 827 | by this specification by parsing them correctly 828 | and rendering the document accordingly. However, the inability of a 829 | UA to correctly render a document due to limitations of the device 830 | does not make the UA non-conformant. (For example, a UA is not 831 | required to render color on a monochrome monitor.)

832 |

An authoring tool is conformant to this specification 833 | if it writes style sheets that are syntactically correct according to the 834 | generic CSS grammar and the individual grammars of each feature in 835 | this module, and meet all other conformance requirements of style sheets 836 | as described in this module.

837 |

Partial implementations

838 |

So that authors can exploit the forward-compatible parsing rules to 839 | assign fallback values, CSS renderers must treat as invalid (and ignore 840 | as appropriate) any at-rules, properties, property values, keywords, 841 | and other syntactic constructs for which they have no usable level of 842 | support. In particular, user agents must not selectively 843 | ignore unsupported component values and honor supported values in a single 844 | multi-value property declaration: if any value is considered invalid 845 | (as unsupported values must be), CSS requires that the entire declaration 846 | be ignored.

847 |

Implementations of Unstable and Proprietary Features

848 |

To avoid clashes with future stable CSS features, 849 | the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

850 |

Non-experimental implementations

851 |

Once a specification reaches the Candidate Recommendation stage, 852 | non-experimental implementations are possible, and implementors should 853 | release an unprefixed implementation of any CR-level feature they 854 | can demonstrate to be correctly implemented according to spec.

855 |

To establish and maintain the interoperability of CSS across 856 | implementations, the CSS Working Group requests that non-experimental 857 | CSS renderers submit an implementation report (and, if necessary, the 858 | testcases used for that implementation report) to the W3C before 859 | releasing an unprefixed implementation of any CSS features. Testcases 860 | submitted to W3C are subject to review and correction by the CSS 861 | Working Group.

862 |

Further information on submitting testcases and implementation reports 863 | can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. 864 | Questions should be directed to the public-css-testsuite@w3.org mailing list.

865 | 866 |

Index

867 |

Terms defined by this specification

868 | 946 | 952 | 958 | 964 | 970 | 977 | 983 | 989 | 995 | 1001 | 1008 |

Terms defined by reference

1009 |
    1010 |
  • 1011 | [css-typed-om-1] defines the following terms: 1012 |
      1013 |
    • CSSStyleValue 1014 |
    1015 |
  • 1016 | [cssom-1] defines the following terms: 1017 |
      1018 |
    • CSS 1019 |
    1020 |
  • 1021 | [HTML] defines the following terms: 1022 |
      1023 |
    • sizes 1024 |
    1025 |
  • 1026 | [STREAMS] defines the following terms: 1027 |
      1028 |
    • ReadableStream 1029 |
    1030 |
  • 1031 | [WebIDL] defines the following terms: 1032 |
      1033 |
    • DOMString 1034 |
    • Exposed 1035 |
    • FrozenArray 1036 |
    • Promise 1037 |
    • object 1038 |
    • sequence 1039 |
    1040 |
1041 |

References

1042 |

Normative References

1043 |
1044 |
[CSS-SYNTAX-3] 1045 |
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 16 July 2019. CR. URL: https://www.w3.org/TR/css-syntax-3/ 1046 |
[CSS-TYPED-OM-1] 1047 |
Shane Stephens; Tab Atkins Jr.; Naina Raisinghani. CSS Typed OM Level 1. 10 April 2018. WD. URL: https://www.w3.org/TR/css-typed-om-1/ 1048 |
[CSSOM-1] 1049 |
Simon Pieters; Glenn Adams. CSS Object Model (CSSOM). 17 March 2016. WD. URL: https://www.w3.org/TR/cssom-1/ 1050 |
[HTML] 1051 |
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/ 1052 |
[RFC2119] 1053 |
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119 1054 |
[STREAMS] 1055 |
Adam Rice; Domenic Denicola; 吉野剛史 (Takeshi Yoshino). Streams Standard. Living Standard. URL: https://streams.spec.whatwg.org/ 1056 |
[WebIDL] 1057 |
Boris Zbarsky. Web IDL. 15 December 2016. ED. URL: https://heycam.github.io/webidl/ 1058 |
1059 |

IDL Index

1060 |
typedef (DOMString or ReadableStream) CSSStringSource;
1061 | typedef (DOMString or CSSStyleValue or CSSParserValue) CSSToken;
1062 | 
1063 | partial namespace CSS {
1064 |   Promise<sequence<CSSParserRule>> parseStylesheet(CSSStringSource css, optional CSSParserOptions options = {});
1065 |   Promise<sequence<CSSParserRule>> parseRuleList(CSSStringSource css, optional CSSParserOptions options = {});
1066 |   Promise<CSSParserRule> parseRule(CSSStringSource css, optional CSSParserOptions options = {});
1067 |   Promise<sequence<CSSParserRule>> parseDeclarationList(CSSStringSource css, optional CSSParserOptions options = {});
1068 |   CSSParserDeclaration parseDeclaration(DOMString css, optional CSSParserOptions options = {});
1069 |   CSSToken parseValue(DOMString css);
1070 |   sequence<CSSToken> parseValueList(DOMString css);
1071 |   sequence<sequence<CSSToken>> parseCommaValueList(DOMString css);
1072 | };
1073 | 
1074 | dictionary CSSParserOptions {
1075 |   object atRules;
1076 |   /* dict of at-rule name => at-rule type
1077 |      (contains decls or contains qualified rules) */
1078 | };
1079 | 
1080 | [Exposed=Window]
1081 | interface CSSParserRule {
1082 |   /* Just a superclass. */
1083 | };
1084 | 
1085 | [Exposed=Window]
1086 | interface CSSParserAtRule : CSSParserRule {
1087 |   constructor(DOMString name, sequence<CSSToken> prelude, optional sequence<CSSParserRule>? body);
1088 |   readonly attribute DOMString name;
1089 |   readonly attribute FrozenArray<CSSParserValue> prelude;
1090 |   readonly attribute FrozenArray<CSSParserRule>? body;
1091 |   /* nullable to handle at-statements */
1092 |   stringifier;
1093 | };
1094 | 
1095 | [Exposed=Window]
1096 | interface CSSParserQualifiedRule : CSSParserRule {
1097 |   constructor(sequence<CSSToken> prelude, optional sequence<CSSParserRule>? body);
1098 |   readonly attribute FrozenArray<CSSParserValue> prelude;
1099 |   readonly attribute FrozenArray<CSSParserRule> body;
1100 |   stringifier;
1101 | };
1102 | 
1103 | [Exposed=Window]
1104 | interface CSSParserDeclaration : CSSParserRule {
1105 |   constructor(DOMString name, optional sequence<CSSParserRule> body);
1106 |   readonly attribute DOMString name;
1107 |   readonly attribute FrozenArray<CSSParserValue> body;
1108 |   stringifier;
1109 | };
1110 | 
1111 | [Exposed=Window]
1112 | interface CSSParserValue {
1113 |   /* Just a superclass. */
1114 | };
1115 | 
1116 | [Exposed=Window]
1117 | interface CSSParserBlock : CSSParserValue {
1118 |   constructor(DOMString name, sequence<CSSParserValue> body);
1119 |   readonly attribute DOMString name; /* "[]", "{}", or "()" */
1120 |   readonly attribute FrozenArray<CSSParserValue> body;
1121 |   stringifier;
1122 | };
1123 | 
1124 | [Exposed=Window]
1125 | interface CSSParserFunction : CSSParserValue {
1126 |   constructor(DOMString name, sequence<sequence<CSSParserValue>> args);
1127 |   readonly attribute DOMString name;
1128 |   readonly attribute FrozenArray<FrozenArray<CSSParserValue>> args;
1129 |   stringifier;
1130 | };
1131 | 
1132 | 
1133 |

Issues Index

1134 |
1135 |
parseCommaValueList() is in Syntax, and thus here, 1136 | because it’s actually a very common operation. 1137 | It’s trivial to do yourself 1138 | (just call parseValueList() and then split into an array on top-level commas), 1139 | but comma-separated lists are so common 1140 | that it was worthwhile to improve spec ergonomics 1141 | by providing a shortcut for that functionality. 1142 | Is it worth it to provide this to JS as well?
1143 |
Do we handle comments? 1144 | Currently I don’t; 1145 | Syntax by default just drops comments, 1146 | but allows an impl to preserve information about them if they want. 1147 | Maybe add an option to preserve comments? 1148 | If so, they can appear *anywhere*, 1149 | in any API that returns a sequence.
1150 |
What do we do if an unknown at-rule 1151 | (not appearing in the atRules option) 1152 | shows up in the results? 1153 | Default to decls or rules? 1154 | Or treat it more simply as just a token sequence?
1155 |
Parsing stylesheets/rule lists should definitely be async, 1156 | because stylesheets can be quite large. 1157 | Parsing individual properties/value lists should definitely be sync, 1158 | because they’re small and it would be really annoying. 1159 | Parsing a single rule, tho, is unclear—is it large enough to be worth making async, 1160 | or is it too annoying to be worth it?
1161 |
Trying to be as useful as possible, 1162 | without exposing so many details that we’re unable to change tokenization in the future. 1163 | In particular, whitespace and delims all get parsed into DOMStrings. 1164 | Am I succeeding at this goal?
1165 |
1166 | 1172 | 1179 | 1185 | 1191 | 1197 | 1203 | 1210 | 1216 | 1223 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [80485] 3 | , "contacts": ["marcoscaceres"] 4 | , "repo-type": "cg-report" 5 | } 6 | --------------------------------------------------------------------------------