diff --git a/packages/compiler-core/__tests__/parse.spec.ts b/packages/compiler-core/__tests__/parse.spec.ts index 4e5a9616511..15f211e7d9e 100644 --- a/packages/compiler-core/__tests__/parse.spec.ts +++ b/packages/compiler-core/__tests__/parse.spec.ts @@ -1264,6 +1264,17 @@ describe('compiler: parse', () => { }) }) + // #13361 + test('directive with multiline value', () => { + const ast = baseParse( + `
`, + ) + expect(ast.loc.end.line).toBe(4) + }) + test('directive with argument', () => { const ast = baseParse('
') const directive = (ast.children[0] as ElementNode).props[0] diff --git a/packages/compiler-core/src/tokenizer.ts b/packages/compiler-core/src/tokenizer.ts index 329e8b48181..041951f0b44 100644 --- a/packages/compiler-core/src/tokenizer.ts +++ b/packages/compiler-core/src/tokenizer.ts @@ -322,7 +322,7 @@ export default class Tokenizer { } this.state = State.BeforeTagName this.sectionStart = this.index - } else if (!__BROWSER__ && c === CharCodes.Amp) { + } else if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) { this.startEntity() } else if (!this.inVPre && c === this.delimiterOpen[0]) { this.state = State.InterpolationOpen @@ -436,7 +436,7 @@ export default class Tokenizer { (this.currentSequence === Sequences.TextareaEnd && !this.inSFCRoot) ) { // We have to parse entities in and <textarea> tags. - if (!__BROWSER__ && c === CharCodes.Amp) { + if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) { this.startEntity() } else if (!this.inVPre && c === this.delimiterOpen[0]) { // We also need to handle interpolation @@ -795,7 +795,7 @@ export default class Tokenizer { this.index + 1, ) this.state = State.BeforeAttrName - } else if (!__BROWSER__ && c === CharCodes.Amp) { + } else if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) { this.startEntity() } } @@ -823,7 +823,7 @@ export default class Tokenizer { ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE, this.index, ) - } else if (!__BROWSER__ && c === CharCodes.Amp) { + } else if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) { this.startEntity() } } @@ -1178,4 +1178,11 @@ export default class Tokenizer { } } } + + private isLogicalAnd(): boolean { + return ( + this.buffer.charCodeAt(this.index - 1) === CharCodes.Amp || + this.buffer.charCodeAt(this.index + 1) === CharCodes.Amp + ) + } }