pax_global_header00006660000000000000000000000064145646411270014524gustar00rootroot0000000000000052 comment=f67f5e388cc4d3bd8de5f6f1ec4cefc8fdf34811 css-1.1.8/000077500000000000000000000000001456464112700123235ustar00rootroot00000000000000css-1.1.8/.gitignore000066400000000000000000000000531456464112700143110ustar00rootroot00000000000000/node_modules/ /src/parser.* .tern-* /dist css-1.1.8/.npmignore000066400000000000000000000000161456464112700143170ustar00rootroot00000000000000/node_modules css-1.1.8/CHANGELOG.md000066400000000000000000000072601456464112700141410ustar00rootroot00000000000000## 1.1.8 (2024-02-19) ### Bug fixes Follow the standard, allowing digits in unit identifiers. ## 1.1.7 (2024-01-08) ### Bug fixes Correctly parse properties with a space before the colon. ## 1.1.6 (2024-01-01) ### Bug fixes Add support for bracketed grid line names. ## 1.1.5 (2023-12-28) ### Bug fixes Tag comments and strings as isolating for the purpose of bidirectional text. ## 1.1.4 (2023-11-09) ### Bug fixes Fix parsing of `&` selectors in descendant selectors. Allow identifiers to contain backslash escapes. ## 1.1.3 (2023-07-03) ### Bug fixes Comments are now parsed to end of file if no closing `*/` is found. Make the package work with new TS resolution styles. ## 1.1.2 (2023-05-15) ### Bug fixes Make keyframe selector parsing more flexible to support timeline ranges. Allow multiple comma-separated keyframe selectors per keyframe. ## 1.1.1 (2022-12-02) ### Bug fixes The `Styles` top rule now also recognizes nested rules. ## 1.1.0 (2022-11-25) ### Bug fixes Don't emit an error node when the input is empty. Export a Styles top-level rule for parsing lists of properties ### New features The new `Styles` top-level rule can be used to parse semicolon-separated lists of properties. ## 1.0.1 (2022-10-10) ### Bug fixes Add support for the `is`, `where`, `host-context`, `nth-last-of-type`, and `nth-of-type` pseudo classes. Apply a consistent highlighting tag (`definitionKeyword`) to all @ keywords. ## 1.0.0 (2022-06-06) ### New features First stable version. ## 0.16.0 (2022-04-20) ### Breaking changes Move to 0.16 serialized parser format. ### New features The parser now includes syntax highlighting information in its node types. ## 0.15.2 (2021-09-24) ### Bug fixes Distinguish between variable names and other names. Fix the name of nodes for the `selector` keyword (which by accident was `callee` before). ## 0.15.1 (2021-08-31) ### Bug fixes Fix parsing of selector arguments to pseudo selectors. ## 0.15.0 (2021-08-11) ### Breaking changes The module's name changed from `lezer-css` to `@lezer/css`. Upgrade to the 0.15.0 lezer interfaces. ## 0.13.1 (2020-12-04) ### Bug fixes Fix versions of lezer packages depended on. ## 0.13.0 (2020-12-04) ## 0.12.0 (2020-10-23) ### Breaking changes Adjust to changed serialized parser format. ## 0.11.1 (2020-09-26) ### Bug fixes Fix lezer depencency versions ## 0.11.0 (2020-09-26) ### Breaking changes Follow change in serialized parser format. ## 0.10.1 (2020-09-02) ### Bug fixes Fix a conflicting pair of tokens that the generator previously didn't catch. ## 0.10.0 (2020-08-07) ### Breaking changes Upgrade to 0.10 parser serialization ## 0.9.0 (2020-06-08) ### Breaking changes Upgrade to 0.9 parser serialization ## 0.8.3 (2020-04-09) ### Bug fixes Regenerate parser with a fix in lezer-generator so that the top node prop is properly assigned. ## 0.8.2 (2020-04-01) ### Bug fixes Make the package load as an ES module on node ## 0.8.1 (2020-02-28) ### New features Provide an ES module file. ## 0.8.0 (2020-02-03) ### New features Follow 0.8.0 release of the library. ## 0.7.0 (2020-01-20) ### Breaking changes Use the lezer 0.7.0 parser format. ## 0.5.2 (2020-01-15) ### Bug fixes Regenerate with lezer-generator 0.5.2 to avoid cyclic forced reductions. ## 0.5.1 (2019-10-22) ### Bug fixes Fix top prop missing from build output. ## 0.5.0 (2019-10-22) ### Breaking changes Move from `lang` to `top` prop on document node. ## 0.4.0 (2019-09-10) ### Breaking changes Adjust to 0.4.0 parse table format. ## 0.3.0 (2019-08-22) ### New features Go back to node names, add props, follow changes in grammar syntax. ## 0.2.0 (2019-08-02) ### New Features First documented release. css-1.1.8/LICENSE000066400000000000000000000021311456464112700133250ustar00rootroot00000000000000MIT License Copyright (C) 2018 by Marijn Haverbeke and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. css-1.1.8/README.md000066400000000000000000000002161456464112700136010ustar00rootroot00000000000000# @lezer/css This is a CSS grammar for the [lezer](https://lezer.codemirror.net/) parser system. The code is licensed under an MIT license. css-1.1.8/dist/000077500000000000000000000000001456464112700132665ustar00rootroot00000000000000css-1.1.8/dist/index.d.cts000066400000000000000000000001021456464112700153230ustar00rootroot00000000000000import {LRParser} from "@lezer/lr" export const parser: LRParser css-1.1.8/dist/index.d.ts000066400000000000000000000001021456464112700151600ustar00rootroot00000000000000import {LRParser} from "@lezer/lr" export const parser: LRParser css-1.1.8/package.json000066400000000000000000000017301456464112700146120ustar00rootroot00000000000000{ "name": "@lezer/css", "version": "1.1.8", "description": "lezer-based CSS grammar", "main": "dist/index.cjs", "type": "module", "exports": { "import": "./dist/index.js", "require": "./dist/index.cjs" }, "module": "dist/index.js", "types": "dist/index.d.ts", "author": "Marijn Haverbeke ", "license": "MIT", "devDependencies": { "@lezer/generator": "^1.0.0", "mocha": "^10.2.0", "rollup": "^2.52.2", "@rollup/plugin-node-resolve": "^9.0.0" }, "dependencies": { "@lezer/common": "^1.2.0", "@lezer/lr": "^1.0.0", "@lezer/highlight": "^1.0.0" }, "repository": { "type" : "git", "url" : "https://github.com/lezer-parser/css.git" }, "scripts": { "build": "lezer-generator src/css.grammar -o src/parser && rollup -c", "build-debug": "lezer-generator src/css.grammar --names -o src/parser && rollup -c", "prepare": "npm run build", "test": "mocha test/test-*.js" } } css-1.1.8/rollup.config.js000066400000000000000000000004621456464112700154440ustar00rootroot00000000000000import {nodeResolve} from "@rollup/plugin-node-resolve" export default { input: "./src/parser.js", output: [{ format: "cjs", file: "./dist/index.cjs" }, { format: "es", file: "./dist/index.js" }], external(id) { return !/^[\.\/]/.test(id) }, plugins: [ nodeResolve() ] } css-1.1.8/src/000077500000000000000000000000001456464112700131125ustar00rootroot00000000000000css-1.1.8/src/css.grammar000066400000000000000000000111741456464112700152560ustar00rootroot00000000000000@precedence { attribute @left, structure @left, valueOp @left } @skip { whitespace | Comment } @top StyleSheet { item* } @top Styles { blockContent } item { RuleSet | ImportStatement | MediaStatement | CharsetStatement | NamespaceStatement | KeyframesStatement | SupportsStatement | AtRule } RuleSet { selector ("," selector)* Block } ImportStatement { @specialize[@name=import] value commaSep ";" } MediaStatement { @specialize[@name=media] commaSep Block } CharsetStatement { @specialize[@name=charset] value ";" } NamespaceStatement { @specialize[@name=namespace] NamespaceName { identifier }? (StringLiteral | CallLiteral) ";" } KeyframesStatement { @specialize[@name=keyframes] KeyframeName { identifier | StringLiteral } KeyframeList } KeyframeSelector { KeyframeRangeName { identifier } NumberLiteral? | NumberLiteral } KeyframeList { "{" (KeyframeSelector ("," KeyframeSelector)* Block)* "}" } SupportsStatement { @specialize[@name=supports] query Block } AtRule { AtKeyword commaSep (";" | Block) } Block { "{" blockContent "}" } blockContent { ~item item* (Declaration (";" ~item item* Declaration?)*)? } selector { UniversalSelector | TagSelector { ~item TagName { identifier ~item } } | NestingSelector | ClassSelector { selector? !attribute "." ClassName { identifier } } | PseudoClassSelector { selector? !attribute (":" | "::") ( PseudoClassName { identifier } | pseudoClassWithArg ArgList | PseudoClassName { callee } ArgList) } | IdSelector { selector? !attribute "#" IdName { identifier } } | AttributeSelector { selector? !attribute "[" AttributeName { identifier } (MatchOp value)? "]" } | ChildSelector { selector !structure ChildOp selector } | DescendantSelector { selector !structure descendantOp selector } | SiblingSelector { selector !structure SiblingOp selector } } pseudoClassWithArg { @specialize[@name=PseudoClassName] } NumberLiteral { numberLiteralInner Unit? } ArgList { "(" commaSep ")" } Declaration { (PropertyName { identifier ~item } | VariableName) ":" value (","? value)* Important? } query { KeywordQuery { identifier } | FeatureQuery { "(" FeatureName { identifier } ":" value+ ")" } | BinaryQuery { query !valueOp LogicOp query } | UnaryQuery { @specialize[@name=UnaryQueryOp] query } | ParenthesizedQuery { "(" query ")" } | SelectorQuery { @specialize[@name=selector] "(" selector ")" } } value { VariableName | ValueName { identifier } | ParenthesizedValue { "(" value ")" } | ColorLiteral | NumberLiteral | StringLiteral | BinaryExpression { value !valueOp BinOp value } | CallExpression | CallLiteral | LineNames { "[" LineName { identifier }* "]" } } CallLiteral { @specialize[@name=CallTag] "(" (ParenthesizedContent | StringLiteral) ")" } CallExpression { Callee { callee } ArgList } @skip {} { Comment[isolate] { "/*" (commentContent | commentLineBreak)* commentEnd } } @local tokens { commentEnd { "*/" | @eof } commentLineBreak { "\n" } @else commentContent } commaSep { "" | value ("," value)* } @external tokens descendant from "./tokens" { descendantOp } @external tokens unitToken from "./tokens" { Unit } @external tokens identifiers from "./tokens" { callee, identifier, VariableName } @tokens { UniversalSelector { "*" } NestingSelector { "&" } AtKeyword { "@" @asciiLetter (@asciiLetter | @digit | "-")* } MatchOp { $[~^|*$]? "=" } ChildOp { ">" ">"? } SiblingOp { "~" | "+" } LogicOp { "and" | "or" } BinOp { $[+\-*/] } Important { "!important" } whitespace { @whitespace+ } hexDigit { @digit | $[a-fA-F] } ParenthesizedContent { !['")] ![)]+ } @precedence { whitespace, ParenthesizedContent, "/*" } ColorLiteral { "#" hexDigit hexDigit hexDigit (hexDigit (hexDigit hexDigit (hexDigit hexDigit)?)?)? } numberLiteralInner { ("+" | "-")? (@digit+ ("." @digit*)? | "." @digit+) (("e" | "E") ("+" | "-")? @digit+)? } @precedence { numberLiteralInner, BinOp, SiblingOp } StringLiteral[isolate] { "\"" (!["\n\\] | "\\" _)* "\"" | "'" (!['\n\\] | "\\" _)* "'" } "#" ":" "::" ";" "," "(" ")" "[" "]" "{" "}" } @external propSource cssHighlighting from "./highlight" @detectDelim css-1.1.8/src/highlight.js000066400000000000000000000021731456464112700154220ustar00rootroot00000000000000import {styleTags, tags as t} from "@lezer/highlight" export const cssHighlighting = styleTags({ "AtKeyword import charset namespace keyframes media supports": t.definitionKeyword, "from to selector": t.keyword, NamespaceName: t.namespace, KeyframeName: t.labelName, KeyframeRangeName: t.operatorKeyword, TagName: t.tagName, ClassName: t.className, PseudoClassName: t.constant(t.className), IdName: t.labelName, "FeatureName PropertyName": t.propertyName, AttributeName: t.attributeName, NumberLiteral: t.number, KeywordQuery: t.keyword, UnaryQueryOp: t.operatorKeyword, "CallTag ValueName": t.atom, VariableName: t.variableName, Callee: t.operatorKeyword, Unit: t.unit, "UniversalSelector NestingSelector": t.definitionOperator, MatchOp: t.compareOperator, "ChildOp SiblingOp, LogicOp": t.logicOperator, BinOp: t.arithmeticOperator, Important: t.modifier, Comment: t.blockComment, ColorLiteral: t.color, "ParenthesizedContent StringLiteral": t.string, ":": t.punctuation, "PseudoOp #": t.derefOperator, "; ,": t.separator, "( )": t.paren, "[ ]": t.squareBracket, "{ }": t.brace }) css-1.1.8/src/tokens.js000066400000000000000000000041031456464112700147510ustar00rootroot00000000000000/* Hand-written tokenizers for CSS tokens that can't be expressed by Lezer's built-in tokenizer. */ import {ExternalTokenizer} from "@lezer/lr" import {callee, identifier, VariableName, descendantOp, Unit} from "./parser.terms.js" const space = [9, 10, 11, 12, 13, 32, 133, 160, 5760, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232, 8233, 8239, 8287, 12288] const colon = 58, parenL = 40, underscore = 95, bracketL = 91, dash = 45, period = 46, hash = 35, percent = 37, ampersand = 38, backslash = 92, newline = 10 function isAlpha(ch) { return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 161 } function isDigit(ch) { return ch >= 48 && ch <= 57 } export const identifiers = new ExternalTokenizer((input, stack) => { for (let inside = false, dashes = 0, i = 0;; i++) { let {next} = input if (isAlpha(next) || next == dash || next == underscore || (inside && isDigit(next))) { if (!inside && (next != dash || i > 0)) inside = true if (dashes === i && next == dash) dashes++ input.advance() } else if (next == backslash && input.peek(1) != newline) { input.advance() if (input.next > -1) input.advance() inside = true } else { if (inside) input.acceptToken(next == parenL ? callee : dashes == 2 && stack.canShift(VariableName) ? VariableName : identifier) break } } }) export const descendant = new ExternalTokenizer(input => { if (space.includes(input.peek(-1))) { let {next} = input if (isAlpha(next) || next == underscore || next == hash || next == period || next == bracketL || next == colon && isAlpha(input.peek(1)) || next == dash || next == ampersand) input.acceptToken(descendantOp) } }) export const unitToken = new ExternalTokenizer(input => { if (!space.includes(input.peek(-1))) { let {next} = input if (next == percent) { input.advance(); input.acceptToken(Unit) } if (isAlpha(next)) { do { input.advance() } while (isAlpha(input.next) || isDigit(input.next)) input.acceptToken(Unit) } } }) css-1.1.8/test/000077500000000000000000000000001456464112700133025ustar00rootroot00000000000000css-1.1.8/test/declarations.txt000066400000000000000000000100071456464112700165110ustar00rootroot00000000000000# Function calls a { color: rgba(0, 255, 0, 0.5); } ==> StyleSheet( RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,CallExpression(Callee,ArgList(NumberLiteral,NumberLiteral,NumberLiteral,NumberLiteral)))))) # Calls where each argument has multiple values div { background: repeating-linear-gradient(red, orange 50px); clip-path: polygon(50% 0%, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0% 50%, 40% 40%) } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,CallExpression(Callee,ArgList(ValueName,ValueName,NumberLiteral(Unit)))), Declaration(PropertyName,CallExpression(Callee,ArgList( NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit), NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit), NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit), NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit))))))) # Color literals a { b: #fafd04; c: #fafd0401; } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,ColorLiteral), Declaration(PropertyName,ColorLiteral)))) # Numbers a { b: 0.5%; c: 5em; margin: 10E3px; margin: -456.8px; margin: -0.0px; } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,NumberLiteral(Unit)), Declaration(PropertyName,NumberLiteral(Unit)), Declaration(PropertyName,NumberLiteral(Unit)), Declaration(PropertyName,NumberLiteral(Unit)), Declaration(PropertyName,NumberLiteral(Unit))))) # Binary arithmetic operators a { width: calc(100% - 80px); aspect-ratio: 1/2; font-size: calc(10px + (56 - 10) * ((100vw - 320px) / (1920 - 320))); } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,CallExpression(Callee,ArgList(BinaryExpression(NumberLiteral(Unit),BinOp,NumberLiteral(Unit))))), Declaration(PropertyName,BinaryExpression(NumberLiteral,BinOp,NumberLiteral)), Declaration(PropertyName,CallExpression(Callee,ArgList( BinaryExpression(BinaryExpression(NumberLiteral(Unit),BinOp,ParenthesizedValue( BinaryExpression(NumberLiteral,BinOp,NumberLiteral))),BinOp,ParenthesizedValue( BinaryExpression(ParenthesizedValue(BinaryExpression(NumberLiteral(Unit),BinOp,NumberLiteral(Unit))),BinOp, ParenthesizedValue(BinaryExpression(NumberLiteral,BinOp,NumberLiteral))))))))))) # Strings a { b: ''; c: '\'hi\''; } ==> StyleSheet(RuleSet(TagSelector(TagName),Block(Declaration(PropertyName,StringLiteral),Declaration(PropertyName,StringLiteral)))) # URLs a { b: url(http://something-else?foo=bar); } ==> StyleSheet(RuleSet(TagSelector(TagName),Block(Declaration(PropertyName,CallLiteral(CallTag,ParenthesizedContent))))) # Important declarations a { b: c !important; } ==> StyleSheet(RuleSet(TagSelector(TagName),Block(Declaration(PropertyName,ValueName,Important)))) # Comments right after numbers a { shape-outside: circle(20em/*=*/at 50% 50%); shape-outside: inset(1em, 1em, 1em, 1em); } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,CallExpression(Callee,ArgList(NumberLiteral(Unit),Comment,ValueName,NumberLiteral(Unit),NumberLiteral(Unit)))), Declaration(PropertyName,CallExpression(Callee,ArgList(NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit),NumberLiteral(Unit))))))) # Unfinished rule a { foo: 2 ==> StyleSheet(RuleSet(TagSelector(TagName),Block(Declaration(PropertyName,NumberLiteral),⚠))) # Variable names foo { --my-variable: white; color: var(--my-variable); } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(VariableName,ValueName), Declaration(PropertyName,CallExpression(Callee,ArgList(VariableName)))))) # Space before colon div { color : red; .x :active { color : blue; } } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( Declaration(PropertyName,ValueName), RuleSet(DescendantSelector(ClassSelector(ClassName),PseudoClassSelector(PseudoClassName)),Block( Declaration(PropertyName,ValueName)))))) css-1.1.8/test/selector.txt000066400000000000000000000057561456464112700157000ustar00rootroot00000000000000# Universal selectors * {} ==> StyleSheet(RuleSet(UniversalSelector,Block)) # Type selectors div, span {} h1, h2, h3, h4 {} ==> StyleSheet( RuleSet(TagSelector(TagName),TagSelector(TagName),Block), RuleSet(TagSelector(TagName),TagSelector(TagName),TagSelector(TagName),TagSelector(TagName),Block)) # Class selectors .class-a {} div.class-b, .class-c.class-d {} ==> StyleSheet( RuleSet(ClassSelector(ClassName),Block), RuleSet(ClassSelector(TagSelector(TagName),ClassName),ClassSelector(ClassSelector(ClassName),ClassName),Block)) # Id selectors #some-id, a#another-id {} ==> StyleSheet(RuleSet(IdSelector(IdName),IdSelector(TagSelector(TagName),IdName),Block)) # Attribute selectors [a] {} [b=c] {} [d~=e] {} a[b] {} ==> StyleSheet( RuleSet(AttributeSelector(AttributeName),Block), RuleSet(AttributeSelector(AttributeName,MatchOp,ValueName),Block), RuleSet(AttributeSelector(AttributeName,MatchOp,ValueName),Block), RuleSet(AttributeSelector(TagSelector(TagName),AttributeName),Block)) # Pseudo-class selectors a:hover {} :nth-child(2) {} ==> StyleSheet( RuleSet(PseudoClassSelector(TagSelector(TagName),":",PseudoClassName),Block), RuleSet(PseudoClassSelector(":",PseudoClassName,ArgList(NumberLiteral)),Block)) # Pseudo-element selectors a::first-line {} ==> StyleSheet(RuleSet(PseudoClassSelector(TagSelector(TagName),"::",PseudoClassName),Block)) # Child selectors a > b {} c > d > e {} ==> StyleSheet( RuleSet(ChildSelector(TagSelector(TagName),ChildOp,TagSelector(TagName)),Block), RuleSet(ChildSelector(ChildSelector(TagSelector(TagName),ChildOp,TagSelector(TagName)),ChildOp,TagSelector(TagName)),Block)) # Descendant selectors a b {} c d e {} ==> StyleSheet( RuleSet(DescendantSelector(TagSelector(TagName),TagSelector(TagName)),Block), RuleSet(DescendantSelector(DescendantSelector(TagSelector(TagName),TagSelector(TagName)),TagSelector(TagName)),Block)) # Nesting selectors a { &.b {} & c {} c & {} & > d {} } ==> StyleSheet(RuleSet(TagSelector(TagName),Block( RuleSet(ClassSelector(NestingSelector,ClassName),Block), RuleSet(DescendantSelector(NestingSelector,TagSelector(TagName)),Block), RuleSet(DescendantSelector(TagSelector(TagName), NestingSelector),Block), RuleSet(ChildSelector(NestingSelector,ChildOp,TagSelector(TagName)),Block)))) # Sibling selectors a.b ~ c.d {} .e.f + .g.h {} ==> StyleSheet( RuleSet(SiblingSelector(ClassSelector(TagSelector(TagName),ClassName),SiblingOp,ClassSelector(TagSelector(TagName),ClassName)),Block), RuleSet(SiblingSelector(ClassSelector(ClassSelector(ClassName),ClassName),SiblingOp,ClassSelector(ClassSelector(ClassName),ClassName)),Block)) # The :not selector a:not(:hover) {} .b:not(c > .d) {} ==> StyleSheet( RuleSet(PseudoClassSelector(TagSelector(TagName),":",PseudoClassName,ArgList(PseudoClassSelector(":",PseudoClassName))),Block), RuleSet(PseudoClassSelector(ClassSelector(ClassName),":",PseudoClassName,ArgList(ChildSelector(TagSelector(TagName),ChildOp,ClassSelector(ClassName)))),Block)) css-1.1.8/test/statements.txt000066400000000000000000000132771456464112700162440ustar00rootroot00000000000000# Empty stylesheets /* Just a comment */ ==> StyleSheet(Comment) # Import statements @import url("fineprint.css") print; @import url("bluish.css") speech; @import 'custom.css'; @import url("chrome://communicator/skin/"); @import "common.css" screen; ==> StyleSheet( ImportStatement(import,CallLiteral(CallTag,StringLiteral),KeywordQuery), ImportStatement(import,CallLiteral(CallTag,StringLiteral),KeywordQuery), ImportStatement(import,StringLiteral), ImportStatement(import,CallLiteral(CallTag,StringLiteral)), ImportStatement(import,StringLiteral,KeywordQuery)) # Namespace statements /* Default namespace */ @namespace url(XML-namespace-URL); @namespace "XML-namespace-URL"; @namespace url(http://www.w3.org/1999/xhtml); @namespace svg url(http://www.w3.org/2000/svg); /* Prefixed namespace */ @namespace prefix url(XML-namespace-URL); @namespace prefix "XML-namespace-URL"; ==> StyleSheet( Comment, NamespaceStatement(namespace,CallLiteral(CallTag,ParenthesizedContent)), NamespaceStatement(namespace,StringLiteral), NamespaceStatement(namespace,CallLiteral(CallTag,ParenthesizedContent)), NamespaceStatement(namespace,NamespaceName,CallLiteral(CallTag,ParenthesizedContent)), Comment, NamespaceStatement(namespace,NamespaceName,CallLiteral(CallTag,ParenthesizedContent)), NamespaceStatement(namespace,NamespaceName,StringLiteral)) # Keyframes statements @keyframes important1 { from { margin-top: 50px; } 50%, 60% { margin-top: 150px !important; } /* ignored */ to { margin-top: 100px; } } ==> StyleSheet(KeyframesStatement(keyframes,KeyframeName,KeyframeList( KeyframeSelector(KeyframeRangeName),Block(Declaration(PropertyName,NumberLiteral(Unit))), KeyframeSelector(NumberLiteral(Unit)),KeyframeSelector(NumberLiteral(Unit)),Block( Declaration(PropertyName,NumberLiteral(Unit),Important)), Comment, KeyframeSelector(KeyframeRangeName),Block(Declaration(PropertyName,NumberLiteral(Unit)))))) # Keyframes statements with range @keyframes anim-1 { entry 0% { margin-top: 50px; } entry 100% { margin-top: 50px; } exit 0% { margin-top: 50px; } exit 100% { margin-top: 50px; } } ==> StyleSheet(KeyframesStatement(keyframes,KeyframeName,KeyframeList( KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),Block(Declaration(PropertyName,NumberLiteral(Unit))), KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),Block(Declaration(PropertyName,NumberLiteral(Unit))), KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),Block(Declaration(PropertyName,NumberLiteral(Unit))), KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),Block(Declaration(PropertyName,NumberLiteral(Unit)))))) # Keyframes statements with range and multiple keyframe selectors @keyframes fade-in-out-animation { entry 0%, exit 100% { opacity: 0 } entry 100%, exit 0% { opacity: 1 } } ==> StyleSheet(KeyframesStatement(keyframes,KeyframeName,KeyframeList( KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),Block( Declaration(PropertyName,NumberLiteral)), KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),KeyframeSelector(KeyframeRangeName,NumberLiteral(Unit)),Block( Declaration(PropertyName,NumberLiteral))))) # Media statements @media screen and (min-width: 30em) and (orientation: landscape) {} @media (min-height: 680px), screen and (orientation: portrait) {} @media not all and (monochrome) {} @media only screen {} ==> StyleSheet( MediaStatement(media,BinaryQuery(BinaryQuery(KeywordQuery,LogicOp,FeatureQuery(FeatureName,NumberLiteral(Unit))),LogicOp, FeatureQuery(FeatureName,ValueName)),Block), MediaStatement(media,FeatureQuery(FeatureName,NumberLiteral(Unit)),BinaryQuery(KeywordQuery,LogicOp,FeatureQuery(FeatureName,ValueName)),Block), MediaStatement(media,UnaryQuery(UnaryQueryOp,BinaryQuery(KeywordQuery,LogicOp,ParenthesizedQuery(KeywordQuery))),Block), MediaStatement(media,UnaryQuery(UnaryQueryOp,KeywordQuery),Block)) # Supports statements @supports (animation-name: test) { div { animation-name: test; } } @supports (transform-style: preserve) or (-moz-transform-style: preserve) {} @supports not ((text-align-last: justify) or (-moz-text-align-last: justify)) {} @supports not selector(:matches(a, b)) {} ==> StyleSheet( SupportsStatement(supports,FeatureQuery(FeatureName,ValueName),Block(RuleSet(TagSelector(TagName),Block(Declaration(PropertyName,ValueName))))), SupportsStatement(supports,BinaryQuery(FeatureQuery(FeatureName,ValueName),LogicOp,FeatureQuery(FeatureName,ValueName)),Block), SupportsStatement(supports,UnaryQuery(UnaryQueryOp,ParenthesizedQuery( BinaryQuery(FeatureQuery(FeatureName,ValueName),LogicOp,FeatureQuery(FeatureName,ValueName)))),Block), SupportsStatement(supports,UnaryQuery(UnaryQueryOp,SelectorQuery(selector,PseudoClassSelector(PseudoClassName,ArgList(TagSelector(TagName),TagSelector(TagName))))),Block)) # Charset statements @charset "utf-8"; ==> StyleSheet(CharsetStatement(charset,StringLiteral)) # Other at-statements @font-face { font-family: "Open Sans"; src: url("/a") format("woff2"), url("/b/c") format("woff"); } ==> StyleSheet(AtRule(AtKeyword,Block( Declaration(PropertyName,StringLiteral), Declaration(PropertyName,CallLiteral(CallTag,StringLiteral),CallExpression(Callee,ArgList(StringLiteral)), CallLiteral(CallTag,StringLiteral),CallExpression(Callee,ArgList(StringLiteral)))))) # Unterminated Comment p {} /* div {} ==> StyleSheet(RuleSet(TagSelector(TagName),Block),Comment) # Escaped identifiers #foo\ bar { --weird\\var: 5px; width: var(--weird\\var); } ==> StyleSheet(RuleSet(IdSelector(IdName),Block( Declaration(VariableName,NumberLiteral(Unit)), Declaration(PropertyName,CallExpression(Callee,ArgList(VariableName)))))) css-1.1.8/test/test-css.js000066400000000000000000000010121456464112700153770ustar00rootroot00000000000000import {parser} from "../dist/index.js" import {fileTests} from "@lezer/generator/dist/test" import * as fs from "fs" import * as path from "path" import {fileURLToPath} from "url" let caseDir = path.dirname(fileURLToPath(import.meta.url)) for (let file of fs.readdirSync(caseDir)) { if (!/\.txt$/.test(file)) continue let name = /^[^\.]*/.exec(file)[0] describe(name, () => { for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file)) it(name, () => run(parser)) }) }