"codegenNode": undefined,
"loc": {
"end": {
- "column": 13,
+ "column": 12,
"line": 1,
- "offset": 12,
+ "offset": 11,
},
"source": "<template><",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 14,
+ "column": 13,
"line": 1,
- "offset": 13,
+ "offset": 12,
},
"source": "<template></",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 26,
+ "column": 25,
"line": 1,
- "offset": 25,
+ "offset": 24,
},
"source": "<svg><![CDATA[",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 26,
+ "column": 25,
"line": 1,
- "offset": 25,
+ "offset": 24,
},
"source": "<template><svg><![CDATA[",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 31,
+ "column": 30,
"line": 1,
- "offset": 30,
+ "offset": 29,
},
"source": "<svg><![CDATA[cdata",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 31,
+ "column": 30,
"line": 1,
- "offset": 30,
+ "offset": 29,
},
"source": "<template><svg><![CDATA[cdata",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 16,
+ "column": 15,
"line": 1,
- "offset": 15,
+ "offset": 14,
},
"source": "<template><!--",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 23,
+ "column": 22,
"line": 1,
- "offset": 22,
+ "offset": 21,
},
"source": "<template><!--comment",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 12,
+ "column": 11,
"line": 1,
- "offset": 11,
+ "offset": 10,
},
"source": "<div></div",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 17,
+ "column": 16,
"line": 1,
- "offset": 16,
+ "offset": 15,
},
"source": "<template><div ",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 16,
+ "column": 15,
"line": 1,
- "offset": 15,
+ "offset": 14,
},
"source": "<template><div",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 20,
+ "column": 19,
"line": 1,
- "offset": 19,
+ "offset": 18,
},
"source": "<template><div id ",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 21,
+ "column": 20,
"line": 1,
- "offset": 20,
+ "offset": 19,
},
"source": "<template><div id =",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 19,
+ "column": 18,
"line": 1,
- "offset": 18,
+ "offset": 17,
},
"source": "<template><div id",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 24,
+ "column": 23,
"line": 1,
- "offset": 23,
+ "offset": 22,
},
"source": "<template><div id="abc",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 25,
+ "column": 24,
"line": 1,
- "offset": 24,
+ "offset": 23,
},
"source": "<template><div id="abc"",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 26,
+ "column": 25,
"line": 1,
- "offset": 25,
+ "offset": 24,
},
"source": "<template><div id="abc"/",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 24,
+ "column": 23,
"line": 1,
- "offset": 23,
+ "offset": 22,
},
"source": "<template><div id='abc",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 25,
+ "column": 24,
"line": 1,
- "offset": 24,
+ "offset": 23,
},
"source": "<template><div id='abc'",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 26,
+ "column": 25,
"line": 1,
- "offset": 25,
+ "offset": 24,
},
"source": "<template><div id='abc'/",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 25,
+ "column": 24,
"line": 1,
- "offset": 24,
+ "offset": 23,
},
"source": "<template><div id=abc /",
"start": {
"codegenNode": undefined,
"loc": {
"end": {
- "column": 23,
+ "column": 22,
"line": 1,
- "offset": 22,
+ "offset": 21,
},
"source": "<template><div id=abc",
"start": {
})
})
+ test('attribute value with >', () => {
+ const ast = baseParse(
+ '<script setup lang="ts" generic="T extends Record<string,string>"></script>',
+ { parseMode: 'sfc' }
+ )
+ const element = ast.children[0] as ElementNode
+ expect(element).toMatchObject({
+ type: NodeTypes.ELEMENT,
+ ns: Namespaces.HTML,
+ tag: 'script',
+ tagType: ElementTypes.ELEMENT,
+ codegenNode: undefined,
+ children: [],
+ innerLoc: {
+ start: { column: 67, line: 1, offset: 66 },
+ end: { column: 67, line: 1, offset: 66 }
+ },
+ props: [
+ {
+ loc: {
+ source: 'setup',
+ end: { column: 14, line: 1, offset: 13 },
+ start: { column: 9, line: 1, offset: 8 }
+ },
+ name: 'setup',
+ nameLoc: {
+ source: 'setup',
+ end: { column: 14, line: 1, offset: 13 },
+ start: { column: 9, line: 1, offset: 8 }
+ },
+ type: NodeTypes.ATTRIBUTE,
+ value: undefined
+ },
+ {
+ loc: {
+ source: 'lang="ts"',
+ end: { column: 24, line: 1, offset: 23 },
+ start: { column: 15, line: 1, offset: 14 }
+ },
+ name: 'lang',
+ nameLoc: {
+ source: 'lang',
+ end: { column: 19, line: 1, offset: 18 },
+ start: { column: 15, line: 1, offset: 14 }
+ },
+ type: NodeTypes.ATTRIBUTE,
+ value: {
+ content: 'ts',
+ loc: {
+ source: '"ts"',
+ end: { column: 24, line: 1, offset: 23 },
+ start: { column: 20, line: 1, offset: 19 }
+ },
+ type: NodeTypes.TEXT
+ }
+ },
+ {
+ loc: {
+ source: 'generic="T extends Record<string,string>"',
+ end: { column: 66, line: 1, offset: 65 },
+ start: { column: 25, line: 1, offset: 24 }
+ },
+ name: 'generic',
+ nameLoc: {
+ source: 'generic',
+ end: { column: 32, line: 1, offset: 31 },
+ start: { column: 25, line: 1, offset: 24 }
+ },
+ type: NodeTypes.ATTRIBUTE,
+ value: {
+ content: 'T extends Record<string,string>',
+ loc: {
+ source: '"T extends Record<string,string>"',
+ end: { column: 66, line: 1, offset: 65 },
+ start: { column: 33, line: 1, offset: 32 }
+ },
+ type: NodeTypes.TEXT
+ }
+ }
+ ]
+ })
+ })
+
test('multiple attributes', () => {
const ast = baseParse('<div id=a class="c" inert style=\'\'></div>')
const element = ast.children[0] as ElementNode
loc: getLoc(start - 1, end),
codegenNode: undefined
}
- if (tokenizer.inSFCRoot) {
- // in SFC mode, generate locations for root-level tags' inner content.
- currentOpenTag.innerLoc = getLoc(
- end + fastForward(end, CharCodes.Gt) + 1,
- end
- )
- }
},
onopentagend(end) {
}
function endOpenTag(end: number) {
+ if (tokenizer.inSFCRoot) {
+ // in SFC mode, generate locations for root-level tags' inner content.
+ currentOpenTag!.innerLoc = getLoc(end + 1, end + 1)
+ }
addNode(currentOpenTag!)
const { tag, ns } = currentOpenTag!
if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) {
// implied close, end should be backtracked to close
setLocEnd(el.loc, backTrack(end, CharCodes.Lt))
} else {
- setLocEnd(el.loc, end + fastForward(end, CharCodes.Gt) + 1)
+ setLocEnd(el.loc, end + 1)
}
if (tokenizer.inSFCRoot) {
}
}
-function fastForward(start: number, c: number) {
- let offset = 0
- while (
- currentInput.charCodeAt(start + offset) !== CharCodes.Gt &&
- start + offset < currentInput.length
- ) {
- offset++
- }
- return offset
-}
-
function backTrack(index: number, c: number) {
let i = index
while (currentInput.charCodeAt(i) !== c && i >= 0) i--
})"
`;
+exports[`SFC compile <script setup> > with TypeScript > with generic attribute 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+type Bar = {}
+
+export default /*#__PURE__*/_defineComponent({
+ setup(__props, { expose: __expose }) {
+ __expose();
+
+
+return { }
+}
+
+})"
+`;
+
exports[`SFC genDefaultAs > <script setup> only 1`] = `
"const a = 1
expect(content).toMatch(`return { get Baz() { return Baz } }`)
assertCode(content)
})
+
+ test('with generic attribute', () => {
+ const { content } = compile(`
+ <script setup lang="ts" generic="T extends Record<string,string>">
+ type Bar = {}
+ </script>`)
+ assertCode(content)
+ })
})
describe('async/await detection', () => {