@eslint/css-tree 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +194 -0
- package/cjs/convertor/create.cjs +32 -0
- package/cjs/convertor/index.cjs +8 -0
- package/cjs/data-patch.cjs +7 -0
- package/cjs/data.cjs +120 -0
- package/cjs/definition-syntax/SyntaxError.cjs +16 -0
- package/cjs/definition-syntax/generate.cjs +139 -0
- package/cjs/definition-syntax/index.cjs +13 -0
- package/cjs/definition-syntax/parse.cjs +556 -0
- package/cjs/definition-syntax/scanner.cjs +113 -0
- package/cjs/definition-syntax/walk.cjs +57 -0
- package/cjs/generator/create.cjs +102 -0
- package/cjs/generator/index.cjs +8 -0
- package/cjs/generator/sourceMap.cjs +96 -0
- package/cjs/generator/token-before.cjs +170 -0
- package/cjs/index.cjs +65 -0
- package/cjs/lexer/Lexer.cjs +517 -0
- package/cjs/lexer/error.cjs +128 -0
- package/cjs/lexer/generic-an-plus-b.cjs +235 -0
- package/cjs/lexer/generic-const.cjs +12 -0
- package/cjs/lexer/generic-urange.cjs +149 -0
- package/cjs/lexer/generic.cjs +589 -0
- package/cjs/lexer/index.cjs +7 -0
- package/cjs/lexer/match-graph.cjs +530 -0
- package/cjs/lexer/match.cjs +632 -0
- package/cjs/lexer/prepare-tokens.cjs +54 -0
- package/cjs/lexer/search.cjs +65 -0
- package/cjs/lexer/structure.cjs +173 -0
- package/cjs/lexer/trace.cjs +73 -0
- package/cjs/lexer/units.cjs +38 -0
- package/cjs/parser/SyntaxError.cjs +74 -0
- package/cjs/parser/create.cjs +378 -0
- package/cjs/parser/index.cjs +8 -0
- package/cjs/parser/parse-selector.cjs +8 -0
- package/cjs/parser/sequence.cjs +47 -0
- package/cjs/syntax/atrule/container.cjs +32 -0
- package/cjs/syntax/atrule/font-face.cjs +12 -0
- package/cjs/syntax/atrule/import.cjs +101 -0
- package/cjs/syntax/atrule/index.cjs +27 -0
- package/cjs/syntax/atrule/layer.cjs +16 -0
- package/cjs/syntax/atrule/media.cjs +16 -0
- package/cjs/syntax/atrule/nest.cjs +16 -0
- package/cjs/syntax/atrule/page.cjs +16 -0
- package/cjs/syntax/atrule/scope.cjs +16 -0
- package/cjs/syntax/atrule/starting-style.cjs +12 -0
- package/cjs/syntax/atrule/supports.cjs +16 -0
- package/cjs/syntax/config/generator.cjs +9 -0
- package/cjs/syntax/config/lexer.cjs +14 -0
- package/cjs/syntax/config/mix.cjs +126 -0
- package/cjs/syntax/config/parser-selector.cjs +19 -0
- package/cjs/syntax/config/parser.cjs +49 -0
- package/cjs/syntax/config/walker.cjs +9 -0
- package/cjs/syntax/create.cjs +58 -0
- package/cjs/syntax/function/expression.cjs +11 -0
- package/cjs/syntax/function/var.cjs +43 -0
- package/cjs/syntax/index.cjs +14 -0
- package/cjs/syntax/node/AnPlusB.cjs +293 -0
- package/cjs/syntax/node/Atrule.cjs +103 -0
- package/cjs/syntax/node/AtrulePrelude.cjs +52 -0
- package/cjs/syntax/node/AttributeSelector.cjs +148 -0
- package/cjs/syntax/node/Block.cjs +96 -0
- package/cjs/syntax/node/Brackets.cjs +38 -0
- package/cjs/syntax/node/CDC.cjs +26 -0
- package/cjs/syntax/node/CDO.cjs +26 -0
- package/cjs/syntax/node/ClassSelector.cjs +31 -0
- package/cjs/syntax/node/Combinator.cjs +61 -0
- package/cjs/syntax/node/Comment.cjs +40 -0
- package/cjs/syntax/node/Condition.cjs +120 -0
- package/cjs/syntax/node/Declaration.cjs +166 -0
- package/cjs/syntax/node/DeclarationList.cjs +62 -0
- package/cjs/syntax/node/Dimension.cjs +30 -0
- package/cjs/syntax/node/Feature.cjs +101 -0
- package/cjs/syntax/node/FeatureFunction.cjs +67 -0
- package/cjs/syntax/node/FeatureRange.cjs +133 -0
- package/cjs/syntax/node/Function.cjs +45 -0
- package/cjs/syntax/node/GeneralEnclosed.cjs +68 -0
- package/cjs/syntax/node/Hash.cjs +30 -0
- package/cjs/syntax/node/IdSelector.cjs +33 -0
- package/cjs/syntax/node/Identifier.cjs +25 -0
- package/cjs/syntax/node/Layer.cjs +35 -0
- package/cjs/syntax/node/LayerList.cjs +43 -0
- package/cjs/syntax/node/MediaQuery.cjs +100 -0
- package/cjs/syntax/node/MediaQueryList.cjs +41 -0
- package/cjs/syntax/node/NestingSelector.cjs +29 -0
- package/cjs/syntax/node/Nth.cjs +54 -0
- package/cjs/syntax/node/Number.cjs +25 -0
- package/cjs/syntax/node/Operator.cjs +28 -0
- package/cjs/syntax/node/Parentheses.cjs +38 -0
- package/cjs/syntax/node/Percentage.cjs +25 -0
- package/cjs/syntax/node/PseudoClassSelector.cjs +67 -0
- package/cjs/syntax/node/PseudoElementSelector.cjs +69 -0
- package/cjs/syntax/node/Ratio.cjs +71 -0
- package/cjs/syntax/node/Raw.cjs +48 -0
- package/cjs/syntax/node/Rule.cjs +58 -0
- package/cjs/syntax/node/Scope.cjs +69 -0
- package/cjs/syntax/node/Selector.cjs +38 -0
- package/cjs/syntax/node/SelectorList.cjs +43 -0
- package/cjs/syntax/node/String.cjs +26 -0
- package/cjs/syntax/node/StyleSheet.cjs +83 -0
- package/cjs/syntax/node/SupportsDeclaration.cjs +38 -0
- package/cjs/syntax/node/TypeSelector.cjs +59 -0
- package/cjs/syntax/node/UnicodeRange.cjs +158 -0
- package/cjs/syntax/node/Url.cjs +54 -0
- package/cjs/syntax/node/Value.cjs +26 -0
- package/cjs/syntax/node/WhiteSpace.cjs +34 -0
- package/cjs/syntax/node/index-generate.cjs +103 -0
- package/cjs/syntax/node/index-parse-selector.cjs +39 -0
- package/cjs/syntax/node/index-parse.cjs +103 -0
- package/cjs/syntax/node/index.cjs +103 -0
- package/cjs/syntax/pseudo/index.cjs +60 -0
- package/cjs/syntax/pseudo/lang.cjs +37 -0
- package/cjs/syntax/scope/atrulePrelude.cjs +9 -0
- package/cjs/syntax/scope/default.cjs +76 -0
- package/cjs/syntax/scope/index.cjs +11 -0
- package/cjs/syntax/scope/selector.cjs +88 -0
- package/cjs/syntax/scope/value.cjs +29 -0
- package/cjs/tokenizer/OffsetToLocation.cjs +91 -0
- package/cjs/tokenizer/TokenStream.cjs +358 -0
- package/cjs/tokenizer/adopt-buffer.cjs +13 -0
- package/cjs/tokenizer/char-code-definitions.cjs +236 -0
- package/cjs/tokenizer/index.cjs +554 -0
- package/cjs/tokenizer/names.cjs +32 -0
- package/cjs/tokenizer/types.cjs +57 -0
- package/cjs/tokenizer/utils.cjs +261 -0
- package/cjs/utils/List.cjs +473 -0
- package/cjs/utils/clone.cjs +25 -0
- package/cjs/utils/create-custom-error.cjs +18 -0
- package/cjs/utils/ident.cjs +102 -0
- package/cjs/utils/index.cjs +20 -0
- package/cjs/utils/names.cjs +113 -0
- package/cjs/utils/string.cjs +99 -0
- package/cjs/utils/url.cjs +108 -0
- package/cjs/version.cjs +5 -0
- package/cjs/walker/create.cjs +291 -0
- package/cjs/walker/index.cjs +8 -0
- package/data/patch.json +874 -0
- package/dist/csstree.esm.js +12 -0
- package/dist/csstree.js +12 -0
- package/dist/data.cjs +1341 -0
- package/dist/data.js +1341 -0
- package/dist/version.cjs +1 -0
- package/dist/version.js +1 -0
- package/lib/convertor/create.js +28 -0
- package/lib/convertor/index.js +4 -0
- package/lib/data-patch.js +6 -0
- package/lib/data.js +118 -0
- package/lib/definition-syntax/SyntaxError.js +12 -0
- package/lib/definition-syntax/generate.js +135 -0
- package/lib/definition-syntax/index.js +4 -0
- package/lib/definition-syntax/parse.js +552 -0
- package/lib/definition-syntax/scanner.js +109 -0
- package/lib/definition-syntax/walk.js +53 -0
- package/lib/generator/create.js +97 -0
- package/lib/generator/index.js +4 -0
- package/lib/generator/sourceMap.js +92 -0
- package/lib/generator/token-before.js +182 -0
- package/lib/index.d.ts +3016 -0
- package/lib/index.js +30 -0
- package/lib/lexer/Lexer.js +511 -0
- package/lib/lexer/error.js +123 -0
- package/lib/lexer/generic-an-plus-b.js +238 -0
- package/lib/lexer/generic-const.js +8 -0
- package/lib/lexer/generic-urange.js +151 -0
- package/lib/lexer/generic.js +622 -0
- package/lib/lexer/index.js +1 -0
- package/lib/lexer/match-graph.js +527 -0
- package/lib/lexer/match.js +630 -0
- package/lib/lexer/prepare-tokens.js +50 -0
- package/lib/lexer/search.js +61 -0
- package/lib/lexer/structure.js +169 -0
- package/lib/lexer/trace.js +66 -0
- package/lib/lexer/units.js +27 -0
- package/lib/parser/SyntaxError.js +70 -0
- package/lib/parser/create.js +388 -0
- package/lib/parser/index.js +4 -0
- package/lib/parser/parse-selector.js +4 -0
- package/lib/parser/sequence.js +43 -0
- package/lib/syntax/atrule/container.js +28 -0
- package/lib/syntax/atrule/font-face.js +8 -0
- package/lib/syntax/atrule/import.js +104 -0
- package/lib/syntax/atrule/index.js +23 -0
- package/lib/syntax/atrule/layer.js +12 -0
- package/lib/syntax/atrule/media.js +12 -0
- package/lib/syntax/atrule/nest.js +12 -0
- package/lib/syntax/atrule/page.js +12 -0
- package/lib/syntax/atrule/scope.js +12 -0
- package/lib/syntax/atrule/starting-style.js +8 -0
- package/lib/syntax/atrule/supports.js +12 -0
- package/lib/syntax/config/generator.js +5 -0
- package/lib/syntax/config/lexer.js +10 -0
- package/lib/syntax/config/mix.js +122 -0
- package/lib/syntax/config/parser-selector.js +15 -0
- package/lib/syntax/config/parser.js +45 -0
- package/lib/syntax/config/walker.js +5 -0
- package/lib/syntax/create.js +55 -0
- package/lib/syntax/function/expression.js +7 -0
- package/lib/syntax/function/var.js +39 -0
- package/lib/syntax/index.js +10 -0
- package/lib/syntax/node/AnPlusB.js +292 -0
- package/lib/syntax/node/Atrule.js +100 -0
- package/lib/syntax/node/AtrulePrelude.js +47 -0
- package/lib/syntax/node/AttributeSelector.js +147 -0
- package/lib/syntax/node/Block.js +95 -0
- package/lib/syntax/node/Brackets.js +35 -0
- package/lib/syntax/node/CDC.js +19 -0
- package/lib/syntax/node/CDO.js +19 -0
- package/lib/syntax/node/ClassSelector.js +24 -0
- package/lib/syntax/node/Combinator.js +54 -0
- package/lib/syntax/node/Comment.js +33 -0
- package/lib/syntax/node/Condition.js +123 -0
- package/lib/syntax/node/Declaration.js +165 -0
- package/lib/syntax/node/DeclarationList.js +62 -0
- package/lib/syntax/node/Dimension.js +23 -0
- package/lib/syntax/node/Feature.js +103 -0
- package/lib/syntax/node/FeatureFunction.js +63 -0
- package/lib/syntax/node/FeatureRange.js +133 -0
- package/lib/syntax/node/Function.js +41 -0
- package/lib/syntax/node/GeneralEnclosed.js +66 -0
- package/lib/syntax/node/Hash.js +23 -0
- package/lib/syntax/node/IdSelector.js +26 -0
- package/lib/syntax/node/Identifier.js +18 -0
- package/lib/syntax/node/Layer.js +28 -0
- package/lib/syntax/node/LayerList.js +36 -0
- package/lib/syntax/node/MediaQuery.js +102 -0
- package/lib/syntax/node/MediaQueryList.js +34 -0
- package/lib/syntax/node/NestingSelector.js +22 -0
- package/lib/syntax/node/Nth.js +47 -0
- package/lib/syntax/node/Number.js +18 -0
- package/lib/syntax/node/Operator.js +21 -0
- package/lib/syntax/node/Parentheses.js +34 -0
- package/lib/syntax/node/Percentage.js +18 -0
- package/lib/syntax/node/PseudoClassSelector.js +65 -0
- package/lib/syntax/node/PseudoElementSelector.js +66 -0
- package/lib/syntax/node/Ratio.js +68 -0
- package/lib/syntax/node/Raw.js +41 -0
- package/lib/syntax/node/Rule.js +51 -0
- package/lib/syntax/node/Scope.js +66 -0
- package/lib/syntax/node/Selector.js +31 -0
- package/lib/syntax/node/SelectorList.js +35 -0
- package/lib/syntax/node/String.js +19 -0
- package/lib/syntax/node/StyleSheet.js +82 -0
- package/lib/syntax/node/SupportsDeclaration.js +34 -0
- package/lib/syntax/node/TypeSelector.js +52 -0
- package/lib/syntax/node/UnicodeRange.js +156 -0
- package/lib/syntax/node/Url.js +52 -0
- package/lib/syntax/node/Value.js +19 -0
- package/lib/syntax/node/WhiteSpace.js +27 -0
- package/lib/syntax/node/index-generate.js +49 -0
- package/lib/syntax/node/index-parse-selector.js +17 -0
- package/lib/syntax/node/index-parse.js +49 -0
- package/lib/syntax/node/index.js +49 -0
- package/lib/syntax/pseudo/index.js +56 -0
- package/lib/syntax/pseudo/lang.js +33 -0
- package/lib/syntax/scope/atrulePrelude.js +5 -0
- package/lib/syntax/scope/default.js +85 -0
- package/lib/syntax/scope/index.js +3 -0
- package/lib/syntax/scope/selector.js +94 -0
- package/lib/syntax/scope/value.js +25 -0
- package/lib/tokenizer/OffsetToLocation.js +87 -0
- package/lib/tokenizer/TokenStream.js +366 -0
- package/lib/tokenizer/adopt-buffer.js +9 -0
- package/lib/tokenizer/char-code-definitions.js +212 -0
- package/lib/tokenizer/index.js +513 -0
- package/lib/tokenizer/names.js +28 -0
- package/lib/tokenizer/types.js +28 -0
- package/lib/tokenizer/utils.js +254 -0
- package/lib/utils/List.js +469 -0
- package/lib/utils/clone.js +21 -0
- package/lib/utils/create-custom-error.js +14 -0
- package/lib/utils/ident.js +101 -0
- package/lib/utils/index.js +6 -0
- package/lib/utils/names.js +106 -0
- package/lib/utils/string.js +99 -0
- package/lib/utils/url.js +108 -0
- package/lib/version.js +5 -0
- package/lib/walker/create.js +287 -0
- package/lib/walker/index.js +4 -0
- package/package.json +133 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (C) 2016-2024 by Roman Dvornov
|
|
2
|
+
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in
|
|
12
|
+
all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
20
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<img align="right" width="111" height="111" alt="CSSTree logo" src="assets/csstree-logo-rounded.svg" />
|
|
2
|
+
|
|
3
|
+
# CSSTree (ESLint Fork)
|
|
4
|
+
|
|
5
|
+
CSSTree is a tool set for CSS: [fast](https://github.com/postcss/benchmark) detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations. The main goal is to be efficient and W3C spec compliant, with focus on CSS analyzing and source-to-source transforming tasks.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Detailed parsing with an adjustable level of detail**
|
|
10
|
+
|
|
11
|
+
By default CSSTree parses CSS as detailed as possible, i.e. each single logical part is representing with its own AST node (see [AST format](docs/ast.md) for all possible node types). The parsing detail level can be changed through [parser options](docs/parsing.md#parsesource-options), for example, you can disable parsing of selectors or declaration values for component parts.
|
|
12
|
+
|
|
13
|
+
- **Tolerant to errors by design**
|
|
14
|
+
|
|
15
|
+
Parser behaves as [spec says](https://www.w3.org/TR/css-syntax-3/#error-handling): "When errors occur in CSS, the parser attempts to recover gracefully, throwing away only the minimum amount of content before returning to parsing as normal". The only thing the parser departs from the specification is that it doesn't throw away bad content, but wraps it in a special node type (`Raw`) that allows processing it later.
|
|
16
|
+
|
|
17
|
+
- **Fast and efficient**
|
|
18
|
+
|
|
19
|
+
CSSTree is created with focus on performance and effective memory consumption. Therefore it's [one of the fastest CSS parsers](https://github.com/postcss/benchmark) at the moment.
|
|
20
|
+
|
|
21
|
+
- **Syntax validation**
|
|
22
|
+
|
|
23
|
+
The built-in lexer can test CSS against syntaxes defined by W3C. CSSTree uses [mdn/data](https://github.com/mdn/data/) as a basis for lexer's dictionaries and extends it with vendor specific and legacy syntaxes. Lexer can only check the declaration values and at-rules currently, but this feature will be extended to other parts of the CSS in the future.
|
|
24
|
+
|
|
25
|
+
## Projects using CSSTree
|
|
26
|
+
|
|
27
|
+
- [Svelte](https://github.com/sveltejs/svelte) – Cybernetically enhanced web apps
|
|
28
|
+
- [SVGO](https://github.com/svg/svgo) – Node.js tool for optimizing SVG files
|
|
29
|
+
- [CSSO](https://github.com/css/csso) – CSS minifier with structural optimizations
|
|
30
|
+
- [NativeScript](https://github.com/NativeScript/NativeScript) – NativeScript empowers you to access native APIs from JavaScript directly
|
|
31
|
+
- [react-native-svg](https://github.com/react-native-svg/react-native-svg) – SVG library for React Native, React Native Web, and plain React web projects
|
|
32
|
+
- [penthouse](https://github.com/pocketjoso/penthouse) – Critical Path CSS Generator
|
|
33
|
+
- [Bit](https://github.com/teambit/bit) – Bit is the platform for collaborating on components
|
|
34
|
+
- and more...
|
|
35
|
+
|
|
36
|
+
## Documentation
|
|
37
|
+
|
|
38
|
+
- [AST format](docs/ast.md)
|
|
39
|
+
- [Parsing CSS → AST](docs/parsing.md)
|
|
40
|
+
- [parse(source[, options])](docs/parsing.md#parsesource-options)
|
|
41
|
+
- [Serialization AST → CSS](docs/generate.md)
|
|
42
|
+
- [generate(ast[, options])](docs/generate.md#generateast-options)
|
|
43
|
+
- [AST traversal](docs/traversal.md)
|
|
44
|
+
- [walk(ast, options)](docs/traversal.md#walkast-options)
|
|
45
|
+
- [find(ast, fn)](docs/traversal.md#findast-fn)
|
|
46
|
+
- [findLast(ast, fn)](docs/traversal.md#findlastast-fn)
|
|
47
|
+
- [findAll(ast, fn)](docs/traversal.md#findallast-fn)
|
|
48
|
+
- [Util functions](docs/utils.md)
|
|
49
|
+
- Value encoding & decoding
|
|
50
|
+
- [property(name)](docs/utils.md#propertyname)
|
|
51
|
+
- [keyword(name)](docs/utils.md#keywordname)
|
|
52
|
+
- [ident](docs/utils.md#ident)
|
|
53
|
+
- [string](docs/utils.md#string)
|
|
54
|
+
- [url](docs/utils.md#url)
|
|
55
|
+
- [List class](docs/list.md)
|
|
56
|
+
- AST transforming
|
|
57
|
+
- [clone(ast)](docs/utils.md#cloneast)
|
|
58
|
+
- [fromPlainObject(object)](docs/utils.md#fromplainobjectobject)
|
|
59
|
+
- [toPlainObject(ast)](docs/utils.md#toplainobjectast)
|
|
60
|
+
- [Value Definition Syntax](docs/definition-syntax.md)
|
|
61
|
+
- [parse(source)](docs/definition-syntax.md#parsesource)
|
|
62
|
+
- [walk(node, options, context)](docs/definition-syntax.md#walknode-options-context)
|
|
63
|
+
- [generate(node, options)](docs/definition-syntax.md#generatenode-options)
|
|
64
|
+
- [AST format](docs/definition-syntax.md#ast-format)
|
|
65
|
+
|
|
66
|
+
## Tools
|
|
67
|
+
|
|
68
|
+
* [AST Explorer](https://astexplorer.net/#/gist/244e2fb4da940df52bf0f4b94277db44/e79aff44611020b22cfd9708f3a99ce09b7d67a8) – explore CSSTree AST format with zero setup
|
|
69
|
+
* [CSS syntax reference](https://csstree.github.io/docs/syntax.html)
|
|
70
|
+
* [CSS syntax validator](https://csstree.github.io/docs/validator.html)
|
|
71
|
+
|
|
72
|
+
## Related projects
|
|
73
|
+
|
|
74
|
+
* [csstree-validator](https://github.com/csstree/validator) – NPM package to validate CSS
|
|
75
|
+
* [stylelint-csstree-validator](https://github.com/csstree/stylelint-validator) – plugin for stylelint to validate CSS
|
|
76
|
+
* [Grunt plugin](https://github.com/sergejmueller/grunt-csstree-validator)
|
|
77
|
+
* [Gulp plugin](https://github.com/csstree/gulp-csstree)
|
|
78
|
+
* [Sublime plugin](https://github.com/csstree/SublimeLinter-contrib-csstree)
|
|
79
|
+
* [VS Code plugin](https://github.com/csstree/vscode-plugin)
|
|
80
|
+
* [Atom plugin](https://github.com/csstree/atom-plugin)
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
Install with npm:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
npm install @eslint/css-tree
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Basic usage:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import * as csstree from '@eslint/css-tree';
|
|
94
|
+
|
|
95
|
+
// parse CSS to AST
|
|
96
|
+
const ast = csstree.parse('.example { world: "!" }');
|
|
97
|
+
|
|
98
|
+
// traverse AST and modify it
|
|
99
|
+
csstree.walk(ast, (node) => {
|
|
100
|
+
if (node.type === 'ClassSelector' && node.name === 'example') {
|
|
101
|
+
node.name = 'hello';
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// generate CSS from AST
|
|
106
|
+
console.log(csstree.generate(ast));
|
|
107
|
+
// .hello{world:"!"}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Syntax matching:
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
// parse CSS to AST as a declaration value
|
|
114
|
+
const ast = csstree.parse('red 1px solid', { context: 'value' });
|
|
115
|
+
|
|
116
|
+
// match to syntax of `border` property
|
|
117
|
+
const matchResult = csstree.lexer.matchProperty('border', ast);
|
|
118
|
+
|
|
119
|
+
// check first value node is a <color>
|
|
120
|
+
console.log(matchResult.isType(ast.children.first, 'color'));
|
|
121
|
+
// true
|
|
122
|
+
|
|
123
|
+
// get a type list matched to a node
|
|
124
|
+
console.log(matchResult.getTrace(ast.children.first));
|
|
125
|
+
// [ { type: 'Property', name: 'border' },
|
|
126
|
+
// { type: 'Type', name: 'color' },
|
|
127
|
+
// { type: 'Type', name: 'named-color' },
|
|
128
|
+
// { type: 'Keyword', name: 'red' } ]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Exports
|
|
132
|
+
|
|
133
|
+
Is it possible to import just a needed part of library like a parser or a walker. That's might useful for loading time or bundle size optimisations.
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
import * as tokenizer from '@eslint/css-tree/tokenizer';
|
|
137
|
+
import * as parser from '@eslint/css-tree/parser';
|
|
138
|
+
import * as walker from '@eslint/css-tree/walker';
|
|
139
|
+
import * as lexer from '@eslint/css-tree/lexer';
|
|
140
|
+
import * as definitionSyntax from '@eslint/css-tree/definition-syntax';
|
|
141
|
+
import * as data from '@eslint/css-tree/definition-syntax-data';
|
|
142
|
+
import * as dataPatch from '@eslint/css-tree/definition-syntax-data-patch';
|
|
143
|
+
import * as utils from '@eslint/css-tree/utils';
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Using in a browser
|
|
147
|
+
|
|
148
|
+
Bundles are available for use in a browser:
|
|
149
|
+
|
|
150
|
+
- `dist/csstree.js` – minified IIFE with `csstree` as global
|
|
151
|
+
```html
|
|
152
|
+
<script src="node_modules/@eslint/css-tree/dist/csstree.js"></script>
|
|
153
|
+
<script>
|
|
154
|
+
csstree.parse('.example { color: green }');
|
|
155
|
+
</script>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
- `dist/csstree.esm.js` – minified ES module
|
|
159
|
+
```html
|
|
160
|
+
<script type="module">
|
|
161
|
+
import { parse } from 'node_modules/@eslint/css-tree/dist/csstree.esm.js'
|
|
162
|
+
parse('.example { color: green }');
|
|
163
|
+
</script>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
One of CDN services like `unpkg` or `jsDelivr` can be used. By default (for short path) a ESM version is exposing. For IIFE version a full path to a bundle should be specified:
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<!-- ESM -->
|
|
170
|
+
<script type="module">
|
|
171
|
+
import * as csstree from 'https://cdn.jsdelivr.net/npm/@eslint/css-tree';
|
|
172
|
+
import * as csstree from 'https://unpkg.com/@eslint/css-tree';
|
|
173
|
+
</script>
|
|
174
|
+
|
|
175
|
+
<!-- IIFE with an export to global -->
|
|
176
|
+
<script src="https://cdn.jsdelivr.net/npm/@eslint/css-tree/dist/csstree.js"></script>
|
|
177
|
+
<script src="https://unpkg.com/@eslint/css-tree/dist/csstree.js"></script>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Top level API
|
|
181
|
+
|
|
182
|
+

|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
## Branch Setup and Development
|
|
190
|
+
|
|
191
|
+
* `main` - the default branch for new development in the fork repo
|
|
192
|
+
* `upstream` - kept in sync with `csstree/csstree`
|
|
193
|
+
|
|
194
|
+
When merging in changes from `csstree/csstree`, sync `upstream` in the GitHub UI (if possible). Then send a pull request to `main` to work through any merge conflicts.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const List = require('../utils/List.cjs');
|
|
4
|
+
|
|
5
|
+
function createConvertor(walk) {
|
|
6
|
+
return {
|
|
7
|
+
fromPlainObject(ast) {
|
|
8
|
+
walk(ast, {
|
|
9
|
+
enter(node) {
|
|
10
|
+
if (node.children && node.children instanceof List.List === false) {
|
|
11
|
+
node.children = new List.List().fromArray(node.children);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return ast;
|
|
17
|
+
},
|
|
18
|
+
toPlainObject(ast) {
|
|
19
|
+
walk(ast, {
|
|
20
|
+
leave(node) {
|
|
21
|
+
if (node.children && node.children instanceof List.List) {
|
|
22
|
+
node.children = node.children.toArray();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return ast;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
exports.createConvertor = createConvertor;
|
package/cjs/data.cjs
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const dataPatch = require('./data-patch.cjs');
|
|
4
|
+
|
|
5
|
+
const mdnAtrules = require('mdn-data/css/at-rules.json');
|
|
6
|
+
const mdnProperties = require('mdn-data/css/properties.json');
|
|
7
|
+
const mdnSyntaxes = require('mdn-data/css/syntaxes.json');
|
|
8
|
+
|
|
9
|
+
const hasOwn = Object.hasOwn || ((object, property) => Object.prototype.hasOwnProperty.call(object, property));
|
|
10
|
+
const extendSyntax = /^\s*\|\s*/;
|
|
11
|
+
|
|
12
|
+
function preprocessAtrules(dict) {
|
|
13
|
+
const result = Object.create(null);
|
|
14
|
+
|
|
15
|
+
for (const [atruleName, atrule] of Object.entries(dict)) {
|
|
16
|
+
let descriptors = null;
|
|
17
|
+
|
|
18
|
+
if (atrule.descriptors) {
|
|
19
|
+
descriptors = Object.create(null);
|
|
20
|
+
|
|
21
|
+
for (const [name, descriptor] of Object.entries(atrule.descriptors)) {
|
|
22
|
+
descriptors[name] = descriptor.syntax;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
result[atruleName.substr(1)] = {
|
|
27
|
+
prelude: atrule.syntax.trim().replace(/\{(.|\s)+\}/, '').match(/^@\S+\s+([^;\{]*)/)[1].trim() || null,
|
|
28
|
+
descriptors
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function patchDictionary(dict, patchDict) {
|
|
36
|
+
const result = Object.create(null);
|
|
37
|
+
|
|
38
|
+
// copy all syntaxes for an original dict
|
|
39
|
+
for (const [key, value] of Object.entries(dict)) {
|
|
40
|
+
if (value) {
|
|
41
|
+
result[key] = value.syntax || value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// apply a patch
|
|
46
|
+
for (const key of Object.keys(patchDict)) {
|
|
47
|
+
if (hasOwn(dict, key)) {
|
|
48
|
+
if (patchDict[key].syntax) {
|
|
49
|
+
result[key] = extendSyntax.test(patchDict[key].syntax)
|
|
50
|
+
? result[key] + ' ' + patchDict[key].syntax.trim()
|
|
51
|
+
: patchDict[key].syntax;
|
|
52
|
+
} else {
|
|
53
|
+
delete result[key];
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
if (patchDict[key].syntax) {
|
|
57
|
+
result[key] = patchDict[key].syntax.replace(extendSyntax, '');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function preprocessPatchAtrulesDescritors(declarations) {
|
|
66
|
+
const result = {};
|
|
67
|
+
|
|
68
|
+
for (const [key, value] of Object.entries(declarations || {})) {
|
|
69
|
+
result[key] = typeof value === 'string'
|
|
70
|
+
? { syntax: value }
|
|
71
|
+
: value;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function patchAtrules(dict, patchDict) {
|
|
78
|
+
const result = {};
|
|
79
|
+
|
|
80
|
+
// copy all syntaxes for an original dict
|
|
81
|
+
for (const key in dict) {
|
|
82
|
+
if (patchDict[key] === null) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const atrulePatch = patchDict[key] || {};
|
|
87
|
+
|
|
88
|
+
result[key] = {
|
|
89
|
+
prelude: key in patchDict && 'prelude' in atrulePatch
|
|
90
|
+
? atrulePatch.prelude
|
|
91
|
+
: dict[key].prelude || null,
|
|
92
|
+
descriptors: patchDictionary(
|
|
93
|
+
dict[key].descriptors || {},
|
|
94
|
+
preprocessPatchAtrulesDescritors(atrulePatch.descriptors)
|
|
95
|
+
)
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// apply a patch
|
|
100
|
+
for (const [key, atrulePatch] of Object.entries(patchDict)) {
|
|
101
|
+
if (atrulePatch && !hasOwn(dict, key)) {
|
|
102
|
+
result[key] = {
|
|
103
|
+
prelude: atrulePatch.prelude || null,
|
|
104
|
+
descriptors: atrulePatch.descriptors
|
|
105
|
+
? patchDictionary({}, preprocessPatchAtrulesDescritors(atrulePatch.descriptors))
|
|
106
|
+
: null
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const definitions = {
|
|
115
|
+
types: patchDictionary(mdnSyntaxes, dataPatch.types),
|
|
116
|
+
atrules: patchAtrules(preprocessAtrules(mdnAtrules), dataPatch.atrules),
|
|
117
|
+
properties: patchDictionary(mdnProperties, dataPatch.properties)
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
module.exports = definitions;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const createCustomError = require('../utils/create-custom-error.cjs');
|
|
4
|
+
|
|
5
|
+
function SyntaxError(message, input, offset) {
|
|
6
|
+
return Object.assign(createCustomError.createCustomError('SyntaxError', message), {
|
|
7
|
+
input,
|
|
8
|
+
offset,
|
|
9
|
+
rawMessage: message,
|
|
10
|
+
message: message + '\n' +
|
|
11
|
+
' ' + input + '\n' +
|
|
12
|
+
'--' + new Array((offset || input.length) + 1).join('-') + '^'
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.SyntaxError = SyntaxError;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function noop(value) {
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function generateMultiplier(multiplier) {
|
|
8
|
+
const { min, max, comma } = multiplier;
|
|
9
|
+
|
|
10
|
+
if (min === 0 && max === 0) {
|
|
11
|
+
return comma ? '#?' : '*';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (min === 0 && max === 1) {
|
|
15
|
+
return '?';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (min === 1 && max === 0) {
|
|
19
|
+
return comma ? '#' : '+';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (min === 1 && max === 1) {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
(comma ? '#' : '') +
|
|
28
|
+
(min === max
|
|
29
|
+
? '{' + min + '}'
|
|
30
|
+
: '{' + min + ',' + (max !== 0 ? max : '') + '}'
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function generateTypeOpts(node) {
|
|
36
|
+
switch (node.type) {
|
|
37
|
+
case 'Range':
|
|
38
|
+
return (
|
|
39
|
+
' [' +
|
|
40
|
+
(node.min === null ? '-∞' : node.min) +
|
|
41
|
+
',' +
|
|
42
|
+
(node.max === null ? '∞' : node.max) +
|
|
43
|
+
']'
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
default:
|
|
47
|
+
throw new Error('Unknown node type `' + node.type + '`');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function generateSequence(node, decorate, forceBraces, compact) {
|
|
52
|
+
const combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
|
|
53
|
+
const result = node.terms
|
|
54
|
+
.map(term => internalGenerate(term, decorate, forceBraces, compact))
|
|
55
|
+
.join(combinator);
|
|
56
|
+
|
|
57
|
+
if (node.explicit || forceBraces) {
|
|
58
|
+
return (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function internalGenerate(node, decorate, forceBraces, compact) {
|
|
65
|
+
let result;
|
|
66
|
+
|
|
67
|
+
switch (node.type) {
|
|
68
|
+
case 'Group':
|
|
69
|
+
result =
|
|
70
|
+
generateSequence(node, decorate, forceBraces, compact) +
|
|
71
|
+
(node.disallowEmpty ? '!' : '');
|
|
72
|
+
break;
|
|
73
|
+
|
|
74
|
+
case 'Multiplier':
|
|
75
|
+
// return since node is a composition
|
|
76
|
+
return (
|
|
77
|
+
internalGenerate(node.term, decorate, forceBraces, compact) +
|
|
78
|
+
decorate(generateMultiplier(node), node)
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
case 'Boolean':
|
|
82
|
+
result = '<boolean-expr[' + internalGenerate(node.term, decorate, forceBraces, compact) + ']>';
|
|
83
|
+
break;
|
|
84
|
+
|
|
85
|
+
case 'Type':
|
|
86
|
+
result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
case 'Property':
|
|
90
|
+
result = '<\'' + node.name + '\'>';
|
|
91
|
+
break;
|
|
92
|
+
|
|
93
|
+
case 'Keyword':
|
|
94
|
+
result = node.name;
|
|
95
|
+
break;
|
|
96
|
+
|
|
97
|
+
case 'AtKeyword':
|
|
98
|
+
result = '@' + node.name;
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
case 'Function':
|
|
102
|
+
result = node.name + '(';
|
|
103
|
+
break;
|
|
104
|
+
|
|
105
|
+
case 'String':
|
|
106
|
+
case 'Token':
|
|
107
|
+
result = node.value;
|
|
108
|
+
break;
|
|
109
|
+
|
|
110
|
+
case 'Comma':
|
|
111
|
+
result = ',';
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
default:
|
|
115
|
+
throw new Error('Unknown node type `' + node.type + '`');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return decorate(result, node);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function generate(node, options) {
|
|
122
|
+
let decorate = noop;
|
|
123
|
+
let forceBraces = false;
|
|
124
|
+
let compact = false;
|
|
125
|
+
|
|
126
|
+
if (typeof options === 'function') {
|
|
127
|
+
decorate = options;
|
|
128
|
+
} else if (options) {
|
|
129
|
+
forceBraces = Boolean(options.forceBraces);
|
|
130
|
+
compact = Boolean(options.compact);
|
|
131
|
+
if (typeof options.decorate === 'function') {
|
|
132
|
+
decorate = options.decorate;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return internalGenerate(node, decorate, forceBraces, compact);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
exports.generate = generate;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const SyntaxError = require('./SyntaxError.cjs');
|
|
4
|
+
const generate = require('./generate.cjs');
|
|
5
|
+
const parse = require('./parse.cjs');
|
|
6
|
+
const walk = require('./walk.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.SyntaxError = SyntaxError.SyntaxError;
|
|
11
|
+
exports.generate = generate.generate;
|
|
12
|
+
exports.parse = parse.parse;
|
|
13
|
+
exports.walk = walk.walk;
|