diff --git a/packages/compiler-core/src/parse.ts b/packages/compiler-core/src/parse.ts index d48f93c189a..a2f22193eb8 100644 --- a/packages/compiler-core/src/parse.ts +++ b/packages/compiler-core/src/parse.ts @@ -96,8 +96,8 @@ export interface ParserContext { offset: number line: number column: number - inPre: boolean // HTML
tag, preserve whitespaces - inVPre: boolean // v-pre, do not process directives and interpolations + inPre: number // HTMLtag, preserve whitespaces + inVPre: number // v-pre, do not process directives and interpolations onWarn: NonNullable} @@ -134,8 +134,8 @@ function createParserContext( offset: 0, originalSource: content, source: content, - inPre: false, - inVPre: false, + inPre: 0, + inVPre: 0, onWarn: options.onWarn } } @@ -254,7 +254,7 @@ function parseChildren( // Whitespace handling strategy like v2 let removedWhitespace = false if (mode !== TextModes.RAWTEXT && mode !== TextModes.RCDATA) { - const preserve = context.options.whitespace === 'preserve' + const shouldCondense = context.options.whitespace !== 'preserve' for (let i = 0; i < nodes.length; i++) { const node = nodes[i] if (!context.inPre && node.type === NodeTypes.TEXT) { @@ -268,7 +268,7 @@ function parseChildren( if ( !prev || !next || - (!preserve && + (shouldCondense && (prev.type === NodeTypes.COMMENT || next.type === NodeTypes.COMMENT || (prev.type === NodeTypes.ELEMENT && @@ -281,7 +281,7 @@ function parseChildren( // Otherwise, the whitespace is condensed into a single space node.content = ' ' } - } else if (!preserve) { + } else if (shouldCondense) { // in condense mode, consecutive whitespaces in text are condensed // down to a single space. node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ') @@ -428,7 +428,7 @@ function parseElement( if (element.isSelfClosing || context.options.isVoidTag(element.tag)) { // #4030 self-closing tag if (context.options.isPreTag(element.tag)) { - context.inPre = false + context.inPre-- } return element } @@ -479,10 +479,10 @@ function parseElement( element.loc = getSelection(context, element.loc.start) if (isPreBoundary) { - context.inPre = false + context.inPre-- } if (isVPreBoundary) { - context.inVPre = false + context.inVPre-- } return element } @@ -534,9 +534,8 @@ function parseTag( const currentSource = context.source // checktag - const isPreTag = context.options.isPreTag(tag) - if (isPreTag) { - context.inPre = true + if (context.options.isPreTag(tag)) { + context.inPre++ } // Attributes. @@ -548,7 +547,7 @@ function parseTag( !context.inVPre && props.some(p => p.type === NodeTypes.DIRECTIVE && p.name === 'pre') ) { - context.inVPre = true + context.inVPre++ // reset context extend(context, cursor) context.source = currentSource diff --git a/packages/compiler-sfc/__tests__/parse.spec.ts b/packages/compiler-sfc/__tests__/parse.spec.ts index 470bfb9d0ba..8d1cad1a9c8 100644 --- a/packages/compiler-sfc/__tests__/parse.spec.ts +++ b/packages/compiler-sfc/__tests__/parse.spec.ts @@ -111,6 +111,22 @@ h1 { color: red } ) }) + test('should parse correct range for root level self closing tag', () => { + const content = `\n \n` + const { descriptor } = parse(`${content}`) + expect(descriptor.template).toBeTruthy() + expect(descriptor.template!.content).toBe(content) + expect(descriptor.template!.loc).toMatchObject({ + start: { line: 1, column: 11, offset: 10 }, + end: { + line: 3, + column: 1, + offset: 10 + content.length + }, + source: content + }) + }) + test('should parse correct range for blocks with no content (self closing)', () => { const { descriptor } = parse(``) expect(descriptor.template).toBeTruthy()