From 76cb9c2a39d477a64824a985ade40507e3bbade1 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Fri, 13 Feb 2026 21:34:48 -0800 Subject: feat(vanilla): add testing infrastructure and tests (NK-wjnczv) --- vanilla/node_modules/css-tree/LICENSE | 19 + vanilla/node_modules/css-tree/README.md | 192 +++ .../node_modules/css-tree/cjs/convertor/create.cjs | 32 + .../node_modules/css-tree/cjs/convertor/index.cjs | 8 + vanilla/node_modules/css-tree/cjs/data-patch.cjs | 7 + vanilla/node_modules/css-tree/cjs/data.cjs | 120 ++ .../css-tree/cjs/definition-syntax/SyntaxError.cjs | 16 + .../css-tree/cjs/definition-syntax/generate.cjs | 139 +++ .../css-tree/cjs/definition-syntax/index.cjs | 13 + .../css-tree/cjs/definition-syntax/parse.cjs | 556 +++++++++ .../css-tree/cjs/definition-syntax/scanner.cjs | 113 ++ .../css-tree/cjs/definition-syntax/tokenizer.cjs | 59 + .../css-tree/cjs/definition-syntax/walk.cjs | 57 + .../node_modules/css-tree/cjs/generator/create.cjs | 102 ++ .../node_modules/css-tree/cjs/generator/index.cjs | 8 + .../css-tree/cjs/generator/sourceMap.cjs | 96 ++ .../css-tree/cjs/generator/token-before.cjs | 170 +++ vanilla/node_modules/css-tree/cjs/index.cjs | 65 + vanilla/node_modules/css-tree/cjs/lexer/Lexer.cjs | 517 ++++++++ vanilla/node_modules/css-tree/cjs/lexer/error.cjs | 128 ++ .../css-tree/cjs/lexer/generic-an-plus-b.cjs | 235 ++++ .../css-tree/cjs/lexer/generic-const.cjs | 12 + .../css-tree/cjs/lexer/generic-urange.cjs | 149 +++ .../node_modules/css-tree/cjs/lexer/generic.cjs | 589 +++++++++ vanilla/node_modules/css-tree/cjs/lexer/index.cjs | 7 + .../css-tree/cjs/lexer/match-graph.cjs | 530 ++++++++ vanilla/node_modules/css-tree/cjs/lexer/match.cjs | 632 ++++++++++ .../css-tree/cjs/lexer/prepare-tokens.cjs | 54 + vanilla/node_modules/css-tree/cjs/lexer/search.cjs | 65 + .../node_modules/css-tree/cjs/lexer/structure.cjs | 173 +++ vanilla/node_modules/css-tree/cjs/lexer/trace.cjs | 73 ++ vanilla/node_modules/css-tree/cjs/lexer/units.cjs | 38 + .../css-tree/cjs/parser/SyntaxError.cjs | 74 ++ .../node_modules/css-tree/cjs/parser/create.cjs | 340 +++++ vanilla/node_modules/css-tree/cjs/parser/index.cjs | 8 + .../css-tree/cjs/parser/parse-selector.cjs | 8 + .../node_modules/css-tree/cjs/parser/sequence.cjs | 47 + .../css-tree/cjs/syntax/atrule/container.cjs | 32 + .../css-tree/cjs/syntax/atrule/font-face.cjs | 12 + .../css-tree/cjs/syntax/atrule/import.cjs | 101 ++ .../css-tree/cjs/syntax/atrule/index.cjs | 27 + .../css-tree/cjs/syntax/atrule/layer.cjs | 16 + .../css-tree/cjs/syntax/atrule/media.cjs | 16 + .../css-tree/cjs/syntax/atrule/nest.cjs | 16 + .../css-tree/cjs/syntax/atrule/page.cjs | 16 + .../css-tree/cjs/syntax/atrule/scope.cjs | 16 + .../css-tree/cjs/syntax/atrule/starting-style.cjs | 12 + .../css-tree/cjs/syntax/atrule/supports.cjs | 16 + .../css-tree/cjs/syntax/config/generator.cjs | 9 + .../css-tree/cjs/syntax/config/lexer.cjs | 14 + .../css-tree/cjs/syntax/config/mix.cjs | 127 ++ .../css-tree/cjs/syntax/config/parser-selector.cjs | 19 + .../css-tree/cjs/syntax/config/parser.cjs | 49 + .../css-tree/cjs/syntax/config/walker.cjs | 9 + .../node_modules/css-tree/cjs/syntax/create.cjs | 58 + .../css-tree/cjs/syntax/function/expression.cjs | 11 + .../css-tree/cjs/syntax/function/var.cjs | 43 + vanilla/node_modules/css-tree/cjs/syntax/index.cjs | 14 + .../css-tree/cjs/syntax/node/AnPlusB.cjs | 293 +++++ .../css-tree/cjs/syntax/node/Atrule.cjs | 103 ++ .../css-tree/cjs/syntax/node/AtrulePrelude.cjs | 52 + .../css-tree/cjs/syntax/node/AttributeSelector.cjs | 148 +++ .../css-tree/cjs/syntax/node/Block.cjs | 96 ++ .../css-tree/cjs/syntax/node/Brackets.cjs | 38 + .../node_modules/css-tree/cjs/syntax/node/CDC.cjs | 26 + .../node_modules/css-tree/cjs/syntax/node/CDO.cjs | 26 + .../css-tree/cjs/syntax/node/ClassSelector.cjs | 31 + .../css-tree/cjs/syntax/node/Combinator.cjs | 61 + .../css-tree/cjs/syntax/node/Comment.cjs | 40 + .../css-tree/cjs/syntax/node/Condition.cjs | 120 ++ .../css-tree/cjs/syntax/node/Declaration.cjs | 166 +++ .../css-tree/cjs/syntax/node/DeclarationList.cjs | 62 + .../css-tree/cjs/syntax/node/Dimension.cjs | 30 + .../css-tree/cjs/syntax/node/Feature.cjs | 101 ++ .../css-tree/cjs/syntax/node/FeatureFunction.cjs | 67 + .../css-tree/cjs/syntax/node/FeatureRange.cjs | 133 ++ .../css-tree/cjs/syntax/node/Function.cjs | 45 + .../css-tree/cjs/syntax/node/GeneralEnclosed.cjs | 68 + .../node_modules/css-tree/cjs/syntax/node/Hash.cjs | 30 + .../css-tree/cjs/syntax/node/IdSelector.cjs | 33 + .../css-tree/cjs/syntax/node/Identifier.cjs | 25 + .../css-tree/cjs/syntax/node/Layer.cjs | 35 + .../css-tree/cjs/syntax/node/LayerList.cjs | 43 + .../css-tree/cjs/syntax/node/LayerName.cjs | 34 + .../css-tree/cjs/syntax/node/LayerNameList.cjs | 42 + .../css-tree/cjs/syntax/node/MediaCondition.cjs | 70 ++ .../css-tree/cjs/syntax/node/MediaFeature.cjs | 76 ++ .../css-tree/cjs/syntax/node/MediaFeatureRange.cjs | 11 + .../css-tree/cjs/syntax/node/MediaQuery.cjs | 100 ++ .../css-tree/cjs/syntax/node/MediaQueryList.cjs | 41 + .../css-tree/cjs/syntax/node/NestingSelector.cjs | 29 + .../node_modules/css-tree/cjs/syntax/node/Nth.cjs | 54 + .../css-tree/cjs/syntax/node/Number.cjs | 25 + .../css-tree/cjs/syntax/node/Operator.cjs | 28 + .../css-tree/cjs/syntax/node/Parentheses.cjs | 38 + .../css-tree/cjs/syntax/node/Percentage.cjs | 25 + .../cjs/syntax/node/PseudoClassSelector.cjs | 67 + .../cjs/syntax/node/PseudoElementSelector.cjs | 69 ++ .../css-tree/cjs/syntax/node/Ratio.cjs | 71 ++ .../node_modules/css-tree/cjs/syntax/node/Raw.cjs | 48 + .../node_modules/css-tree/cjs/syntax/node/Rule.cjs | 58 + .../css-tree/cjs/syntax/node/Scope.cjs | 69 ++ .../css-tree/cjs/syntax/node/Selector.cjs | 38 + .../css-tree/cjs/syntax/node/SelectorList.cjs | 43 + .../css-tree/cjs/syntax/node/String.cjs | 26 + .../css-tree/cjs/syntax/node/StyleSheet.cjs | 83 ++ .../cjs/syntax/node/SupportsDeclaration.cjs | 38 + .../css-tree/cjs/syntax/node/SupportsFeature.cjs | 69 ++ .../css-tree/cjs/syntax/node/TypeSelector.cjs | 59 + .../css-tree/cjs/syntax/node/UnicodeRange.cjs | 158 +++ .../node_modules/css-tree/cjs/syntax/node/Url.cjs | 54 + .../css-tree/cjs/syntax/node/Value.cjs | 26 + .../css-tree/cjs/syntax/node/WhiteSpace.cjs | 34 + .../cjs/syntax/node/common/feature-range.cjs | 112 ++ .../css-tree/cjs/syntax/node/common/feature.cjs | 76 ++ .../css-tree/cjs/syntax/node/index-generate.cjs | 103 ++ .../cjs/syntax/node/index-parse-selector.cjs | 39 + .../css-tree/cjs/syntax/node/index-parse.cjs | 103 ++ .../css-tree/cjs/syntax/node/index.cjs | 103 ++ .../css-tree/cjs/syntax/pseudo/index.cjs | 60 + .../css-tree/cjs/syntax/pseudo/lang.cjs | 37 + .../css-tree/cjs/syntax/scope/atrulePrelude.cjs | 9 + .../css-tree/cjs/syntax/scope/default.cjs | 76 ++ .../css-tree/cjs/syntax/scope/index.cjs | 11 + .../css-tree/cjs/syntax/scope/selector.cjs | 88 ++ .../css-tree/cjs/syntax/scope/value.cjs | 29 + .../css-tree/cjs/tokenizer/OffsetToLocation.cjs | 91 ++ .../css-tree/cjs/tokenizer/TokenStream.cjs | 308 +++++ .../css-tree/cjs/tokenizer/adopt-buffer.cjs | 13 + .../cjs/tokenizer/char-code-definitions.cjs | 236 ++++ .../node_modules/css-tree/cjs/tokenizer/index.cjs | 554 +++++++++ .../node_modules/css-tree/cjs/tokenizer/names.cjs | 32 + .../node_modules/css-tree/cjs/tokenizer/types.cjs | 57 + .../node_modules/css-tree/cjs/tokenizer/utils.cjs | 261 ++++ vanilla/node_modules/css-tree/cjs/utils/List.cjs | 473 +++++++ vanilla/node_modules/css-tree/cjs/utils/clone.cjs | 25 + .../css-tree/cjs/utils/create-custom-error.cjs | 18 + vanilla/node_modules/css-tree/cjs/utils/ident.cjs | 102 ++ vanilla/node_modules/css-tree/cjs/utils/index.cjs | 20 + vanilla/node_modules/css-tree/cjs/utils/names.cjs | 113 ++ vanilla/node_modules/css-tree/cjs/utils/string.cjs | 99 ++ vanilla/node_modules/css-tree/cjs/utils/url.cjs | 108 ++ vanilla/node_modules/css-tree/cjs/version.cjs | 5 + .../node_modules/css-tree/cjs/walker/create.cjs | 291 +++++ vanilla/node_modules/css-tree/cjs/walker/index.cjs | 8 + vanilla/node_modules/css-tree/data/patch.json | 982 +++++++++++++++ vanilla/node_modules/css-tree/dist/csstree.esm.js | 12 + vanilla/node_modules/css-tree/dist/csstree.js | 12 + vanilla/node_modules/css-tree/dist/data.cjs | 1308 ++++++++++++++++++++ vanilla/node_modules/css-tree/dist/data.js | 1308 ++++++++++++++++++++ vanilla/node_modules/css-tree/dist/version.cjs | 1 + vanilla/node_modules/css-tree/dist/version.js | 1 + .../node_modules/css-tree/lib/convertor/create.js | 28 + .../node_modules/css-tree/lib/convertor/index.js | 4 + vanilla/node_modules/css-tree/lib/data-patch.js | 6 + vanilla/node_modules/css-tree/lib/data.js | 118 ++ .../css-tree/lib/definition-syntax/SyntaxError.js | 12 + .../css-tree/lib/definition-syntax/generate.js | 135 ++ .../css-tree/lib/definition-syntax/index.js | 4 + .../css-tree/lib/definition-syntax/parse.js | 552 +++++++++ .../css-tree/lib/definition-syntax/scanner.js | 109 ++ .../css-tree/lib/definition-syntax/walk.js | 53 + .../node_modules/css-tree/lib/generator/create.js | 97 ++ .../node_modules/css-tree/lib/generator/index.js | 4 + .../css-tree/lib/generator/sourceMap.js | 92 ++ .../css-tree/lib/generator/token-before.js | 182 +++ vanilla/node_modules/css-tree/lib/index.js | 30 + vanilla/node_modules/css-tree/lib/lexer/Lexer.js | 511 ++++++++ vanilla/node_modules/css-tree/lib/lexer/error.js | 123 ++ .../css-tree/lib/lexer/generic-an-plus-b.js | 238 ++++ .../css-tree/lib/lexer/generic-const.js | 8 + .../css-tree/lib/lexer/generic-urange.js | 151 +++ vanilla/node_modules/css-tree/lib/lexer/generic.js | 622 ++++++++++ vanilla/node_modules/css-tree/lib/lexer/index.js | 1 + .../node_modules/css-tree/lib/lexer/match-graph.js | 527 ++++++++ vanilla/node_modules/css-tree/lib/lexer/match.js | 630 ++++++++++ .../css-tree/lib/lexer/prepare-tokens.js | 50 + vanilla/node_modules/css-tree/lib/lexer/search.js | 61 + .../node_modules/css-tree/lib/lexer/structure.js | 169 +++ vanilla/node_modules/css-tree/lib/lexer/trace.js | 66 + vanilla/node_modules/css-tree/lib/lexer/units.js | 27 + .../css-tree/lib/parser/SyntaxError.js | 70 ++ vanilla/node_modules/css-tree/lib/parser/create.js | 350 ++++++ vanilla/node_modules/css-tree/lib/parser/index.js | 4 + .../css-tree/lib/parser/parse-selector.js | 4 + .../node_modules/css-tree/lib/parser/sequence.js | 43 + .../css-tree/lib/syntax/atrule/container.js | 28 + .../css-tree/lib/syntax/atrule/font-face.js | 8 + .../css-tree/lib/syntax/atrule/import.js | 104 ++ .../css-tree/lib/syntax/atrule/index.js | 23 + .../css-tree/lib/syntax/atrule/layer.js | 12 + .../css-tree/lib/syntax/atrule/media.js | 12 + .../css-tree/lib/syntax/atrule/nest.js | 12 + .../css-tree/lib/syntax/atrule/page.js | 12 + .../css-tree/lib/syntax/atrule/scope.js | 12 + .../css-tree/lib/syntax/atrule/starting-style.js | 8 + .../css-tree/lib/syntax/atrule/supports.js | 12 + .../css-tree/lib/syntax/config/generator.js | 5 + .../css-tree/lib/syntax/config/lexer.js | 10 + .../node_modules/css-tree/lib/syntax/config/mix.js | 123 ++ .../css-tree/lib/syntax/config/parser-selector.js | 15 + .../css-tree/lib/syntax/config/parser.js | 45 + .../css-tree/lib/syntax/config/walker.js | 5 + vanilla/node_modules/css-tree/lib/syntax/create.js | 55 + .../css-tree/lib/syntax/function/expression.js | 7 + .../css-tree/lib/syntax/function/var.js | 39 + vanilla/node_modules/css-tree/lib/syntax/index.js | 10 + .../css-tree/lib/syntax/node/AnPlusB.js | 292 +++++ .../css-tree/lib/syntax/node/Atrule.js | 100 ++ .../css-tree/lib/syntax/node/AtrulePrelude.js | 47 + .../css-tree/lib/syntax/node/AttributeSelector.js | 147 +++ .../node_modules/css-tree/lib/syntax/node/Block.js | 95 ++ .../css-tree/lib/syntax/node/Brackets.js | 35 + .../node_modules/css-tree/lib/syntax/node/CDC.js | 19 + .../node_modules/css-tree/lib/syntax/node/CDO.js | 19 + .../css-tree/lib/syntax/node/ClassSelector.js | 24 + .../css-tree/lib/syntax/node/Combinator.js | 54 + .../css-tree/lib/syntax/node/Comment.js | 33 + .../css-tree/lib/syntax/node/Condition.js | 123 ++ .../css-tree/lib/syntax/node/Declaration.js | 165 +++ .../css-tree/lib/syntax/node/DeclarationList.js | 62 + .../css-tree/lib/syntax/node/Dimension.js | 23 + .../css-tree/lib/syntax/node/Feature.js | 103 ++ .../css-tree/lib/syntax/node/FeatureFunction.js | 63 + .../css-tree/lib/syntax/node/FeatureRange.js | 133 ++ .../css-tree/lib/syntax/node/Function.js | 41 + .../css-tree/lib/syntax/node/GeneralEnclosed.js | 66 + .../node_modules/css-tree/lib/syntax/node/Hash.js | 23 + .../css-tree/lib/syntax/node/IdSelector.js | 26 + .../css-tree/lib/syntax/node/Identifier.js | 18 + .../node_modules/css-tree/lib/syntax/node/Layer.js | 28 + .../css-tree/lib/syntax/node/LayerList.js | 36 + .../css-tree/lib/syntax/node/MediaQuery.js | 102 ++ .../css-tree/lib/syntax/node/MediaQueryList.js | 34 + .../css-tree/lib/syntax/node/NestingSelector.js | 22 + .../node_modules/css-tree/lib/syntax/node/Nth.js | 47 + .../css-tree/lib/syntax/node/Number.js | 18 + .../css-tree/lib/syntax/node/Operator.js | 21 + .../css-tree/lib/syntax/node/Parentheses.js | 34 + .../css-tree/lib/syntax/node/Percentage.js | 18 + .../lib/syntax/node/PseudoClassSelector.js | 65 + .../lib/syntax/node/PseudoElementSelector.js | 66 + .../node_modules/css-tree/lib/syntax/node/Ratio.js | 68 + .../node_modules/css-tree/lib/syntax/node/Raw.js | 41 + .../node_modules/css-tree/lib/syntax/node/Rule.js | 51 + .../node_modules/css-tree/lib/syntax/node/Scope.js | 66 + .../css-tree/lib/syntax/node/Selector.js | 31 + .../css-tree/lib/syntax/node/SelectorList.js | 35 + .../css-tree/lib/syntax/node/String.js | 19 + .../css-tree/lib/syntax/node/StyleSheet.js | 82 ++ .../lib/syntax/node/SupportsDeclaration.js | 34 + .../css-tree/lib/syntax/node/TypeSelector.js | 52 + .../css-tree/lib/syntax/node/UnicodeRange.js | 156 +++ .../node_modules/css-tree/lib/syntax/node/Url.js | 52 + .../node_modules/css-tree/lib/syntax/node/Value.js | 19 + .../css-tree/lib/syntax/node/WhiteSpace.js | 27 + .../css-tree/lib/syntax/node/index-generate.js | 49 + .../lib/syntax/node/index-parse-selector.js | 17 + .../css-tree/lib/syntax/node/index-parse.js | 49 + .../node_modules/css-tree/lib/syntax/node/index.js | 49 + .../css-tree/lib/syntax/pseudo/index.js | 56 + .../css-tree/lib/syntax/pseudo/lang.js | 33 + .../css-tree/lib/syntax/scope/atrulePrelude.js | 5 + .../css-tree/lib/syntax/scope/default.js | 85 ++ .../css-tree/lib/syntax/scope/index.js | 3 + .../css-tree/lib/syntax/scope/selector.js | 94 ++ .../css-tree/lib/syntax/scope/value.js | 25 + .../css-tree/lib/tokenizer/OffsetToLocation.js | 87 ++ .../css-tree/lib/tokenizer/TokenStream.js | 316 +++++ .../css-tree/lib/tokenizer/adopt-buffer.js | 9 + .../lib/tokenizer/char-code-definitions.js | 212 ++++ .../node_modules/css-tree/lib/tokenizer/index.js | 513 ++++++++ .../node_modules/css-tree/lib/tokenizer/names.js | 28 + .../node_modules/css-tree/lib/tokenizer/types.js | 28 + .../node_modules/css-tree/lib/tokenizer/utils.js | 254 ++++ vanilla/node_modules/css-tree/lib/utils/List.js | 469 +++++++ vanilla/node_modules/css-tree/lib/utils/clone.js | 21 + .../css-tree/lib/utils/create-custom-error.js | 14 + vanilla/node_modules/css-tree/lib/utils/ident.js | 101 ++ vanilla/node_modules/css-tree/lib/utils/index.js | 6 + vanilla/node_modules/css-tree/lib/utils/names.js | 106 ++ vanilla/node_modules/css-tree/lib/utils/string.js | 99 ++ vanilla/node_modules/css-tree/lib/utils/url.js | 108 ++ vanilla/node_modules/css-tree/lib/version.js | 5 + vanilla/node_modules/css-tree/lib/walker/create.js | 287 +++++ vanilla/node_modules/css-tree/lib/walker/index.js | 4 + vanilla/node_modules/css-tree/package.json | 125 ++ 287 files changed, 28653 insertions(+) create mode 100644 vanilla/node_modules/css-tree/LICENSE create mode 100644 vanilla/node_modules/css-tree/README.md create mode 100644 vanilla/node_modules/css-tree/cjs/convertor/create.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/convertor/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/data-patch.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/data.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/SyntaxError.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/generate.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/parse.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/scanner.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/tokenizer.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/definition-syntax/walk.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/generator/create.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/generator/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/generator/sourceMap.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/generator/token-before.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/Lexer.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/error.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/generic-an-plus-b.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/generic-const.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/generic.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/match-graph.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/match.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/prepare-tokens.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/search.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/structure.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/trace.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/lexer/units.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/parser/SyntaxError.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/parser/create.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/parser/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/parser/parse-selector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/parser/sequence.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/container.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/font-face.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/import.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/layer.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/media.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/nest.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/page.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/scope.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/starting-style.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/atrule/supports.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/config/generator.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/config/lexer.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/config/mix.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/config/parser-selector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/config/parser.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/config/walker.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/create.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/function/expression.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/function/var.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/AnPlusB.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Atrule.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/AtrulePrelude.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/AttributeSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Block.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Brackets.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/CDC.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/CDO.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/ClassSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Combinator.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Comment.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Condition.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Declaration.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/DeclarationList.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Dimension.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Feature.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/FeatureFunction.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/FeatureRange.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Function.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/GeneralEnclosed.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Hash.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/IdSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Identifier.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Layer.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/LayerList.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/LayerName.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/LayerNameList.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/MediaCondition.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/MediaFeature.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/MediaFeatureRange.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/MediaQuery.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/MediaQueryList.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/NestingSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Nth.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Number.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Operator.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Parentheses.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Percentage.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/PseudoClassSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/PseudoElementSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Ratio.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Raw.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Rule.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Scope.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Selector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/SelectorList.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/String.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/StyleSheet.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/SupportsDeclaration.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/SupportsFeature.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/TypeSelector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/UnicodeRange.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Url.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/Value.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/WhiteSpace.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/common/feature-range.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/common/feature.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/index-generate.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/index-parse-selector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/index-parse.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/node/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/pseudo/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/pseudo/lang.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/scope/atrulePrelude.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/scope/default.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/scope/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/scope/selector.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/syntax/scope/value.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/OffsetToLocation.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/TokenStream.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/adopt-buffer.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/char-code-definitions.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/names.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/types.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/tokenizer/utils.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/List.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/clone.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/create-custom-error.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/ident.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/index.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/names.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/string.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/utils/url.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/version.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/walker/create.cjs create mode 100644 vanilla/node_modules/css-tree/cjs/walker/index.cjs create mode 100644 vanilla/node_modules/css-tree/data/patch.json create mode 100644 vanilla/node_modules/css-tree/dist/csstree.esm.js create mode 100644 vanilla/node_modules/css-tree/dist/csstree.js create mode 100644 vanilla/node_modules/css-tree/dist/data.cjs create mode 100644 vanilla/node_modules/css-tree/dist/data.js create mode 100644 vanilla/node_modules/css-tree/dist/version.cjs create mode 100644 vanilla/node_modules/css-tree/dist/version.js create mode 100644 vanilla/node_modules/css-tree/lib/convertor/create.js create mode 100644 vanilla/node_modules/css-tree/lib/convertor/index.js create mode 100644 vanilla/node_modules/css-tree/lib/data-patch.js create mode 100755 vanilla/node_modules/css-tree/lib/data.js create mode 100644 vanilla/node_modules/css-tree/lib/definition-syntax/SyntaxError.js create mode 100644 vanilla/node_modules/css-tree/lib/definition-syntax/generate.js create mode 100644 vanilla/node_modules/css-tree/lib/definition-syntax/index.js create mode 100644 vanilla/node_modules/css-tree/lib/definition-syntax/parse.js create mode 100644 vanilla/node_modules/css-tree/lib/definition-syntax/scanner.js create mode 100644 vanilla/node_modules/css-tree/lib/definition-syntax/walk.js create mode 100644 vanilla/node_modules/css-tree/lib/generator/create.js create mode 100644 vanilla/node_modules/css-tree/lib/generator/index.js create mode 100644 vanilla/node_modules/css-tree/lib/generator/sourceMap.js create mode 100644 vanilla/node_modules/css-tree/lib/generator/token-before.js create mode 100644 vanilla/node_modules/css-tree/lib/index.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/Lexer.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/error.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/generic-an-plus-b.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/generic-const.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/generic-urange.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/generic.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/index.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/match-graph.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/match.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/prepare-tokens.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/search.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/structure.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/trace.js create mode 100644 vanilla/node_modules/css-tree/lib/lexer/units.js create mode 100644 vanilla/node_modules/css-tree/lib/parser/SyntaxError.js create mode 100644 vanilla/node_modules/css-tree/lib/parser/create.js create mode 100644 vanilla/node_modules/css-tree/lib/parser/index.js create mode 100644 vanilla/node_modules/css-tree/lib/parser/parse-selector.js create mode 100644 vanilla/node_modules/css-tree/lib/parser/sequence.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/container.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/font-face.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/import.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/index.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/layer.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/media.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/nest.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/page.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/scope.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/starting-style.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/atrule/supports.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/config/generator.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/config/lexer.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/config/mix.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/config/parser-selector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/config/parser.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/config/walker.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/create.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/function/expression.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/function/var.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/index.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/AnPlusB.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Atrule.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/AtrulePrelude.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/AttributeSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Block.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Brackets.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/CDC.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/CDO.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/ClassSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Combinator.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Comment.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Condition.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Declaration.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/DeclarationList.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Dimension.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Feature.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/FeatureFunction.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/FeatureRange.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Function.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/GeneralEnclosed.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Hash.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/IdSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Identifier.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Layer.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/LayerList.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/MediaQuery.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/MediaQueryList.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/NestingSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Nth.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Number.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Operator.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Parentheses.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Percentage.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/PseudoClassSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/PseudoElementSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Ratio.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Raw.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Rule.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Scope.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Selector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/SelectorList.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/String.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/StyleSheet.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/SupportsDeclaration.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/TypeSelector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/UnicodeRange.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Url.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/Value.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/WhiteSpace.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/index-generate.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/index-parse-selector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/index-parse.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/node/index.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/pseudo/index.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/pseudo/lang.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/scope/atrulePrelude.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/scope/default.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/scope/index.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/scope/selector.js create mode 100644 vanilla/node_modules/css-tree/lib/syntax/scope/value.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/OffsetToLocation.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/TokenStream.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/adopt-buffer.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/char-code-definitions.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/index.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/names.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/types.js create mode 100644 vanilla/node_modules/css-tree/lib/tokenizer/utils.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/List.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/clone.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/create-custom-error.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/ident.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/index.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/names.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/string.js create mode 100644 vanilla/node_modules/css-tree/lib/utils/url.js create mode 100644 vanilla/node_modules/css-tree/lib/version.js create mode 100644 vanilla/node_modules/css-tree/lib/walker/create.js create mode 100644 vanilla/node_modules/css-tree/lib/walker/index.js create mode 100644 vanilla/node_modules/css-tree/package.json (limited to 'vanilla/node_modules/css-tree') diff --git a/vanilla/node_modules/css-tree/LICENSE b/vanilla/node_modules/css-tree/LICENSE new file mode 100644 index 0000000..c627ec0 --- /dev/null +++ b/vanilla/node_modules/css-tree/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2016-2024 by Roman Dvornov + +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. diff --git a/vanilla/node_modules/css-tree/README.md b/vanilla/node_modules/css-tree/README.md new file mode 100644 index 0000000..92e6f15 --- /dev/null +++ b/vanilla/node_modules/css-tree/README.md @@ -0,0 +1,192 @@ +CSSTree logo + +# CSSTree + +[![NPM version](https://img.shields.io/npm/v/css-tree.svg)](https://www.npmjs.com/package/css-tree) +[![Build Status](https://github.com/csstree/csstree/actions/workflows/build.yml/badge.svg)](https://github.com/csstree/csstree/actions/workflows/build.yml) +[![Coverage Status](https://coveralls.io/repos/github/csstree/csstree/badge.svg?branch=master)](https://coveralls.io/github/csstree/csstree?branch=master) +[![NPM Downloads](https://img.shields.io/npm/dm/css-tree.svg)](https://www.npmjs.com/package/css-tree) +[![Twitter](https://img.shields.io/badge/Twitter-@csstree-blue.svg)](https://twitter.com/csstree) + +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. + +## Features + +- **Detailed parsing with an adjustable level of detail** + + 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. + +- **Tolerant to errors by design** + + 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. + +- **Fast and efficient** + + 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. + +- **Syntax validation** + + 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. + +## Projects using CSSTree + +- [Svelte](https://github.com/sveltejs/svelte) – Cybernetically enhanced web apps +- [SVGO](https://github.com/svg/svgo) – Node.js tool for optimizing SVG files +- [CSSO](https://github.com/css/csso) – CSS minifier with structural optimizations +- [NativeScript](https://github.com/NativeScript/NativeScript) – NativeScript empowers you to access native APIs from JavaScript directly +- [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 +- [penthouse](https://github.com/pocketjoso/penthouse) – Critical Path CSS Generator +- [Bit](https://github.com/teambit/bit) – Bit is the platform for collaborating on components +- and more... + +## Documentation + +- [AST format](docs/ast.md) +- [Parsing CSS → AST](docs/parsing.md) + - [parse(source[, options])](docs/parsing.md#parsesource-options) +- [Serialization AST → CSS](docs/generate.md) + - [generate(ast[, options])](docs/generate.md#generateast-options) +- [AST traversal](docs/traversal.md) + - [walk(ast, options)](docs/traversal.md#walkast-options) + - [find(ast, fn)](docs/traversal.md#findast-fn) + - [findLast(ast, fn)](docs/traversal.md#findlastast-fn) + - [findAll(ast, fn)](docs/traversal.md#findallast-fn) +- [Util functions](docs/utils.md) + - Value encoding & decoding + - [property(name)](docs/utils.md#propertyname) + - [keyword(name)](docs/utils.md#keywordname) + - [ident](docs/utils.md#ident) + - [string](docs/utils.md#string) + - [url](docs/utils.md#url) + - [List class](docs/list.md) + - AST transforming + - [clone(ast)](docs/utils.md#cloneast) + - [fromPlainObject(object)](docs/utils.md#fromplainobjectobject) + - [toPlainObject(ast)](docs/utils.md#toplainobjectast) +- [Value Definition Syntax](docs/definition-syntax.md) + - [parse(source)](docs/definition-syntax.md#parsesource) + - [walk(node, options, context)](docs/definition-syntax.md#walknode-options-context) + - [generate(node, options)](docs/definition-syntax.md#generatenode-options) + - [AST format](docs/definition-syntax.md#ast-format) + +## Tools + +* [AST Explorer](https://astexplorer.net/#/gist/244e2fb4da940df52bf0f4b94277db44/e79aff44611020b22cfd9708f3a99ce09b7d67a8) – explore CSSTree AST format with zero setup +* [CSS syntax reference](https://csstree.github.io/docs/syntax.html) +* [CSS syntax validator](https://csstree.github.io/docs/validator.html) + +## Related projects + +* [csstree-validator](https://github.com/csstree/validator) – NPM package to validate CSS +* [stylelint-csstree-validator](https://github.com/csstree/stylelint-validator) – plugin for stylelint to validate CSS +* [Grunt plugin](https://github.com/sergejmueller/grunt-csstree-validator) +* [Gulp plugin](https://github.com/csstree/gulp-csstree) +* [Sublime plugin](https://github.com/csstree/SublimeLinter-contrib-csstree) +* [VS Code plugin](https://github.com/csstree/vscode-plugin) +* [Atom plugin](https://github.com/csstree/atom-plugin) + +## Usage + +Install with npm: + +``` +npm install css-tree +``` + +Basic usage: + +```js +import * as csstree from 'css-tree'; + +// parse CSS to AST +const ast = csstree.parse('.example { world: "!" }'); + +// traverse AST and modify it +csstree.walk(ast, (node) => { + if (node.type === 'ClassSelector' && node.name === 'example') { + node.name = 'hello'; + } +}); + +// generate CSS from AST +console.log(csstree.generate(ast)); +// .hello{world:"!"} +``` + +Syntax matching: + +```js +// parse CSS to AST as a declaration value +const ast = csstree.parse('red 1px solid', { context: 'value' }); + +// match to syntax of `border` property +const matchResult = csstree.lexer.matchProperty('border', ast); + +// check first value node is a +console.log(matchResult.isType(ast.children.first, 'color')); +// true + +// get a type list matched to a node +console.log(matchResult.getTrace(ast.children.first)); +// [ { type: 'Property', name: 'border' }, +// { type: 'Type', name: 'color' }, +// { type: 'Type', name: 'named-color' }, +// { type: 'Keyword', name: 'red' } ] +``` + +### Exports + +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. + +```js +import * as tokenizer from 'css-tree/tokenizer'; +import * as parser from 'css-tree/parser'; +import * as walker from 'css-tree/walker'; +import * as lexer from 'css-tree/lexer'; +import * as definitionSyntax from 'css-tree/definition-syntax'; +import * as data from 'css-tree/definition-syntax-data'; +import * as dataPatch from 'css-tree/definition-syntax-data-patch'; +import * as utils from 'css-tree/utils'; +``` + +### Using in a browser + +Bundles are available for use in a browser: + +- `dist/csstree.js` – minified IIFE with `csstree` as global +```html + + +``` + +- `dist/csstree.esm.js` – minified ES module +```html + +``` + +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: + +```html + + + + + + +``` + +## Top level API + +![API map](https://cdn.rawgit.com/csstree/csstree/aaf327e/docs/api-map.svg) + +## License + +MIT diff --git a/vanilla/node_modules/css-tree/cjs/convertor/create.cjs b/vanilla/node_modules/css-tree/cjs/convertor/create.cjs new file mode 100644 index 0000000..55c655b --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/convertor/create.cjs @@ -0,0 +1,32 @@ +'use strict'; + +const List = require('../utils/List.cjs'); + +function createConvertor(walk) { + return { + fromPlainObject(ast) { + walk(ast, { + enter(node) { + if (node.children && node.children instanceof List.List === false) { + node.children = new List.List().fromArray(node.children); + } + } + }); + + return ast; + }, + toPlainObject(ast) { + walk(ast, { + leave(node) { + if (node.children && node.children instanceof List.List) { + node.children = node.children.toArray(); + } + } + }); + + return ast; + } + }; +} + +exports.createConvertor = createConvertor; diff --git a/vanilla/node_modules/css-tree/cjs/convertor/index.cjs b/vanilla/node_modules/css-tree/cjs/convertor/index.cjs new file mode 100644 index 0000000..6654278 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/convertor/index.cjs @@ -0,0 +1,8 @@ +'use strict'; + +const create = require('./create.cjs'); +const index$1 = require('../walker/index.cjs'); + +const index = create.createConvertor(index$1); + +module.exports = index; diff --git a/vanilla/node_modules/css-tree/cjs/data-patch.cjs b/vanilla/node_modules/css-tree/cjs/data-patch.cjs new file mode 100644 index 0000000..9103ea4 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/data-patch.cjs @@ -0,0 +1,7 @@ +'use strict'; + +const patch = require('../data/patch.json'); + +const patch$1 = patch; + +module.exports = patch$1; diff --git a/vanilla/node_modules/css-tree/cjs/data.cjs b/vanilla/node_modules/css-tree/cjs/data.cjs new file mode 100644 index 0000000..258ac6a --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/data.cjs @@ -0,0 +1,120 @@ +'use strict'; + +const dataPatch = require('./data-patch.cjs'); + +const mdnAtrules = require('mdn-data/css/at-rules.json'); +const mdnProperties = require('mdn-data/css/properties.json'); +const mdnSyntaxes = require('mdn-data/css/syntaxes.json'); + +const hasOwn = Object.hasOwn || ((object, property) => Object.prototype.hasOwnProperty.call(object, property)); +const extendSyntax = /^\s*\|\s*/; + +function preprocessAtrules(dict) { + const result = Object.create(null); + + for (const [atruleName, atrule] of Object.entries(dict)) { + let descriptors = null; + + if (atrule.descriptors) { + descriptors = Object.create(null); + + for (const [name, descriptor] of Object.entries(atrule.descriptors)) { + descriptors[name] = descriptor.syntax; + } + } + + result[atruleName.substr(1)] = { + prelude: atrule.syntax.trim().replace(/\{(.|\s)+\}/, '').match(/^@\S+\s+([^;\{]*)/)[1].trim() || null, + descriptors + }; + } + + return result; +} + +function patchDictionary(dict, patchDict) { + const result = Object.create(null); + + // copy all syntaxes for an original dict + for (const [key, value] of Object.entries(dict)) { + if (value) { + result[key] = value.syntax || value; + } + } + + // apply a patch + for (const key of Object.keys(patchDict)) { + if (hasOwn(dict, key)) { + if (patchDict[key].syntax) { + result[key] = extendSyntax.test(patchDict[key].syntax) + ? result[key] + ' ' + patchDict[key].syntax.trim() + : patchDict[key].syntax; + } else { + delete result[key]; + } + } else { + if (patchDict[key].syntax) { + result[key] = patchDict[key].syntax.replace(extendSyntax, ''); + } + } + } + + return result; +} + +function preprocessPatchAtrulesDescritors(declarations) { + const result = {}; + + for (const [key, value] of Object.entries(declarations || {})) { + result[key] = typeof value === 'string' + ? { syntax: value } + : value; + } + + return result; +} + +function patchAtrules(dict, patchDict) { + const result = {}; + + // copy all syntaxes for an original dict + for (const key in dict) { + if (patchDict[key] === null) { + continue; + } + + const atrulePatch = patchDict[key] || {}; + + result[key] = { + prelude: key in patchDict && 'prelude' in atrulePatch + ? atrulePatch.prelude + : dict[key].prelude || null, + descriptors: patchDictionary( + dict[key].descriptors || {}, + preprocessPatchAtrulesDescritors(atrulePatch.descriptors) + ) + }; + } + + // apply a patch + for (const [key, atrulePatch] of Object.entries(patchDict)) { + if (atrulePatch && !hasOwn(dict, key)) { + result[key] = { + prelude: atrulePatch.prelude || null, + descriptors: atrulePatch.descriptors + ? patchDictionary({}, preprocessPatchAtrulesDescritors(atrulePatch.descriptors)) + : null + }; + } + } + + return result; +} + +const definitions = { + types: patchDictionary(mdnSyntaxes, dataPatch.types), + atrules: patchAtrules(preprocessAtrules(mdnAtrules), dataPatch.atrules), + properties: patchDictionary(mdnProperties, dataPatch.properties) +}; + +module.exports = definitions; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/SyntaxError.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/SyntaxError.cjs new file mode 100644 index 0000000..d24e7ce --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/SyntaxError.cjs @@ -0,0 +1,16 @@ +'use strict'; + +const createCustomError = require('../utils/create-custom-error.cjs'); + +function SyntaxError(message, input, offset) { + return Object.assign(createCustomError.createCustomError('SyntaxError', message), { + input, + offset, + rawMessage: message, + message: message + '\n' + + ' ' + input + '\n' + + '--' + new Array((offset || input.length) + 1).join('-') + '^' + }); +} + +exports.SyntaxError = SyntaxError; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/generate.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/generate.cjs new file mode 100644 index 0000000..ff9f0ad --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/generate.cjs @@ -0,0 +1,139 @@ +'use strict'; + +function noop(value) { + return value; +} + +function generateMultiplier(multiplier) { + const { min, max, comma } = multiplier; + + if (min === 0 && max === 0) { + return comma ? '#?' : '*'; + } + + if (min === 0 && max === 1) { + return '?'; + } + + if (min === 1 && max === 0) { + return comma ? '#' : '+'; + } + + if (min === 1 && max === 1) { + return ''; + } + + return ( + (comma ? '#' : '') + + (min === max + ? '{' + min + '}' + : '{' + min + ',' + (max !== 0 ? max : '') + '}' + ) + ); +} + +function generateTypeOpts(node) { + switch (node.type) { + case 'Range': + return ( + ' [' + + (node.min === null ? '-∞' : node.min) + + ',' + + (node.max === null ? '∞' : node.max) + + ']' + ); + + default: + throw new Error('Unknown node type `' + node.type + '`'); + } +} + +function generateSequence(node, decorate, forceBraces, compact) { + const combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' '; + const result = node.terms + .map(term => internalGenerate(term, decorate, forceBraces, compact)) + .join(combinator); + + if (node.explicit || forceBraces) { + return (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]'); + } + + return result; +} + +function internalGenerate(node, decorate, forceBraces, compact) { + let result; + + switch (node.type) { + case 'Group': + result = + generateSequence(node, decorate, forceBraces, compact) + + (node.disallowEmpty ? '!' : ''); + break; + + case 'Multiplier': + // return since node is a composition + return ( + internalGenerate(node.term, decorate, forceBraces, compact) + + decorate(generateMultiplier(node), node) + ); + + case 'Boolean': + result = ''; + break; + + case 'Type': + result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>'; + break; + + case 'Property': + result = '<\'' + node.name + '\'>'; + break; + + case 'Keyword': + result = node.name; + break; + + case 'AtKeyword': + result = '@' + node.name; + break; + + case 'Function': + result = node.name + '('; + break; + + case 'String': + case 'Token': + result = node.value; + break; + + case 'Comma': + result = ','; + break; + + default: + throw new Error('Unknown node type `' + node.type + '`'); + } + + return decorate(result, node); +} + +function generate(node, options) { + let decorate = noop; + let forceBraces = false; + let compact = false; + + if (typeof options === 'function') { + decorate = options; + } else if (options) { + forceBraces = Boolean(options.forceBraces); + compact = Boolean(options.compact); + if (typeof options.decorate === 'function') { + decorate = options.decorate; + } + } + + return internalGenerate(node, decorate, forceBraces, compact); +} + +exports.generate = generate; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/index.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/index.cjs new file mode 100644 index 0000000..0afb505 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/index.cjs @@ -0,0 +1,13 @@ +'use strict'; + +const SyntaxError = require('./SyntaxError.cjs'); +const generate = require('./generate.cjs'); +const parse = require('./parse.cjs'); +const walk = require('./walk.cjs'); + + + +exports.SyntaxError = SyntaxError.SyntaxError; +exports.generate = generate.generate; +exports.parse = parse.parse; +exports.walk = walk.walk; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/parse.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/parse.cjs new file mode 100644 index 0000000..b17b267 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/parse.cjs @@ -0,0 +1,556 @@ +'use strict'; + +const scanner = require('./scanner.cjs'); + +const TAB = 9; +const N = 10; +const F = 12; +const R = 13; +const SPACE = 32; +const EXCLAMATIONMARK = 33; // ! +const NUMBERSIGN = 35; // # +const AMPERSAND = 38; // & +const APOSTROPHE = 39; // ' +const LEFTPARENTHESIS = 40; // ( +const RIGHTPARENTHESIS = 41; // ) +const ASTERISK = 42; // * +const PLUSSIGN = 43; // + +const COMMA = 44; // , +const HYPERMINUS = 45; // - +const LESSTHANSIGN = 60; // < +const GREATERTHANSIGN = 62; // > +const QUESTIONMARK = 63; // ? +const COMMERCIALAT = 64; // @ +const LEFTSQUAREBRACKET = 91; // [ +const RIGHTSQUAREBRACKET = 93; // ] +const LEFTCURLYBRACKET = 123; // { +const VERTICALLINE = 124; // | +const RIGHTCURLYBRACKET = 125; // } +const INFINITY = 8734; // ∞ +const COMBINATOR_PRECEDENCE = { + ' ': 1, + '&&': 2, + '||': 3, + '|': 4 +}; + +function readMultiplierRange(scanner) { + let min = null; + let max = null; + + scanner.eat(LEFTCURLYBRACKET); + scanner.skipWs(); + + min = scanner.scanNumber(scanner); + scanner.skipWs(); + + if (scanner.charCode() === COMMA) { + scanner.pos++; + scanner.skipWs(); + + if (scanner.charCode() !== RIGHTCURLYBRACKET) { + max = scanner.scanNumber(scanner); + scanner.skipWs(); + } + } else { + max = min; + } + + scanner.eat(RIGHTCURLYBRACKET); + + return { + min: Number(min), + max: max ? Number(max) : 0 + }; +} + +function readMultiplier(scanner) { + let range = null; + let comma = false; + + switch (scanner.charCode()) { + case ASTERISK: + scanner.pos++; + + range = { + min: 0, + max: 0 + }; + + break; + + case PLUSSIGN: + scanner.pos++; + + range = { + min: 1, + max: 0 + }; + + break; + + case QUESTIONMARK: + scanner.pos++; + + range = { + min: 0, + max: 1 + }; + + break; + + case NUMBERSIGN: + scanner.pos++; + + comma = true; + + if (scanner.charCode() === LEFTCURLYBRACKET) { + range = readMultiplierRange(scanner); + } else if (scanner.charCode() === QUESTIONMARK) { + // https://www.w3.org/TR/css-values-4/#component-multipliers + // > the # and ? multipliers may be stacked as #? + // In this case just treat "#?" as a single multiplier + // { min: 0, max: 0, comma: true } + scanner.pos++; + range = { + min: 0, + max: 0 + }; + } else { + range = { + min: 1, + max: 0 + }; + } + + break; + + case LEFTCURLYBRACKET: + range = readMultiplierRange(scanner); + break; + + default: + return null; + } + + return { + type: 'Multiplier', + comma, + min: range.min, + max: range.max, + term: null + }; +} + +function maybeMultiplied(scanner, node) { + const multiplier = readMultiplier(scanner); + + if (multiplier !== null) { + multiplier.term = node; + + // https://www.w3.org/TR/css-values-4/#component-multipliers + // > The + and # multipliers may be stacked as +#; + // Represent "+#" as nested multipliers: + // { ..., + // term: { + // ..., + // term: node + // } + // } + if (scanner.charCode() === NUMBERSIGN && + scanner.charCodeAt(scanner.pos - 1) === PLUSSIGN) { + return maybeMultiplied(scanner, multiplier); + } + + return multiplier; + } + + return node; +} + +function maybeToken(scanner) { + const ch = scanner.peek(); + + if (ch === '') { + return null; + } + + return maybeMultiplied(scanner, { + type: 'Token', + value: ch + }); +} + +function readProperty(scanner) { + let name; + + scanner.eat(LESSTHANSIGN); + scanner.eat(APOSTROPHE); + + name = scanner.scanWord(); + + scanner.eat(APOSTROPHE); + scanner.eat(GREATERTHANSIGN); + + return maybeMultiplied(scanner, { + type: 'Property', + name + }); +} + +// https://drafts.csswg.org/css-values-3/#numeric-ranges +// 4.1. Range Restrictions and Range Definition Notation +// +// Range restrictions can be annotated in the numeric type notation using CSS bracketed +// range notation—[min,max]—within the angle brackets, after the identifying keyword, +// indicating a closed range between (and including) min and max. +// For example, indicates an integer between 0 and 10, inclusive. +function readTypeRange(scanner) { + // use null for Infinity to make AST format JSON serializable/deserializable + let min = null; // -Infinity + let max = null; // Infinity + let sign = 1; + + scanner.eat(LEFTSQUAREBRACKET); + + if (scanner.charCode() === HYPERMINUS) { + scanner.peek(); + sign = -1; + } + + if (sign == -1 && scanner.charCode() === INFINITY) { + scanner.peek(); + } else { + min = sign * Number(scanner.scanNumber(scanner)); + + if (scanner.isNameCharCode()) { + min += scanner.scanWord(); + } + } + + scanner.skipWs(); + scanner.eat(COMMA); + scanner.skipWs(); + + if (scanner.charCode() === INFINITY) { + scanner.peek(); + } else { + sign = 1; + + if (scanner.charCode() === HYPERMINUS) { + scanner.peek(); + sign = -1; + } + + max = sign * Number(scanner.scanNumber(scanner)); + + if (scanner.isNameCharCode()) { + max += scanner.scanWord(); + } + } + + scanner.eat(RIGHTSQUAREBRACKET); + + return { + type: 'Range', + min, + max + }; +} + +function readType(scanner) { + let name; + let opts = null; + + scanner.eat(LESSTHANSIGN); + name = scanner.scanWord(); + + // https://drafts.csswg.org/css-values-5/#boolean + if (name === 'boolean-expr') { + scanner.eat(LEFTSQUAREBRACKET); + + const implicitGroup = readImplicitGroup(scanner, RIGHTSQUAREBRACKET); + + scanner.eat(RIGHTSQUAREBRACKET); + scanner.eat(GREATERTHANSIGN); + + return maybeMultiplied(scanner, { + type: 'Boolean', + term: implicitGroup.terms.length === 1 + ? implicitGroup.terms[0] + : implicitGroup + }); + } + + if (scanner.charCode() === LEFTPARENTHESIS && + scanner.nextCharCode() === RIGHTPARENTHESIS) { + scanner.pos += 2; + name += '()'; + } + + if (scanner.charCodeAt(scanner.findWsEnd(scanner.pos)) === LEFTSQUAREBRACKET) { + scanner.skipWs(); + opts = readTypeRange(scanner); + } + + scanner.eat(GREATERTHANSIGN); + + return maybeMultiplied(scanner, { + type: 'Type', + name, + opts + }); +} + +function readKeywordOrFunction(scanner) { + const name = scanner.scanWord(); + + if (scanner.charCode() === LEFTPARENTHESIS) { + scanner.pos++; + + return { + type: 'Function', + name + }; + } + + return maybeMultiplied(scanner, { + type: 'Keyword', + name + }); +} + +function regroupTerms(terms, combinators) { + function createGroup(terms, combinator) { + return { + type: 'Group', + terms, + combinator, + disallowEmpty: false, + explicit: false + }; + } + + let combinator; + + combinators = Object.keys(combinators) + .sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]); + + while (combinators.length > 0) { + combinator = combinators.shift(); + + let i = 0; + let subgroupStart = 0; + + for (; i < terms.length; i++) { + const term = terms[i]; + + if (term.type === 'Combinator') { + if (term.value === combinator) { + if (subgroupStart === -1) { + subgroupStart = i - 1; + } + terms.splice(i, 1); + i--; + } else { + if (subgroupStart !== -1 && i - subgroupStart > 1) { + terms.splice( + subgroupStart, + i - subgroupStart, + createGroup(terms.slice(subgroupStart, i), combinator) + ); + i = subgroupStart + 1; + } + subgroupStart = -1; + } + } + } + + if (subgroupStart !== -1 && combinators.length) { + terms.splice( + subgroupStart, + i - subgroupStart, + createGroup(terms.slice(subgroupStart, i), combinator) + ); + } + } + + return combinator; +} + +function readImplicitGroup(scanner, stopCharCode) { + const combinators = Object.create(null); + const terms = []; + let token; + let prevToken = null; + let prevTokenPos = scanner.pos; + + while (scanner.charCode() !== stopCharCode && (token = peek(scanner, stopCharCode))) { + if (token.type !== 'Spaces') { + if (token.type === 'Combinator') { + // check for combinator in group beginning and double combinator sequence + if (prevToken === null || prevToken.type === 'Combinator') { + scanner.pos = prevTokenPos; + scanner.error('Unexpected combinator'); + } + + combinators[token.value] = true; + } else if (prevToken !== null && prevToken.type !== 'Combinator') { + combinators[' '] = true; // a b + terms.push({ + type: 'Combinator', + value: ' ' + }); + } + + terms.push(token); + prevToken = token; + prevTokenPos = scanner.pos; + } + } + + // check for combinator in group ending + if (prevToken !== null && prevToken.type === 'Combinator') { + scanner.pos -= prevTokenPos; + scanner.error('Unexpected combinator'); + } + + return { + type: 'Group', + terms, + combinator: regroupTerms(terms, combinators) || ' ', + disallowEmpty: false, + explicit: false + }; +} + +function readGroup(scanner, stopCharCode) { + let result; + + scanner.eat(LEFTSQUAREBRACKET); + result = readImplicitGroup(scanner, stopCharCode); + scanner.eat(RIGHTSQUAREBRACKET); + + result.explicit = true; + + if (scanner.charCode() === EXCLAMATIONMARK) { + scanner.pos++; + result.disallowEmpty = true; + } + + return result; +} + +function peek(scanner, stopCharCode) { + let code = scanner.charCode(); + + switch (code) { + case RIGHTSQUAREBRACKET: + // don't eat, stop scan a group + break; + + case LEFTSQUAREBRACKET: + return maybeMultiplied(scanner, readGroup(scanner, stopCharCode)); + + case LESSTHANSIGN: + return scanner.nextCharCode() === APOSTROPHE + ? readProperty(scanner) + : readType(scanner); + + case VERTICALLINE: + return { + type: 'Combinator', + value: scanner.substringToPos( + scanner.pos + (scanner.nextCharCode() === VERTICALLINE ? 2 : 1) + ) + }; + + case AMPERSAND: + scanner.pos++; + scanner.eat(AMPERSAND); + + return { + type: 'Combinator', + value: '&&' + }; + + case COMMA: + scanner.pos++; + return { + type: 'Comma' + }; + + case APOSTROPHE: + return maybeMultiplied(scanner, { + type: 'String', + value: scanner.scanString() + }); + + case SPACE: + case TAB: + case N: + case R: + case F: + return { + type: 'Spaces', + value: scanner.scanSpaces() + }; + + case COMMERCIALAT: + code = scanner.nextCharCode(); + + if (scanner.isNameCharCode(code)) { + scanner.pos++; + return { + type: 'AtKeyword', + name: scanner.scanWord() + }; + } + + return maybeToken(scanner); + + case ASTERISK: + case PLUSSIGN: + case QUESTIONMARK: + case NUMBERSIGN: + case EXCLAMATIONMARK: + // prohibited tokens (used as a multiplier start) + break; + + case LEFTCURLYBRACKET: + // LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting + // check next char isn't a number, because it's likely a disjoined multiplier + code = scanner.nextCharCode(); + + if (code < 48 || code > 57) { + return maybeToken(scanner); + } + + break; + + default: + if (scanner.isNameCharCode(code)) { + return readKeywordOrFunction(scanner); + } + + return maybeToken(scanner); + } +} + +function parse(source) { + const scanner$1 = new scanner.Scanner(source); + const result = readImplicitGroup(scanner$1); + + if (scanner$1.pos !== source.length) { + scanner$1.error('Unexpected input'); + } + + // reduce redundant groups with single group term + if (result.terms.length === 1 && result.terms[0].type === 'Group') { + return result.terms[0]; + } + + return result; +} + +exports.parse = parse; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/scanner.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/scanner.cjs new file mode 100644 index 0000000..0bad36a --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/scanner.cjs @@ -0,0 +1,113 @@ +'use strict'; + +const SyntaxError = require('./SyntaxError.cjs'); + +const TAB = 9; +const N = 10; +const F = 12; +const R = 13; +const SPACE = 32; +const NAME_CHAR = new Uint8Array(128).map((_, idx) => + /[a-zA-Z0-9\-]/.test(String.fromCharCode(idx)) ? 1 : 0 +); + +class Scanner { + constructor(str) { + this.str = str; + this.pos = 0; + } + + charCodeAt(pos) { + return pos < this.str.length ? this.str.charCodeAt(pos) : 0; + } + charCode() { + return this.charCodeAt(this.pos); + } + isNameCharCode(code = this.charCode()) { + return code < 128 && NAME_CHAR[code] === 1; + } + nextCharCode() { + return this.charCodeAt(this.pos + 1); + } + nextNonWsCode(pos) { + return this.charCodeAt(this.findWsEnd(pos)); + } + skipWs() { + this.pos = this.findWsEnd(this.pos); + } + findWsEnd(pos) { + for (; pos < this.str.length; pos++) { + const code = this.str.charCodeAt(pos); + if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) { + break; + } + } + + return pos; + } + substringToPos(end) { + return this.str.substring(this.pos, this.pos = end); + } + eat(code) { + if (this.charCode() !== code) { + this.error('Expect `' + String.fromCharCode(code) + '`'); + } + + this.pos++; + } + peek() { + return this.pos < this.str.length ? this.str.charAt(this.pos++) : ''; + } + error(message) { + throw new SyntaxError.SyntaxError(message, this.str, this.pos); + } + + scanSpaces() { + return this.substringToPos(this.findWsEnd(this.pos)); + } + scanWord() { + let end = this.pos; + + for (; end < this.str.length; end++) { + const code = this.str.charCodeAt(end); + if (code >= 128 || NAME_CHAR[code] === 0) { + break; + } + } + + if (this.pos === end) { + this.error('Expect a keyword'); + } + + return this.substringToPos(end); + } + scanNumber() { + let end = this.pos; + + for (; end < this.str.length; end++) { + const code = this.str.charCodeAt(end); + + if (code < 48 || code > 57) { + break; + } + } + + if (this.pos === end) { + this.error('Expect a number'); + } + + return this.substringToPos(end); + } + scanString() { + const end = this.str.indexOf('\'', this.pos + 1); + + if (end === -1) { + this.pos = this.str.length; + this.error('Expect an apostrophe'); + } + + return this.substringToPos(end + 1); + } +} + +exports.Scanner = Scanner; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/tokenizer.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/tokenizer.cjs new file mode 100644 index 0000000..2b934bd --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/tokenizer.cjs @@ -0,0 +1,59 @@ +'use strict'; + +const SyntaxError = require('./SyntaxError.cjs'); + +const TAB = 9; +const N = 10; +const F = 12; +const R = 13; +const SPACE = 32; + +class Tokenizer { + constructor(str) { + this.str = str; + this.pos = 0; + } + charCodeAt(pos) { + return pos < this.str.length ? this.str.charCodeAt(pos) : 0; + } + charCode() { + return this.charCodeAt(this.pos); + } + nextCharCode() { + return this.charCodeAt(this.pos + 1); + } + nextNonWsCode(pos) { + return this.charCodeAt(this.findWsEnd(pos)); + } + skipWs() { + this.pos = this.findWsEnd(this.pos); + } + findWsEnd(pos) { + for (; pos < this.str.length; pos++) { + const code = this.str.charCodeAt(pos); + if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) { + break; + } + } + + return pos; + } + substringToPos(end) { + return this.str.substring(this.pos, this.pos = end); + } + eat(code) { + if (this.charCode() !== code) { + this.error('Expect `' + String.fromCharCode(code) + '`'); + } + + this.pos++; + } + peek() { + return this.pos < this.str.length ? this.str.charAt(this.pos++) : ''; + } + error(message) { + throw new SyntaxError.SyntaxError(message, this.str, this.pos); + } +} + +exports.Tokenizer = Tokenizer; diff --git a/vanilla/node_modules/css-tree/cjs/definition-syntax/walk.cjs b/vanilla/node_modules/css-tree/cjs/definition-syntax/walk.cjs new file mode 100644 index 0000000..fdba065 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/definition-syntax/walk.cjs @@ -0,0 +1,57 @@ +'use strict'; + +const noop = function() {}; + +function ensureFunction(value) { + return typeof value === 'function' ? value : noop; +} + +function walk(node, options, context) { + function walk(node) { + enter.call(context, node); + + switch (node.type) { + case 'Group': + node.terms.forEach(walk); + break; + + case 'Multiplier': + case 'Boolean': + walk(node.term); + break; + + case 'Type': + case 'Property': + case 'Keyword': + case 'AtKeyword': + case 'Function': + case 'String': + case 'Token': + case 'Comma': + break; + + default: + throw new Error('Unknown type: ' + node.type); + } + + leave.call(context, node); + } + + let enter = noop; + let leave = noop; + + if (typeof options === 'function') { + enter = options; + } else if (options) { + enter = ensureFunction(options.enter); + leave = ensureFunction(options.leave); + } + + if (enter === noop && leave === noop) { + throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function'); + } + + walk(node); +} + +exports.walk = walk; diff --git a/vanilla/node_modules/css-tree/cjs/generator/create.cjs b/vanilla/node_modules/css-tree/cjs/generator/create.cjs new file mode 100644 index 0000000..87a54b2 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/generator/create.cjs @@ -0,0 +1,102 @@ +'use strict'; + +const index = require('../tokenizer/index.cjs'); +const sourceMap = require('./sourceMap.cjs'); +const tokenBefore = require('./token-before.cjs'); +const types = require('../tokenizer/types.cjs'); + +const REVERSESOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\) + +function processChildren(node, delimeter) { + if (typeof delimeter === 'function') { + let prev = null; + + node.children.forEach(node => { + if (prev !== null) { + delimeter.call(this, prev); + } + + this.node(node); + prev = node; + }); + + return; + } + + node.children.forEach(this.node, this); +} + +function processChunk(chunk) { + index.tokenize(chunk, (type, start, end) => { + this.token(type, chunk.slice(start, end)); + }); +} + +function createGenerator(config) { + const types$1 = new Map(); + + for (let [name, item] of Object.entries(config.node)) { + const fn = item.generate || item; + + if (typeof fn === 'function') { + types$1.set(name, item.generate || item); + } + } + + return function(node, options) { + let buffer = ''; + let prevCode = 0; + let handlers = { + node(node) { + if (types$1.has(node.type)) { + types$1.get(node.type).call(publicApi, node); + } else { + throw new Error('Unknown node type: ' + node.type); + } + }, + tokenBefore: tokenBefore.safe, + token(type, value) { + prevCode = this.tokenBefore(prevCode, type, value); + + this.emit(value, type, false); + + if (type === types.Delim && value.charCodeAt(0) === REVERSESOLIDUS) { + this.emit('\n', types.WhiteSpace, true); + } + }, + emit(value) { + buffer += value; + }, + result() { + return buffer; + } + }; + + if (options) { + if (typeof options.decorator === 'function') { + handlers = options.decorator(handlers); + } + + if (options.sourceMap) { + handlers = sourceMap.generateSourceMap(handlers); + } + + if (options.mode in tokenBefore) { + handlers.tokenBefore = tokenBefore[options.mode]; + } + } + + const publicApi = { + node: (node) => handlers.node(node), + children: processChildren, + token: (type, value) => handlers.token(type, value), + tokenize: processChunk + }; + + handlers.node(node); + + return handlers.result(); + }; +} + +exports.createGenerator = createGenerator; diff --git a/vanilla/node_modules/css-tree/cjs/generator/index.cjs b/vanilla/node_modules/css-tree/cjs/generator/index.cjs new file mode 100644 index 0000000..5c87cd3 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/generator/index.cjs @@ -0,0 +1,8 @@ +'use strict'; + +const create = require('./create.cjs'); +const generator = require('../syntax/config/generator.cjs'); + +const index = create.createGenerator(generator); + +module.exports = index; diff --git a/vanilla/node_modules/css-tree/cjs/generator/sourceMap.cjs b/vanilla/node_modules/css-tree/cjs/generator/sourceMap.cjs new file mode 100644 index 0000000..efbc5b9 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/generator/sourceMap.cjs @@ -0,0 +1,96 @@ +'use strict'; + +const sourceMapGenerator_js = require('source-map-js/lib/source-map-generator.js'); + +const trackNodes = new Set(['Atrule', 'Selector', 'Declaration']); + +function generateSourceMap(handlers) { + const map = new sourceMapGenerator_js.SourceMapGenerator(); + const generated = { + line: 1, + column: 0 + }; + const original = { + line: 0, // should be zero to add first mapping + column: 0 + }; + const activatedGenerated = { + line: 1, + column: 0 + }; + const activatedMapping = { + generated: activatedGenerated + }; + let line = 1; + let column = 0; + let sourceMappingActive = false; + + const origHandlersNode = handlers.node; + handlers.node = function(node) { + if (node.loc && node.loc.start && trackNodes.has(node.type)) { + const nodeLine = node.loc.start.line; + const nodeColumn = node.loc.start.column - 1; + + if (original.line !== nodeLine || + original.column !== nodeColumn) { + original.line = nodeLine; + original.column = nodeColumn; + + generated.line = line; + generated.column = column; + + if (sourceMappingActive) { + sourceMappingActive = false; + if (generated.line !== activatedGenerated.line || + generated.column !== activatedGenerated.column) { + map.addMapping(activatedMapping); + } + } + + sourceMappingActive = true; + map.addMapping({ + source: node.loc.source, + original, + generated + }); + } + } + + origHandlersNode.call(this, node); + + if (sourceMappingActive && trackNodes.has(node.type)) { + activatedGenerated.line = line; + activatedGenerated.column = column; + } + }; + + const origHandlersEmit = handlers.emit; + handlers.emit = function(value, type, auto) { + for (let i = 0; i < value.length; i++) { + if (value.charCodeAt(i) === 10) { // \n + line++; + column = 0; + } else { + column++; + } + } + + origHandlersEmit(value, type, auto); + }; + + const origHandlersResult = handlers.result; + handlers.result = function() { + if (sourceMappingActive) { + map.addMapping(activatedMapping); + } + + return { + css: origHandlersResult(), + map + }; + }; + + return handlers; +} + +exports.generateSourceMap = generateSourceMap; diff --git a/vanilla/node_modules/css-tree/cjs/generator/token-before.cjs b/vanilla/node_modules/css-tree/cjs/generator/token-before.cjs new file mode 100644 index 0000000..87bf4a3 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/generator/token-before.cjs @@ -0,0 +1,170 @@ +'use strict'; + +const types = require('../tokenizer/types.cjs'); + +const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+) +const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-) + +const code = (type, value) => { + if (type === types.Delim) { + type = value; + } + + if (typeof type === 'string') { + const charCode = type.charCodeAt(0); + return charCode > 0x7F ? 0x8000 : charCode << 8; + } + + return type; +}; + +// https://www.w3.org/TR/css-syntax-3/#serialization +// The only requirement for serialization is that it must "round-trip" with parsing, +// that is, parsing the stylesheet must produce the same data structures as parsing, +// serializing, and parsing again, except for consecutive s, +// which may be collapsed into a single token. + +const specPairs = [ + [types.Ident, types.Ident], + [types.Ident, types.Function], + [types.Ident, types.Url], + [types.Ident, types.BadUrl], + [types.Ident, '-'], + [types.Ident, types.Number], + [types.Ident, types.Percentage], + [types.Ident, types.Dimension], + [types.Ident, types.CDC], + [types.Ident, types.LeftParenthesis], + + [types.AtKeyword, types.Ident], + [types.AtKeyword, types.Function], + [types.AtKeyword, types.Url], + [types.AtKeyword, types.BadUrl], + [types.AtKeyword, '-'], + [types.AtKeyword, types.Number], + [types.AtKeyword, types.Percentage], + [types.AtKeyword, types.Dimension], + [types.AtKeyword, types.CDC], + + [types.Hash, types.Ident], + [types.Hash, types.Function], + [types.Hash, types.Url], + [types.Hash, types.BadUrl], + [types.Hash, '-'], + [types.Hash, types.Number], + [types.Hash, types.Percentage], + [types.Hash, types.Dimension], + [types.Hash, types.CDC], + + [types.Dimension, types.Ident], + [types.Dimension, types.Function], + [types.Dimension, types.Url], + [types.Dimension, types.BadUrl], + [types.Dimension, '-'], + [types.Dimension, types.Number], + [types.Dimension, types.Percentage], + [types.Dimension, types.Dimension], + [types.Dimension, types.CDC], + + ['#', types.Ident], + ['#', types.Function], + ['#', types.Url], + ['#', types.BadUrl], + ['#', '-'], + ['#', types.Number], + ['#', types.Percentage], + ['#', types.Dimension], + ['#', types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 + + ['-', types.Ident], + ['-', types.Function], + ['-', types.Url], + ['-', types.BadUrl], + ['-', '-'], + ['-', types.Number], + ['-', types.Percentage], + ['-', types.Dimension], + ['-', types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 + + [types.Number, types.Ident], + [types.Number, types.Function], + [types.Number, types.Url], + [types.Number, types.BadUrl], + [types.Number, types.Number], + [types.Number, types.Percentage], + [types.Number, types.Dimension], + [types.Number, '%'], + [types.Number, types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 + + ['@', types.Ident], + ['@', types.Function], + ['@', types.Url], + ['@', types.BadUrl], + ['@', '-'], + ['@', types.CDC], // https://github.com/w3c/csswg-drafts/pull/6874 + + ['.', types.Number], + ['.', types.Percentage], + ['.', types.Dimension], + + ['+', types.Number], + ['+', types.Percentage], + ['+', types.Dimension], + + ['/', '*'] +]; +// validate with scripts/generate-safe +const safePairs = specPairs.concat([ + [types.Ident, types.Hash], + + [types.Dimension, types.Hash], + + [types.Hash, types.Hash], + + [types.AtKeyword, types.LeftParenthesis], + [types.AtKeyword, types.String], + [types.AtKeyword, types.Colon], + + [types.Percentage, types.Percentage], + [types.Percentage, types.Dimension], + [types.Percentage, types.Function], + [types.Percentage, '-'], + + [types.RightParenthesis, types.Ident], + [types.RightParenthesis, types.Function], + [types.RightParenthesis, types.Percentage], + [types.RightParenthesis, types.Dimension], + [types.RightParenthesis, types.Hash], + [types.RightParenthesis, '-'] +]); + +function createMap(pairs) { + const isWhiteSpaceRequired = new Set( + pairs.map(([prev, next]) => (code(prev) << 16 | code(next))) + ); + + return function(prevCode, type, value) { + const nextCode = code(type, value); + const nextCharCode = value.charCodeAt(0); + const emitWs = + (nextCharCode === HYPHENMINUS && + type !== types.Ident && + type !== types.Function && + type !== types.CDC) || + (nextCharCode === PLUSSIGN) + ? isWhiteSpaceRequired.has(prevCode << 16 | nextCharCode << 8) + : isWhiteSpaceRequired.has(prevCode << 16 | nextCode); + + if (emitWs) { + this.emit(' ', types.WhiteSpace, true); + } + + return nextCode; + }; +} + +const spec = createMap(specPairs); +const safe = createMap(safePairs); + +exports.safe = safe; +exports.spec = spec; diff --git a/vanilla/node_modules/css-tree/cjs/index.cjs b/vanilla/node_modules/css-tree/cjs/index.cjs new file mode 100644 index 0000000..cc61137 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/index.cjs @@ -0,0 +1,65 @@ +'use strict'; + +const index$1 = require('./syntax/index.cjs'); +const version = require('./version.cjs'); +const create = require('./syntax/create.cjs'); +const List = require('./utils/List.cjs'); +const Lexer = require('./lexer/Lexer.cjs'); +const index = require('./definition-syntax/index.cjs'); +const clone = require('./utils/clone.cjs'); +const names$1 = require('./utils/names.cjs'); +const ident = require('./utils/ident.cjs'); +const string = require('./utils/string.cjs'); +const url = require('./utils/url.cjs'); +const types = require('./tokenizer/types.cjs'); +const names = require('./tokenizer/names.cjs'); +const TokenStream = require('./tokenizer/TokenStream.cjs'); +const OffsetToLocation = require('./tokenizer/OffsetToLocation.cjs'); + +const { + tokenize, + parse, + generate, + lexer, + createLexer, + + walk, + find, + findLast, + findAll, + + toPlainObject, + fromPlainObject, + + fork +} = index$1; + +exports.version = version.version; +exports.createSyntax = create; +exports.List = List.List; +exports.Lexer = Lexer.Lexer; +exports.definitionSyntax = index; +exports.clone = clone.clone; +exports.isCustomProperty = names$1.isCustomProperty; +exports.keyword = names$1.keyword; +exports.property = names$1.property; +exports.vendorPrefix = names$1.vendorPrefix; +exports.ident = ident; +exports.string = string; +exports.url = url; +exports.tokenTypes = types; +exports.tokenNames = names; +exports.TokenStream = TokenStream.TokenStream; +exports.OffsetToLocation = OffsetToLocation.OffsetToLocation; +exports.createLexer = createLexer; +exports.find = find; +exports.findAll = findAll; +exports.findLast = findLast; +exports.fork = fork; +exports.fromPlainObject = fromPlainObject; +exports.generate = generate; +exports.lexer = lexer; +exports.parse = parse; +exports.toPlainObject = toPlainObject; +exports.tokenize = tokenize; +exports.walk = walk; diff --git a/vanilla/node_modules/css-tree/cjs/lexer/Lexer.cjs b/vanilla/node_modules/css-tree/cjs/lexer/Lexer.cjs new file mode 100644 index 0000000..a6d1fcb --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/lexer/Lexer.cjs @@ -0,0 +1,517 @@ +'use strict'; + +const error = require('./error.cjs'); +const names = require('../utils/names.cjs'); +const genericConst = require('./generic-const.cjs'); +const generic = require('./generic.cjs'); +const units = require('./units.cjs'); +const prepareTokens = require('./prepare-tokens.cjs'); +const matchGraph = require('./match-graph.cjs'); +const match = require('./match.cjs'); +const trace = require('./trace.cjs'); +const search = require('./search.cjs'); +const structure = require('./structure.cjs'); +const parse = require('../definition-syntax/parse.cjs'); +const generate = require('../definition-syntax/generate.cjs'); +const walk = require('../definition-syntax/walk.cjs'); + +function dumpMapSyntax(map, compact, syntaxAsAst) { + const result = {}; + + for (const name in map) { + if (map[name].syntax) { + result[name] = syntaxAsAst + ? map[name].syntax + : generate.generate(map[name].syntax, { compact }); + } + } + + return result; +} + +function dumpAtruleMapSyntax(map, compact, syntaxAsAst) { + const result = {}; + + for (const [name, atrule] of Object.entries(map)) { + result[name] = { + prelude: atrule.prelude && ( + syntaxAsAst + ? atrule.prelude.syntax + : generate.generate(atrule.prelude.syntax, { compact }) + ), + descriptors: atrule.descriptors && dumpMapSyntax(atrule.descriptors, compact, syntaxAsAst) + }; + } + + return result; +} + +function valueHasVar(tokens) { + for (let i = 0; i < tokens.length; i++) { + if (tokens[i].value.toLowerCase() === 'var(') { + return true; + } + } + + return false; +} + +function syntaxHasTopLevelCommaMultiplier(syntax) { + const singleTerm = syntax.terms[0]; + + return ( + syntax.explicit === false && + syntax.terms.length === 1 && + singleTerm.type === 'Multiplier' && + singleTerm.comma === true + ); +} + +function buildMatchResult(matched, error, iterations) { + return { + matched, + iterations, + error, + ...trace + }; +} + +function matchSyntax(lexer, syntax, value, useCssWideKeywords) { + const tokens = prepareTokens(value, lexer.syntax); + let result; + + if (valueHasVar(tokens)) { + return buildMatchResult(null, new Error('Matching for a tree with var() is not supported')); + } + + if (useCssWideKeywords) { + result = match.matchAsTree(tokens, lexer.cssWideKeywordsSyntax, lexer); + } + + if (!useCssWideKeywords || !result.match) { + result = match.matchAsTree(tokens, syntax.match, lexer); + if (!result.match) { + return buildMatchResult( + null, + new error.SyntaxMatchError(result.reason, syntax.syntax, value, result), + result.iterations + ); + } + } + + return buildMatchResult(result.match, null, result.iterations); +} + +class Lexer { + constructor(config, syntax, structure$1) { + this.cssWideKeywords = genericConst.cssWideKeywords; + this.syntax = syntax; + this.generic = false; + this.units = { ...units }; + this.atrules = Object.create(null); + this.properties = Object.create(null); + this.types = Object.create(null); + this.structure = structure$1 || structure.getStructureFromConfig(config); + + if (config) { + if (config.cssWideKeywords) { + this.cssWideKeywords = config.cssWideKeywords; + } + + if (config.units) { + for (const group of Object.keys(units)) { + if (Array.isArray(config.units[group])) { + this.units[group] = config.units[group]; + } + } + } + + if (config.types) { + for (const [name, type] of Object.entries(config.types)) { + this.addType_(name, type); + } + } + + if (config.generic) { + this.generic = true; + for (const [name, value] of Object.entries(generic.createGenericTypes(this.units))) { + this.addType_(name, value); + } + } + + if (config.atrules) { + for (const [name, atrule] of Object.entries(config.atrules)) { + this.addAtrule_(name, atrule); + } + } + + if (config.properties) { + for (const [name, property] of Object.entries(config.properties)) { + this.addProperty_(name, property); + } + } + } + + this.cssWideKeywordsSyntax = matchGraph.buildMatchGraph(this.cssWideKeywords.join(' | ')); + } + + checkStructure(ast) { + function collectWarning(node, message) { + warns.push({ node, message }); + } + + const structure = this.structure; + const warns = []; + + this.syntax.walk(ast, function(node) { + if (structure.hasOwnProperty(node.type)) { + structure[node.type].check(node, collectWarning); + } else { + collectWarning(node, 'Unknown node type `' + node.type + '`'); + } + }); + + return warns.length ? warns : false; + } + + createDescriptor(syntax, type, name, parent = null) { + const ref = { + type, + name + }; + const descriptor = { + type, + name, + parent, + serializable: typeof syntax === 'string' || (syntax && typeof syntax.type === 'string'), + syntax: null, + match: null, + matchRef: null // used for properties when a syntax referenced as <'property'> in other syntax definitions + }; + + if (typeof syntax === 'function') { + descriptor.match = matchGraph.buildMatchGraph(syntax, ref); + } else { + if (typeof syntax === 'string') { + // lazy parsing on first access + Object.defineProperty(descriptor, 'syntax', { + get() { + Object.defineProperty(descriptor, 'syntax', { + value: parse.parse(syntax) + }); + + return descriptor.syntax; + } + }); + } else { + descriptor.syntax = syntax; + } + + // lazy graph build on first access + Object.defineProperty(descriptor, 'match', { + get() { + Object.defineProperty(descriptor, 'match', { + value: matchGraph.buildMatchGraph(descriptor.syntax, ref) + }); + + return descriptor.match; + } + }); + + if (type === 'Property') { + Object.defineProperty(descriptor, 'matchRef', { + get() { + const syntax = descriptor.syntax; + const value = syntaxHasTopLevelCommaMultiplier(syntax) + ? matchGraph.buildMatchGraph({ + ...syntax, + terms: [syntax.terms[0].term] + }, ref) + : null; + + Object.defineProperty(descriptor, 'matchRef', { + value + }); + + return value; + } + }); + } + } + + return descriptor; + } + addAtrule_(name, syntax) { + if (!syntax) { + return; + } + + this.atrules[name] = { + type: 'Atrule', + name: name, + prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null, + descriptors: syntax.descriptors + ? Object.keys(syntax.descriptors).reduce( + (map, descName) => { + map[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name); + return map; + }, + Object.create(null) + ) + : null + }; + } + addProperty_(name, syntax) { + if (!syntax) { + return; + } + + this.properties[name] = this.createDescriptor(syntax, 'Property', name); + } + addType_(name, syntax) { + if (!syntax) { + return; + } + + this.types[name] = this.createDescriptor(syntax, 'Type', name); + } + + checkAtruleName(atruleName) { + if (!this.getAtrule(atruleName)) { + return new error.SyntaxReferenceError('Unknown at-rule', '@' + atruleName); + } + } + checkAtrulePrelude(atruleName, prelude) { + const error = this.checkAtruleName(atruleName); + + if (error) { + return error; + } + + const atrule = this.getAtrule(atruleName); + + if (!atrule.prelude && prelude) { + return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude'); + } + + if (atrule.prelude && !prelude) { + if (!matchSyntax(this, atrule.prelude, '', false).matched) { + return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude'); + } + } + } + checkAtruleDescriptorName(atruleName, descriptorName) { + const error$1 = this.checkAtruleName(atruleName); + + if (error$1) { + return error$1; + } + + const atrule = this.getAtrule(atruleName); + const descriptor = names.keyword(descriptorName); + + if (!atrule.descriptors) { + return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors'); + } + + if (!atrule.descriptors[descriptor.name] && + !atrule.descriptors[descriptor.basename]) { + return new error.SyntaxReferenceError('Unknown at-rule descriptor', descriptorName); + } + } + checkPropertyName(propertyName) { + if (!this.getProperty(propertyName)) { + return new error.SyntaxReferenceError('Unknown property', propertyName); + } + } + + matchAtrulePrelude(atruleName, prelude) { + const error = this.checkAtrulePrelude(atruleName, prelude); + + if (error) { + return buildMatchResult(null, error); + } + + const atrule = this.getAtrule(atruleName); + + if (!atrule.prelude) { + return buildMatchResult(null, null); + } + + return matchSyntax(this, atrule.prelude, prelude || '', false); + } + matchAtruleDescriptor(atruleName, descriptorName, value) { + const error = this.checkAtruleDescriptorName(atruleName, descriptorName); + + if (error) { + return buildMatchResult(null, error); + } + + const atrule = this.getAtrule(atruleName); + const descriptor = names.keyword(descriptorName); + + return matchSyntax(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false); + } + matchDeclaration(node) { + if (node.type !== 'Declaration') { + return buildMatchResult(null, new Error('Not a Declaration node')); + } + + return this.matchProperty(node.property, node.value); + } + matchProperty(propertyName, value) { + // don't match syntax for a custom property at the moment + if (names.property(propertyName).custom) { + return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties')); + } + + const error = this.checkPropertyName(propertyName); + + if (error) { + return buildMatchResult(null, error); + } + + return matchSyntax(this, this.getProperty(propertyName), value, true); + } + matchType(typeName, value) { + const typeSyntax = this.getType(typeName); + + if (!typeSyntax) { + return buildMatchResult(null, new error.SyntaxReferenceError('Unknown type', typeName)); + } + + return matchSyntax(this, typeSyntax, value, false); + } + match(syntax, value) { + if (typeof syntax !== 'string' && (!syntax || !syntax.type)) { + return buildMatchResult(null, new error.SyntaxReferenceError('Bad syntax')); + } + + if (typeof syntax === 'string' || !syntax.match) { + syntax = this.createDescriptor(syntax, 'Type', 'anonymous'); + } + + return matchSyntax(this, syntax, value, false); + } + + findValueFragments(propertyName, value, type, name) { + return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name); + } + findDeclarationValueFragments(declaration, type, name) { + return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name); + } + findAllFragments(ast, type, name) { + const result = []; + + this.syntax.walk(ast, { + visit: 'Declaration', + enter: (declaration) => { + result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name)); + } + }); + + return result; + } + + getAtrule(atruleName, fallbackBasename = true) { + const atrule = names.keyword(atruleName); + const atruleEntry = atrule.vendor && fallbackBasename + ? this.atrules[atrule.name] || this.atrules[atrule.basename] + : this.atrules[atrule.name]; + + return atruleEntry || null; + } + getAtrulePrelude(atruleName, fallbackBasename = true) { + const atrule = this.getAtrule(atruleName, fallbackBasename); + + return atrule && atrule.prelude || null; + } + getAtruleDescriptor(atruleName, name) { + return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators + ? this.atrules[atruleName].declarators[name] || null + : null; + } + getProperty(propertyName, fallbackBasename = true) { + const property = names.property(propertyName); + const propertyEntry = property.vendor && fallbackBasename + ? this.properties[property.name] || this.properties[property.basename] + : this.properties[property.name]; + + return propertyEntry || null; + } + getType(name) { + return hasOwnProperty.call(this.types, name) ? this.types[name] : null; + } + + validate() { + function syntaxRef(name, isType) { + return isType ? `<${name}>` : `<'${name}'>`; + } + + function validate(syntax, name, broken, descriptor) { + if (broken.has(name)) { + return broken.get(name); + } + + broken.set(name, false); + if (descriptor.syntax !== null) { + walk.walk(descriptor.syntax, function(node) { + if (node.type !== 'Type' && node.type !== 'Property') { + return; + } + + const map = node.type === 'Type' ? syntax.types : syntax.properties; + const brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties; + + if (!hasOwnProperty.call(map, node.name)) { + errors.push(`${syntaxRef(name, broken === brokenTypes)} used missed syntax definition ${syntaxRef(node.name, node.type === 'Type')}`); + broken.set(name, true); + } else if (validate(syntax, node.name, brokenMap, map[node.name])) { + errors.push(`${syntaxRef(name, broken === brokenTypes)} used broken syntax definition ${syntaxRef(node.name, node.type === 'Type')}`); + broken.set(name, true); + } + }, this); + } + } + + const errors = []; + let brokenTypes = new Map(); + let brokenProperties = new Map(); + + for (const key in this.types) { + validate(this, key, brokenTypes, this.types[key]); + } + + for (const key in this.properties) { + validate(this, key, brokenProperties, this.properties[key]); + } + + const brokenTypesArray = [...brokenTypes.keys()].filter(name => brokenTypes.get(name)); + const brokenPropertiesArray = [...brokenProperties.keys()].filter(name => brokenProperties.get(name)); + + if (brokenTypesArray.length || brokenPropertiesArray.length) { + return { + errors, + types: brokenTypesArray, + properties: brokenPropertiesArray + }; + } + + return null; + } + dump(syntaxAsAst, pretty) { + return { + generic: this.generic, + cssWideKeywords: this.cssWideKeywords, + units: this.units, + types: dumpMapSyntax(this.types, !pretty, syntaxAsAst), + properties: dumpMapSyntax(this.properties, !pretty, syntaxAsAst), + atrules: dumpAtruleMapSyntax(this.atrules, !pretty, syntaxAsAst) + }; + } + toString() { + return JSON.stringify(this.dump()); + } +} + +exports.Lexer = Lexer; diff --git a/vanilla/node_modules/css-tree/cjs/lexer/error.cjs b/vanilla/node_modules/css-tree/cjs/lexer/error.cjs new file mode 100644 index 0000000..8d252ee --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/lexer/error.cjs @@ -0,0 +1,128 @@ +'use strict'; + +const createCustomError = require('../utils/create-custom-error.cjs'); +const generate = require('../definition-syntax/generate.cjs'); + +const defaultLoc = { offset: 0, line: 1, column: 1 }; + +function locateMismatch(matchResult, node) { + const tokens = matchResult.tokens; + const longestMatch = matchResult.longestMatch; + const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null; + const badNode = mismatchNode !== node ? mismatchNode : null; + let mismatchOffset = 0; + let mismatchLength = 0; + let entries = 0; + let css = ''; + let start; + let end; + + for (let i = 0; i < tokens.length; i++) { + const token = tokens[i].value; + + if (i === longestMatch) { + mismatchLength = token.length; + mismatchOffset = css.length; + } + + if (badNode !== null && tokens[i].node === badNode) { + if (i <= longestMatch) { + entries++; + } else { + entries = 0; + } + } + + css += token; + } + + if (longestMatch === tokens.length || entries > 1) { // last + start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css); + end = buildLoc(start); + } else { + start = fromLoc(badNode, 'start') || + buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset)); + end = fromLoc(badNode, 'end') || + buildLoc(start, css.substr(mismatchOffset, mismatchLength)); + } + + return { + css, + mismatchOffset, + mismatchLength, + start, + end + }; +} + +function fromLoc(node, point) { + const value = node && node.loc && node.loc[point]; + + if (value) { + return 'line' in value ? buildLoc(value) : value; + } + + return null; +} + +function buildLoc({ offset, line, column }, extra) { + const loc = { + offset, + line, + column + }; + + if (extra) { + const lines = extra.split(/\n|\r\n?|\f/); + + loc.offset += extra.length; + loc.line += lines.length - 1; + loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1; + } + + return loc; +} + +const SyntaxReferenceError = function(type, referenceName) { + const error = createCustomError.createCustomError( + 'SyntaxReferenceError', + type + (referenceName ? ' `' + referenceName + '`' : '') + ); + + error.reference = referenceName; + + return error; +}; + +const SyntaxMatchError = function(message, syntax, node, matchResult) { + const error = createCustomError.createCustomError('SyntaxMatchError', message); + const { + css, + mismatchOffset, + mismatchLength, + start, + end + } = locateMismatch(matchResult, node); + + error.rawMessage = message; + error.syntax = syntax ? generate.generate(syntax) : ''; + error.css = css; + error.mismatchOffset = mismatchOffset; + error.mismatchLength = mismatchLength; + error.message = message + '\n' + + ' syntax: ' + error.syntax + '\n' + + ' value: ' + (css || '') + '\n' + + ' --------' + new Array(error.mismatchOffset + 1).join('-') + '^'; + + Object.assign(error, start); + error.loc = { + source: (node && node.loc && node.loc.source) || '', + start, + end + }; + + return error; +}; + +exports.SyntaxMatchError = SyntaxMatchError; +exports.SyntaxReferenceError = SyntaxReferenceError; diff --git a/vanilla/node_modules/css-tree/cjs/lexer/generic-an-plus-b.cjs b/vanilla/node_modules/css-tree/cjs/lexer/generic-an-plus-b.cjs new file mode 100644 index 0000000..a5dfba3 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/lexer/generic-an-plus-b.cjs @@ -0,0 +1,235 @@ +'use strict'; + +const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs'); +const types = require('../tokenizer/types.cjs'); +const utils = require('../tokenizer/utils.cjs'); + +const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+) +const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-) +const N = 0x006E; // U+006E LATIN SMALL LETTER N (n) +const DISALLOW_SIGN = true; +const ALLOW_SIGN = false; + +function isDelim(token, code) { + return token !== null && token.type === types.Delim && token.value.charCodeAt(0) === code; +} + +function skipSC(token, offset, getNextToken) { + while (token !== null && (token.type === types.WhiteSpace || token.type === types.Comment)) { + token = getNextToken(++offset); + } + + return offset; +} + +function checkInteger(token, valueOffset, disallowSign, offset) { + if (!token) { + return 0; + } + + const code = token.value.charCodeAt(valueOffset); + + if (code === PLUSSIGN || code === HYPHENMINUS) { + if (disallowSign) { + // Number sign is not allowed + return 0; + } + valueOffset++; + } + + for (; valueOffset < token.value.length; valueOffset++) { + if (!charCodeDefinitions.isDigit(token.value.charCodeAt(valueOffset))) { + // Integer is expected + return 0; + } + } + + return offset + 1; +} + +// ... +// ... ['+' | '-'] +function consumeB(token, offset_, getNextToken) { + let sign = false; + let offset = skipSC(token, offset_, getNextToken); + + token = getNextToken(offset); + + if (token === null) { + return offset_; + } + + if (token.type !== types.Number) { + if (isDelim(token, PLUSSIGN) || isDelim(token, HYPHENMINUS)) { + sign = true; + offset = skipSC(getNextToken(++offset), offset, getNextToken); + token = getNextToken(offset); + + if (token === null || token.type !== types.Number) { + return 0; + } + } else { + return offset_; + } + } + + if (!sign) { + const code = token.value.charCodeAt(0); + if (code !== PLUSSIGN && code !== HYPHENMINUS) { + // Number sign is expected + return 0; + } + } + + return checkInteger(token, sign ? 0 : 1, sign, offset); +} + +// An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb +function anPlusB(token, getNextToken) { + /* eslint-disable brace-style*/ + let offset = 0; + + if (!token) { + return 0; + } + + // + if (token.type === types.Number) { + return checkInteger(token, 0, ALLOW_SIGN, offset); // b + } + + // -n + // -n + // -n ['+' | '-'] + // -n- + // + else if (token.type === types.Ident && token.value.charCodeAt(0) === HYPHENMINUS) { + // expect 1st char is N + if (!utils.cmpChar(token.value, 1, N)) { + return 0; + } + + switch (token.value.length) { + // -n + // -n + // -n ['+' | '-'] + case 2: + return consumeB(getNextToken(++offset), offset, getNextToken); + + // -n- + case 3: + if (token.value.charCodeAt(2) !== HYPHENMINUS) { + return 0; + } + + offset = skipSC(getNextToken(++offset), offset, getNextToken); + token = getNextToken(offset); + + return checkInteger(token, 0, DISALLOW_SIGN, offset); + + // + default: + if (token.value.charCodeAt(2) !== HYPHENMINUS) { + return 0; + } + + return checkInteger(token, 3, DISALLOW_SIGN, offset); + } + } + + // '+'? n + // '+'? n + // '+'? n ['+' | '-'] + // '+'? n- + // '+'? + else if (token.type === types.Ident || (isDelim(token, PLUSSIGN) && getNextToken(offset + 1).type === types.Ident)) { + // just ignore a plus + if (token.type !== types.Ident) { + token = getNextToken(++offset); + } + + if (token === null || !utils.cmpChar(token.value, 0, N)) { + return 0; + } + + switch (token.value.length) { + // '+'? n + // '+'? n + // '+'? n ['+' | '-'] + case 1: + return consumeB(getNextToken(++offset), offset, getNextToken); + + // '+'? n- + case 2: + if (token.value.charCodeAt(1) !== HYPHENMINUS) { + return 0; + } + + offset = skipSC(getNextToken(++offset), offset, getNextToken); + token = getNextToken(offset); + + return checkInteger(token, 0, DISALLOW_SIGN, offset); + + // '+'? + default: + if (token.value.charCodeAt(1) !== HYPHENMINUS) { + return 0; + } + + return checkInteger(token, 2, DISALLOW_SIGN, offset); + } + } + + // + // + // + // + // ['+' | '-'] + else if (token.type === types.Dimension) { + let code = token.value.charCodeAt(0); + let sign = code === PLUSSIGN || code === HYPHENMINUS ? 1 : 0; + let i = sign; + + for (; i < token.value.length; i++) { + if (!charCodeDefinitions.isDigit(token.value.charCodeAt(i))) { + break; + } + } + + if (i === sign) { + // Integer is expected + return 0; + } + + if (!utils.cmpChar(token.value, i, N)) { + return 0; + } + + // + // + // ['+' | '-'] + if (i + 1 === token.value.length) { + return consumeB(getNextToken(++offset), offset, getNextToken); + } else { + if (token.value.charCodeAt(i + 1) !== HYPHENMINUS) { + return 0; + } + + // + if (i + 2 === token.value.length) { + offset = skipSC(getNextToken(++offset), offset, getNextToken); + token = getNextToken(offset); + + return checkInteger(token, 0, DISALLOW_SIGN, offset); + } + // + else { + return checkInteger(token, i + 2, DISALLOW_SIGN, offset); + } + } + } + + return 0; +} + +module.exports = anPlusB; diff --git a/vanilla/node_modules/css-tree/cjs/lexer/generic-const.cjs b/vanilla/node_modules/css-tree/cjs/lexer/generic-const.cjs new file mode 100644 index 0000000..9b9f615 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/lexer/generic-const.cjs @@ -0,0 +1,12 @@ +'use strict'; + +// https://drafts.csswg.org/css-cascade-5/ +const cssWideKeywords = [ + 'initial', + 'inherit', + 'unset', + 'revert', + 'revert-layer' +]; + +exports.cssWideKeywords = cssWideKeywords; diff --git a/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs b/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs new file mode 100644 index 0000000..ce167bb --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/lexer/generic-urange.cjs @@ -0,0 +1,149 @@ +'use strict'; + +const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs'); +const types = require('../tokenizer/types.cjs'); +const utils = require('../tokenizer/utils.cjs'); + +const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+) +const HYPHENMINUS = 0x002D; // U+002D HYPHEN-MINUS (-) +const QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?) +const U = 0x0075; // U+0075 LATIN SMALL LETTER U (u) + +function isDelim(token, code) { + return token !== null && token.type === types.Delim && token.value.charCodeAt(0) === code; +} + +function startsWith(token, code) { + return token.value.charCodeAt(0) === code; +} + +function hexSequence(token, offset, allowDash) { + let hexlen = 0; + + for (let pos = offset; pos < token.value.length; pos++) { + const code = token.value.charCodeAt(pos); + + if (code === HYPHENMINUS && allowDash && hexlen !== 0) { + hexSequence(token, offset + hexlen + 1, false); + return 6; // dissallow following question marks + } + + if (!charCodeDefinitions.isHexDigit(code)) { + return 0; // not a hex digit + } + + if (++hexlen > 6) { + return 0; // too many hex digits + } } + + return hexlen; +} + +function withQuestionMarkSequence(consumed, length, getNextToken) { + if (!consumed) { + return 0; // nothing consumed + } + + while (isDelim(getNextToken(length), QUESTIONMARK)) { + if (++consumed > 6) { + return 0; // too many question marks + } + + length++; + } + + return length; +} + +// https://drafts.csswg.org/css-syntax/#urange +// Informally, the production has three forms: +// U+0001 +// Defines a range consisting of a single code point, in this case the code point "1". +// U+0001-00ff +// Defines a range of codepoints between the first and the second value, in this case +// the range between "1" and "ff" (255 in decimal) inclusive. +// U+00?? +// Defines a range of codepoints where the "?" characters range over all hex digits, +// in this case defining the same as the value U+0000-00ff. +// In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit). +// +// = +// u '+' '?'* | +// u '?'* | +// u '?'* | +// u | +// u | +// u '+' '?'+ +function urange(token, getNextToken) { + let length = 0; + + // should start with `u` or `U` + if (token === null || token.type !== types.Ident || !utils.cmpChar(token.value, 0, U)) { + return 0; + } + + token = getNextToken(++length); + if (token === null) { + return 0; + } + + // u '+' '?'* + // u '+' '?'+ + if (isDelim(token, PLUSSIGN)) { + token = getNextToken(++length); + if (token === null) { + return 0; + } + + if (token.type === types.Ident) { + // u '+' '?'* + return withQuestionMarkSequence(hexSequence(token, 0, true), ++length, getNextToken); + } + + if (isDelim(token, QUESTIONMARK)) { + // u '+' '?'+ + return withQuestionMarkSequence(1, ++length, getNextToken); + } + + // Hex digit or question mark is expected + return 0; + } + + // u '?'* + // u + // u + if (token.type === types.Number) { + const consumedHexLength = hexSequence(token, 1, true); + if (consumedHexLength === 0) { + return 0; + } + + token = getNextToken(++length); + if (token === null) { + // u + return length; + } + + if (token.type === types.Dimension || token.type === types.Number) { + // u + // u + if (!startsWith(token, HYPHENMINUS) || !hexSequence(token, 1, false)) { + return 0; + } + + return length + 1; + } + + // u '?'* + return withQuestionMarkSequence(consumedHexLength, length, getNextToken); + } + + // u '?'* + if (token.type === types.Dimension) { + return withQuestionMarkSequence(hexSequence(token, 1, true), ++length, getNextToken); + } + + return 0; +} + +module.exports = urange; diff --git a/vanilla/node_modules/css-tree/cjs/lexer/generic.cjs b/vanilla/node_modules/css-tree/cjs/lexer/generic.cjs new file mode 100644 index 0000000..8489911 --- /dev/null +++ b/vanilla/node_modules/css-tree/cjs/lexer/generic.cjs @@ -0,0 +1,589 @@ +'use strict'; + +const genericConst = require('./generic-const.cjs'); +const genericAnPlusB = require('./generic-an-plus-b.cjs'); +const genericUrange = require('./generic-urange.cjs'); +const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs'); +const types = require('../tokenizer/types.cjs'); +const utils = require('../tokenizer/utils.cjs'); + +const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc(']; +const balancePair = new Map([ + [types.Function, types.RightParenthesis], + [types.LeftParenthesis, types.RightParenthesis], + [types.LeftSquareBracket, types.RightSquareBracket], + [types.LeftCurlyBracket, types.RightCurlyBracket] +]); + +// safe char code getter +function charCodeAt(str, index) { + return index < str.length ? str.charCodeAt(index) : 0; +} + +function eqStr(actual, expected) { + return utils.cmpStr(actual, 0, actual.length, expected); +} + +function eqStrAny(actual, expected) { + for (let i = 0; i < expected.length; i++) { + if (eqStr(actual, expected[i])) { + return true; + } + } + + return false; +} + +// IE postfix hack, i.e. 123\0 or 123px\9 +function isPostfixIeHack(str, offset) { + if (offset !== str.length - 2) { + return false; + } + + return ( + charCodeAt(str, offset) === 0x005C && // U+005C REVERSE SOLIDUS (\) + charCodeDefinitions.isDigit(charCodeAt(str, offset + 1)) + ); +} + +function outOfRange(opts, value, numEnd) { + if (opts && opts.type === 'Range') { + const num = Number( + numEnd !== undefined && numEnd !== value.length + ? value.substr(0, numEnd) + : value + ); + + if (isNaN(num)) { + return true; + } + + // FIXME: when opts.min is a string it's a dimension, skip a range validation + // for now since it requires a type covertation which is not implmented yet + if (opts.min !== null && num < opts.min && typeof opts.min !== 'string') { + return true; + } + + // FIXME: when opts.max is a string it's a dimension, skip a range validation + // for now since it requires a type covertation which is not implmented yet + if (opts.max !== null && num > opts.max && typeof opts.max !== 'string') { + return true; + } + } + + return false; +} + +function consumeFunction(token, getNextToken) { + let balanceCloseType = 0; + let balanceStash = []; + let length = 0; + + // balanced token consuming + scan: + do { + switch (token.type) { + case types.RightCurlyBracket: + case types.RightParenthesis: + case types.RightSquareBracket: + if (token.type !== balanceCloseType) { + break scan; + } + + balanceCloseType = balanceStash.pop(); + + if (balanceStash.length === 0) { + length++; + break scan; + } + + break; + + case types.Function: + case types.LeftParenthesis: + case types.LeftSquareBracket: + case types.LeftCurlyBracket: + balanceStash.push(balanceCloseType); + balanceCloseType = balancePair.get(token.type); + break; + } + + length++; + } while (token = getNextToken(length)); + + return length; +} + +// TODO: implement +// can be used wherever , , ,