From f7abdd8e2c587c258a6fd54d620ed2dbefd20152 Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Sat, 22 Jan 2022 02:37:30 +0900 Subject: [PATCH 1/3] Support complex expression in CSS `v-bind()` --- .eslintrc.yml | 2 +- src/html/util/unicode.ts | 15 +- src/style/index.ts | 316 +-- src/style/tokenizer.ts | 335 +++ .../document-fragment.json | 2246 +++++++++++++++++ .../source.vue | 11 + .../token-ranges.json | 78 + .../tree.json | 181 ++ .../document-fragment.json | 1478 +++++++++++ .../source.vue | 9 + .../token-ranges.json | 64 + .../tree.json | 83 + 12 files changed, 4599 insertions(+), 219 deletions(-) create mode 100644 src/style/tokenizer.ts create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression01/document-fragment.json create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression01/source.vue create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression01/token-ranges.json create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression01/tree.json create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression02/document-fragment.json create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression02/source.vue create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression02/token-ranges.json create mode 100644 test/fixtures/document-fragment/style-variables-with-complex-expression02/tree.json diff --git a/.eslintrc.yml b/.eslintrc.yml index 8c0cd09c..9a375797 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -514,7 +514,7 @@ overrides: - error no-sequences: - error - no-shadow: + "@typescript-eslint/no-shadow": - error - builtinGlobals: true hoist: functions diff --git a/src/html/util/unicode.ts b/src/html/util/unicode.ts index a628ab7c..21fd900a 100644 --- a/src/html/util/unicode.ts +++ b/src/html/util/unicode.ts @@ -12,14 +12,18 @@ export const LINE_FEED = 0x0A export const FORM_FEED = 0x0C export const SPACE = 0x20 export const EXCLAMATION_MARK = 0x21 -export const QUOTATION_MARK = 0x22 +export const QUOTATION_MARK = 0x22 // " export const NUMBER_SIGN = 0x23 export const AMPERSAND = 0x26 -export const APOSTROPHE = 0x27 +export const APOSTROPHE = 0x27 // ' +export const LEFT_PARENTHESIS = 0x28 // ( +export const RIGHT_PARENTHESIS = 0x29 // ) +export const ASTERISK = 0x2A // * export const HYPHEN_MINUS = 0x2D -export const SOLIDUS = 0x2F +export const SOLIDUS = 0x2F // / export const DIGIT_0 = 0x30 export const DIGIT_9 = 0x39 +export const COLON = 0x3a export const SEMICOLON = 0x3B export const LESS_THAN_SIGN = 0x3C export const EQUALS_SIGN = 0x3D @@ -31,14 +35,15 @@ export const LATIN_CAPITAL_F = 0x46 export const LATIN_CAPITAL_X = 0x58 export const LATIN_CAPITAL_Z = 0x5A export const LEFT_SQUARE_BRACKET = 0x5B +export const REVERSE_SOLIDUS = 0x5C export const RIGHT_SQUARE_BRACKET = 0x5D export const GRAVE_ACCENT = 0x60 export const LATIN_SMALL_A = 0x61 export const LATIN_SMALL_F = 0x66 export const LATIN_SMALL_X = 0x78 export const LATIN_SMALL_Z = 0x7A -export const LEFT_CURLY_BRACKET = 0x7B -export const RIGHT_CURLY_BRACKET = 0x7D +export const LEFT_CURLY_BRACKET = 0x7B // { +export const RIGHT_CURLY_BRACKET = 0x7D // } export const NULL_REPLACEMENT = 0xFFFD /** diff --git a/src/style/index.ts b/src/style/index.ts index 33594963..e5739c99 100644 --- a/src/style/index.ts +++ b/src/style/index.ts @@ -21,8 +21,27 @@ import { import { parseExpression } from "../script" import { DEFAULT_ECMA_VERSION } from "../script-setup/parser-options" import { resolveReferences } from "../template" +import type { + CSSCommentToken, + CSSParseOption, + CSSPunctuatorToken, + CSSToken, +} from "./tokenizer" +import { CSSTokenType, CSSTokenizer } from "./tokenizer" -type CSSParseOption = { inlineComment?: boolean } +class CSSTokenScanner { + private reconsuming: CSSToken[] = [] + private tokenizer: CSSTokenizer + public constructor(text: string, parserOptions: CSSParseOption) { + this.tokenizer = new CSSTokenizer(text, 0, parserOptions) + } + public nextToken(): CSSToken | null { + return this.reconsuming.shift() || this.tokenizer.nextToken() + } + public reconsume(...tokens: CSSToken[]) { + this.reconsuming.push(...tokens) + } +} /** * Parse the source code of the given ` diff --git a/test/fixtures/document-fragment/style-variables-with-complex-expression01/token-ranges.json b/test/fixtures/document-fragment/style-variables-with-complex-expression01/token-ranges.json new file mode 100644 index 00000000..4f1de537 --- /dev/null +++ b/test/fixtures/document-fragment/style-variables-with-complex-expression01/token-ranges.json @@ -0,0 +1,78 @@ +[ + "", + "\n", + "div", + " ", + "{", + "\n ", + "color:", + " ", + "v-bind", + "(", + "(", + "a", + "+", + "b", + ")", + "/", + "2", + "+", + "'px'", + ")", + ";", + "\n", + "}", + "\n", + "div", + " ", + "{", + "\n ", + "color:", + " ", + "v-bind", + "(", + "(", + "a", + "+", + "b", + ")", + "/", + "2", + "+", + "'px'", + ")", + ";", + "\n", + "}", + "\n", + "p", + " ", + "{", + "\n ", + "color:", + " ", + "v-bind", + "(", + "(", + "(", + "a", + "+", + "b", + ")", + ")", + "/", + "(", + "2", + "*", + "a", + ")", + ")", + ";", + "\n", + "}", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/style-variables-with-complex-expression01/tree.json b/test/fixtures/document-fragment/style-variables-with-complex-expression01/tree.json new file mode 100644 index 00000000..26a7fef2 --- /dev/null +++ b/test/fixtures/document-fragment/style-variables-with-complex-expression01/tree.json @@ -0,0 +1,181 @@ +[ + { + "type": "VDocumentFragment", + "text": "\n", + "children": [ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/style-variables-with-complex-expression02/document-fragment.json b/test/fixtures/document-fragment/style-variables-with-complex-expression02/document-fragment.json new file mode 100644 index 00000000..dea299fb --- /dev/null +++ b/test/fixtures/document-fragment/style-variables-with-complex-expression02/document-fragment.json @@ -0,0 +1,1478 @@ +{ + "type": "VDocumentFragment", + "range": [ + 0, + 139 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 10, + "column": 0 + } + }, + "children": [ + { + "type": "VElement", + "range": [ + 0, + 138 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 9, + "column": 8 + } + }, + "name": "style", + "rawName": "style", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 0, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "selfClosing": false, + "attributes": [] + }, + "children": [ + { + "type": "VText", + "range": [ + 7, + 28 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "value": "\ndiv {\n width: calc(" + }, + { + "type": "VExpressionContainer", + "range": [ + 28, + 55 + ], + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 41 + } + }, + "expression": { + "type": "BinaryExpression", + "start": 35, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 21 + }, + "end": { + "line": 3, + "column": 39 + } + }, + "range": [ + 35, + 53 + ], + "left": { + "type": "BinaryExpression", + "start": 35, + "end": 46, + "loc": { + "start": { + "line": 3, + "column": 21 + }, + "end": { + "line": 3, + "column": 32 + } + }, + "range": [ + 35, + 46 + ], + "left": { + "type": "BinaryExpression", + "start": 36, + "end": 41, + "loc": { + "start": { + "line": 3, + "column": 22 + }, + "end": { + "line": 3, + "column": 27 + } + }, + "range": [ + 36, + 41 + ], + "left": { + "type": "Identifier", + "start": 36, + "end": 37, + "loc": { + "start": { + "line": 3, + "column": 22 + }, + "end": { + "line": 3, + "column": 23 + } + }, + "range": [ + 36, + 37 + ], + "name": "a" + }, + "operator": "+", + "right": { + "type": "Identifier", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 27 + } + }, + "range": [ + 40, + 41 + ], + "name": "b" + } + }, + "operator": "/", + "right": { + "type": "Literal", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 3, + "column": 31 + }, + "end": { + "line": 3, + "column": 32 + } + }, + "range": [ + 45, + 46 + ], + "value": 2, + "raw": "2" + } + }, + "operator": "+", + "right": { + "type": "Literal", + "start": 49, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 35 + }, + "end": { + "line": 3, + "column": 39 + } + }, + "range": [ + 49, + 53 + ], + "value": "px", + "raw": "'px'" + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 36, + "end": 37, + "loc": { + "start": { + "line": 3, + "column": 22 + }, + "end": { + "line": 3, + "column": 23 + } + }, + "range": [ + 36, + 37 + ], + "name": "a" + }, + "mode": "r" + }, + { + "id": { + "type": "Identifier", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 27 + } + }, + "range": [ + 40, + 41 + ], + "name": "b" + }, + "mode": "r" + } + ] + }, + { + "type": "VText", + "range": [ + 55, + 130 + ], + "loc": { + "start": { + "line": 3, + "column": 41 + }, + "end": { + "line": 9, + "column": 0 + } + }, + "value": " - 3px);\n}\np {\n /* missing close */\n width: v-bind(((a + b)) / (2 * a)\n}\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 130, + 138 + ], + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 8 + } + } + }, + "variables": [], + "style": true + }, + { + "type": "VText", + "range": [ + 138, + 139 + ], + "loc": { + "start": { + "line": 9, + "column": 8 + }, + "end": { + "line": 10, + "column": 0 + } + }, + "value": "\n" + } + ], + "tokens": [ + { + "type": "HTMLTagOpen", + "range": [ + 0, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "value": "style" + }, + { + "type": "HTMLTagClose", + "range": [ + 6, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 7, + 8 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 2, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 8, + 11 + ], + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 3 + } + }, + "value": "div" + }, + { + "type": "HTMLWhitespace", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 12, + 13 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + }, + "value": "{" + }, + { + "type": "HTMLWhitespace", + "range": [ + 13, + 16 + ], + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 3, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLRawText", + "range": [ + 16, + 22 + ], + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 8 + } + }, + "value": "width:" + }, + { + "type": "HTMLWhitespace", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 23, + 28 + ], + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "value": "calc(" + }, + { + "type": "HTMLRawText", + "range": [ + 28, + 34 + ], + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 20 + } + }, + "value": "v-bind" + }, + { + "type": "Punctuator", + "range": [ + 34, + 35 + ], + "loc": { + "start": { + "line": 3, + "column": 20 + }, + "end": { + "line": 3, + "column": 21 + } + }, + "value": "(" + }, + { + "type": "Punctuator", + "value": "(", + "start": 35, + "end": 36, + "loc": { + "start": { + "line": 3, + "column": 21 + }, + "end": { + "line": 3, + "column": 22 + } + }, + "range": [ + 35, + 36 + ] + }, + { + "type": "Identifier", + "value": "a", + "start": 36, + "end": 37, + "loc": { + "start": { + "line": 3, + "column": 22 + }, + "end": { + "line": 3, + "column": 23 + } + }, + "range": [ + 36, + 37 + ] + }, + { + "type": "Punctuator", + "value": "+", + "start": 38, + "end": 39, + "loc": { + "start": { + "line": 3, + "column": 24 + }, + "end": { + "line": 3, + "column": 25 + } + }, + "range": [ + 38, + 39 + ] + }, + { + "type": "Identifier", + "value": "b", + "start": 40, + "end": 41, + "loc": { + "start": { + "line": 3, + "column": 26 + }, + "end": { + "line": 3, + "column": 27 + } + }, + "range": [ + 40, + 41 + ] + }, + { + "type": "Punctuator", + "value": ")", + "start": 41, + "end": 42, + "loc": { + "start": { + "line": 3, + "column": 27 + }, + "end": { + "line": 3, + "column": 28 + } + }, + "range": [ + 41, + 42 + ] + }, + { + "type": "Punctuator", + "value": "/", + "start": 43, + "end": 44, + "loc": { + "start": { + "line": 3, + "column": 29 + }, + "end": { + "line": 3, + "column": 30 + } + }, + "range": [ + 43, + 44 + ] + }, + { + "type": "Numeric", + "value": "2", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 3, + "column": 31 + }, + "end": { + "line": 3, + "column": 32 + } + }, + "range": [ + 45, + 46 + ] + }, + { + "type": "Punctuator", + "value": "+", + "start": 47, + "end": 48, + "loc": { + "start": { + "line": 3, + "column": 33 + }, + "end": { + "line": 3, + "column": 34 + } + }, + "range": [ + 47, + 48 + ] + }, + { + "type": "String", + "value": "'px'", + "start": 49, + "end": 53, + "loc": { + "start": { + "line": 3, + "column": 35 + }, + "end": { + "line": 3, + "column": 39 + } + }, + "range": [ + 49, + 53 + ] + }, + { + "type": "Punctuator", + "range": [ + 54, + 55 + ], + "loc": { + "start": { + "line": 3, + "column": 40 + }, + "end": { + "line": 3, + "column": 41 + } + }, + "value": ")" + }, + { + "type": "HTMLWhitespace", + "range": [ + 55, + 56 + ], + "loc": { + "start": { + "line": 3, + "column": 41 + }, + "end": { + "line": 3, + "column": 42 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "line": 3, + "column": 42 + }, + "end": { + "line": 3, + "column": 43 + } + }, + "value": "-" + }, + { + "type": "HTMLWhitespace", + "range": [ + 57, + 58 + ], + "loc": { + "start": { + "line": 3, + "column": 43 + }, + "end": { + "line": 3, + "column": 44 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 58, + 63 + ], + "loc": { + "start": { + "line": 3, + "column": 44 + }, + "end": { + "line": 3, + "column": 49 + } + }, + "value": "3px);" + }, + { + "type": "HTMLWhitespace", + "range": [ + 63, + 64 + ], + "loc": { + "start": { + "line": 3, + "column": 49 + }, + "end": { + "line": 4, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 64, + 65 + ], + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 1 + } + }, + "value": "}" + }, + { + "type": "HTMLWhitespace", + "range": [ + 65, + 66 + ], + "loc": { + "start": { + "line": 4, + "column": 1 + }, + "end": { + "line": 5, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 66, + 67 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 1 + } + }, + "value": "p" + }, + { + "type": "HTMLWhitespace", + "range": [ + 67, + 68 + ], + "loc": { + "start": { + "line": 5, + "column": 1 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 68, + 69 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 5, + "column": 3 + } + }, + "value": "{" + }, + { + "type": "HTMLWhitespace", + "range": [ + 69, + 72 + ], + "loc": { + "start": { + "line": 5, + "column": 3 + }, + "end": { + "line": 6, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLRawText", + "range": [ + 72, + 74 + ], + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 4 + } + }, + "value": "/*" + }, + { + "type": "HTMLWhitespace", + "range": [ + 74, + 75 + ], + "loc": { + "start": { + "line": 6, + "column": 4 + }, + "end": { + "line": 6, + "column": 5 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 75, + 82 + ], + "loc": { + "start": { + "line": 6, + "column": 5 + }, + "end": { + "line": 6, + "column": 12 + } + }, + "value": "missing" + }, + { + "type": "HTMLWhitespace", + "range": [ + 82, + 83 + ], + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 13 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 83, + 88 + ], + "loc": { + "start": { + "line": 6, + "column": 13 + }, + "end": { + "line": 6, + "column": 18 + } + }, + "value": "close" + }, + { + "type": "HTMLWhitespace", + "range": [ + 88, + 89 + ], + "loc": { + "start": { + "line": 6, + "column": 18 + }, + "end": { + "line": 6, + "column": 19 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 89, + 91 + ], + "loc": { + "start": { + "line": 6, + "column": 19 + }, + "end": { + "line": 6, + "column": 21 + } + }, + "value": "*/" + }, + { + "type": "HTMLWhitespace", + "range": [ + 91, + 94 + ], + "loc": { + "start": { + "line": 6, + "column": 21 + }, + "end": { + "line": 7, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLRawText", + "range": [ + 94, + 100 + ], + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 8 + } + }, + "value": "width:" + }, + { + "type": "HTMLWhitespace", + "range": [ + 100, + 101 + ], + "loc": { + "start": { + "line": 7, + "column": 8 + }, + "end": { + "line": 7, + "column": 9 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 101, + 111 + ], + "loc": { + "start": { + "line": 7, + "column": 9 + }, + "end": { + "line": 7, + "column": 19 + } + }, + "value": "v-bind(((a" + }, + { + "type": "HTMLWhitespace", + "range": [ + 111, + 112 + ], + "loc": { + "start": { + "line": 7, + "column": 19 + }, + "end": { + "line": 7, + "column": 20 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 112, + 113 + ], + "loc": { + "start": { + "line": 7, + "column": 20 + }, + "end": { + "line": 7, + "column": 21 + } + }, + "value": "+" + }, + { + "type": "HTMLWhitespace", + "range": [ + 113, + 114 + ], + "loc": { + "start": { + "line": 7, + "column": 21 + }, + "end": { + "line": 7, + "column": 22 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 114, + 117 + ], + "loc": { + "start": { + "line": 7, + "column": 22 + }, + "end": { + "line": 7, + "column": 25 + } + }, + "value": "b))" + }, + { + "type": "HTMLWhitespace", + "range": [ + 117, + 118 + ], + "loc": { + "start": { + "line": 7, + "column": 25 + }, + "end": { + "line": 7, + "column": 26 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 118, + 119 + ], + "loc": { + "start": { + "line": 7, + "column": 26 + }, + "end": { + "line": 7, + "column": 27 + } + }, + "value": "/" + }, + { + "type": "HTMLWhitespace", + "range": [ + 119, + 120 + ], + "loc": { + "start": { + "line": 7, + "column": 27 + }, + "end": { + "line": 7, + "column": 28 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 120, + 122 + ], + "loc": { + "start": { + "line": 7, + "column": 28 + }, + "end": { + "line": 7, + "column": 30 + } + }, + "value": "(2" + }, + { + "type": "HTMLWhitespace", + "range": [ + 122, + 123 + ], + "loc": { + "start": { + "line": 7, + "column": 30 + }, + "end": { + "line": 7, + "column": 31 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 123, + 124 + ], + "loc": { + "start": { + "line": 7, + "column": 31 + }, + "end": { + "line": 7, + "column": 32 + } + }, + "value": "*" + }, + { + "type": "HTMLWhitespace", + "range": [ + 124, + 125 + ], + "loc": { + "start": { + "line": 7, + "column": 32 + }, + "end": { + "line": 7, + "column": 33 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 125, + 127 + ], + "loc": { + "start": { + "line": 7, + "column": 33 + }, + "end": { + "line": 7, + "column": 35 + } + }, + "value": "a)" + }, + { + "type": "HTMLWhitespace", + "range": [ + 127, + 128 + ], + "loc": { + "start": { + "line": 7, + "column": 35 + }, + "end": { + "line": 8, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 128, + 129 + ], + "loc": { + "start": { + "line": 8, + "column": 0 + }, + "end": { + "line": 8, + "column": 1 + } + }, + "value": "}" + }, + { + "type": "HTMLWhitespace", + "range": [ + 129, + 130 + ], + "loc": { + "start": { + "line": 8, + "column": 1 + }, + "end": { + "line": 9, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 130, + 137 + ], + "loc": { + "start": { + "line": 9, + "column": 0 + }, + "end": { + "line": 9, + "column": 7 + } + }, + "value": "style" + }, + { + "type": "HTMLTagClose", + "range": [ + 137, + 138 + ], + "loc": { + "start": { + "line": 9, + "column": 7 + }, + "end": { + "line": 9, + "column": 8 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 138, + 139 + ], + "loc": { + "start": { + "line": 9, + "column": 8 + }, + "end": { + "line": 10, + "column": 0 + } + }, + "value": "\n" + } + ], + "comments": [], + "errors": [] +} \ No newline at end of file diff --git a/test/fixtures/document-fragment/style-variables-with-complex-expression02/source.vue b/test/fixtures/document-fragment/style-variables-with-complex-expression02/source.vue new file mode 100644 index 00000000..2803c288 --- /dev/null +++ b/test/fixtures/document-fragment/style-variables-with-complex-expression02/source.vue @@ -0,0 +1,9 @@ + diff --git a/test/fixtures/document-fragment/style-variables-with-complex-expression02/token-ranges.json b/test/fixtures/document-fragment/style-variables-with-complex-expression02/token-ranges.json new file mode 100644 index 00000000..ff7beaf3 --- /dev/null +++ b/test/fixtures/document-fragment/style-variables-with-complex-expression02/token-ranges.json @@ -0,0 +1,64 @@ +[ + "", + "\n", + "div", + " ", + "{", + "\n ", + "width:", + " ", + "calc(", + "v-bind", + "(", + "(", + "a", + "+", + "b", + ")", + "/", + "2", + "+", + "'px'", + ")", + " ", + "-", + " ", + "3px);", + "\n", + "}", + "\n", + "p", + " ", + "{", + "\n ", + "/*", + " ", + "missing", + " ", + "close", + " ", + "*/", + "\n ", + "width:", + " ", + "v-bind(((a", + " ", + "+", + " ", + "b))", + " ", + "/", + " ", + "(2", + " ", + "*", + " ", + "a)", + "\n", + "}", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/style-variables-with-complex-expression02/tree.json b/test/fixtures/document-fragment/style-variables-with-complex-expression02/tree.json new file mode 100644 index 00000000..2ecb302b --- /dev/null +++ b/test/fixtures/document-fragment/style-variables-with-complex-expression02/tree.json @@ -0,0 +1,83 @@ +[ + { + "type": "VDocumentFragment", + "text": "\n", + "children": [ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + } + ] + } +] \ No newline at end of file From 56607423c6fd6542f8d68793728a19845bc3396d Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Mon, 24 Jan 2022 11:59:45 +0900 Subject: [PATCH 2/3] fix --- src/style/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/style/index.ts b/src/style/index.ts index e5739c99..da81c040 100644 --- a/src/style/index.ts +++ b/src/style/index.ts @@ -23,17 +23,17 @@ import { DEFAULT_ECMA_VERSION } from "../script-setup/parser-options" import { resolveReferences } from "../template" import type { CSSCommentToken, - CSSParseOption, CSSPunctuatorToken, CSSToken, + CSSTokenizeOption, } from "./tokenizer" import { CSSTokenType, CSSTokenizer } from "./tokenizer" class CSSTokenScanner { private reconsuming: CSSToken[] = [] private tokenizer: CSSTokenizer - public constructor(text: string, parserOptions: CSSParseOption) { - this.tokenizer = new CSSTokenizer(text, 0, parserOptions) + public constructor(text: string, options: CSSTokenizeOption) { + this.tokenizer = new CSSTokenizer(text, 0, options) } public nextToken(): CSSToken | null { return this.reconsuming.shift() || this.tokenizer.nextToken() @@ -77,7 +77,7 @@ function parseStyleElement( style: VStyleElement, globalLocationCalculator: LocationCalculatorForHtml, parserOptions: ParserOptions, - cssOptions: CSSParseOption, + cssOptions: CSSTokenizeOption, ) { if (style.children.length !== 1) { return @@ -112,7 +112,7 @@ function parseStyle( code: string, locationCalculator: LocationCalculatorForHtml, parserOptions: ParserOptions, - cssOptions: CSSParseOption, + cssOptions: CSSTokenizeOption, ) { let textStart = 0 for (const { @@ -294,7 +294,7 @@ type VBindLocations = { */ function* iterateVBind( code: string, - cssOptions: CSSParseOption, + cssOptions: CSSTokenizeOption, ): IterableIterator { const tokenizer = new CSSTokenScanner(code, cssOptions) From 99eeaaa12e9526a3d1a2dcc5393125b2c7ba4b5b Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Mon, 24 Jan 2022 12:19:10 +0900 Subject: [PATCH 3/3] add comments --- src/html/util/unicode.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/html/util/unicode.ts b/src/html/util/unicode.ts index 21fd900a..3087de54 100644 --- a/src/html/util/unicode.ts +++ b/src/html/util/unicode.ts @@ -11,33 +11,33 @@ export const CARRIAGE_RETURN = 0x0D export const LINE_FEED = 0x0A export const FORM_FEED = 0x0C export const SPACE = 0x20 -export const EXCLAMATION_MARK = 0x21 +export const EXCLAMATION_MARK = 0x21 // ! export const QUOTATION_MARK = 0x22 // " -export const NUMBER_SIGN = 0x23 -export const AMPERSAND = 0x26 +export const NUMBER_SIGN = 0x23 // # +export const AMPERSAND = 0x26 // & export const APOSTROPHE = 0x27 // ' export const LEFT_PARENTHESIS = 0x28 // ( export const RIGHT_PARENTHESIS = 0x29 // ) export const ASTERISK = 0x2A // * -export const HYPHEN_MINUS = 0x2D +export const HYPHEN_MINUS = 0x2D // - export const SOLIDUS = 0x2F // / export const DIGIT_0 = 0x30 export const DIGIT_9 = 0x39 -export const COLON = 0x3a -export const SEMICOLON = 0x3B -export const LESS_THAN_SIGN = 0x3C -export const EQUALS_SIGN = 0x3D -export const GREATER_THAN_SIGN = 0x3E -export const QUESTION_MARK = 0x3F +export const COLON = 0x3a // : +export const SEMICOLON = 0x3B // ; +export const LESS_THAN_SIGN = 0x3C // < +export const EQUALS_SIGN = 0x3D // = +export const GREATER_THAN_SIGN = 0x3E // > +export const QUESTION_MARK = 0x3F // ? export const LATIN_CAPITAL_A = 0x41 export const LATIN_CAPITAL_D = 0x44 export const LATIN_CAPITAL_F = 0x46 export const LATIN_CAPITAL_X = 0x58 export const LATIN_CAPITAL_Z = 0x5A -export const LEFT_SQUARE_BRACKET = 0x5B -export const REVERSE_SOLIDUS = 0x5C -export const RIGHT_SQUARE_BRACKET = 0x5D -export const GRAVE_ACCENT = 0x60 +export const LEFT_SQUARE_BRACKET = 0x5B // [ +export const REVERSE_SOLIDUS = 0x5C // \ +export const RIGHT_SQUARE_BRACKET = 0x5D // ] +export const GRAVE_ACCENT = 0x60 // ` export const LATIN_SMALL_A = 0x61 export const LATIN_SMALL_F = 0x66 export const LATIN_SMALL_X = 0x78