fix(compiler-sfc): fix whitespace preservation when block contains single self-closing tag
This commit is contained in:
parent
47f488350c
commit
ec6abe8d5e
@ -96,8 +96,8 @@ export interface ParserContext {
|
|||||||
offset: number
|
offset: number
|
||||||
line: number
|
line: number
|
||||||
column: number
|
column: number
|
||||||
inPre: boolean // HTML <pre> tag, preserve whitespaces
|
inPre: number // HTML <pre> tag, preserve whitespaces
|
||||||
inVPre: boolean // v-pre, do not process directives and interpolations
|
inVPre: number // v-pre, do not process directives and interpolations
|
||||||
onWarn: NonNullable<ErrorHandlingOptions['onWarn']>
|
onWarn: NonNullable<ErrorHandlingOptions['onWarn']>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,8 +134,8 @@ function createParserContext(
|
|||||||
offset: 0,
|
offset: 0,
|
||||||
originalSource: content,
|
originalSource: content,
|
||||||
source: content,
|
source: content,
|
||||||
inPre: false,
|
inPre: 0,
|
||||||
inVPre: false,
|
inVPre: 0,
|
||||||
onWarn: options.onWarn
|
onWarn: options.onWarn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +254,7 @@ function parseChildren(
|
|||||||
// Whitespace handling strategy like v2
|
// Whitespace handling strategy like v2
|
||||||
let removedWhitespace = false
|
let removedWhitespace = false
|
||||||
if (mode !== TextModes.RAWTEXT && mode !== TextModes.RCDATA) {
|
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++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
const node = nodes[i]
|
const node = nodes[i]
|
||||||
if (!context.inPre && node.type === NodeTypes.TEXT) {
|
if (!context.inPre && node.type === NodeTypes.TEXT) {
|
||||||
@ -268,7 +268,7 @@ function parseChildren(
|
|||||||
if (
|
if (
|
||||||
!prev ||
|
!prev ||
|
||||||
!next ||
|
!next ||
|
||||||
(!preserve &&
|
(shouldCondense &&
|
||||||
(prev.type === NodeTypes.COMMENT ||
|
(prev.type === NodeTypes.COMMENT ||
|
||||||
next.type === NodeTypes.COMMENT ||
|
next.type === NodeTypes.COMMENT ||
|
||||||
(prev.type === NodeTypes.ELEMENT &&
|
(prev.type === NodeTypes.ELEMENT &&
|
||||||
@ -281,7 +281,7 @@ function parseChildren(
|
|||||||
// Otherwise, the whitespace is condensed into a single space
|
// Otherwise, the whitespace is condensed into a single space
|
||||||
node.content = ' '
|
node.content = ' '
|
||||||
}
|
}
|
||||||
} else if (!preserve) {
|
} else if (shouldCondense) {
|
||||||
// in condense mode, consecutive whitespaces in text are condensed
|
// in condense mode, consecutive whitespaces in text are condensed
|
||||||
// down to a single space.
|
// down to a single space.
|
||||||
node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ')
|
node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ')
|
||||||
@ -428,7 +428,7 @@ function parseElement(
|
|||||||
if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
|
if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
|
||||||
// #4030 self-closing <pre> tag
|
// #4030 self-closing <pre> tag
|
||||||
if (context.options.isPreTag(element.tag)) {
|
if (context.options.isPreTag(element.tag)) {
|
||||||
context.inPre = false
|
context.inPre--
|
||||||
}
|
}
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
@ -479,10 +479,10 @@ function parseElement(
|
|||||||
element.loc = getSelection(context, element.loc.start)
|
element.loc = getSelection(context, element.loc.start)
|
||||||
|
|
||||||
if (isPreBoundary) {
|
if (isPreBoundary) {
|
||||||
context.inPre = false
|
context.inPre--
|
||||||
}
|
}
|
||||||
if (isVPreBoundary) {
|
if (isVPreBoundary) {
|
||||||
context.inVPre = false
|
context.inVPre--
|
||||||
}
|
}
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
@ -534,9 +534,8 @@ function parseTag(
|
|||||||
const currentSource = context.source
|
const currentSource = context.source
|
||||||
|
|
||||||
// check <pre> tag
|
// check <pre> tag
|
||||||
const isPreTag = context.options.isPreTag(tag)
|
if (context.options.isPreTag(tag)) {
|
||||||
if (isPreTag) {
|
context.inPre++
|
||||||
context.inPre = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attributes.
|
// Attributes.
|
||||||
@ -548,7 +547,7 @@ function parseTag(
|
|||||||
!context.inVPre &&
|
!context.inVPre &&
|
||||||
props.some(p => p.type === NodeTypes.DIRECTIVE && p.name === 'pre')
|
props.some(p => p.type === NodeTypes.DIRECTIVE && p.name === 'pre')
|
||||||
) {
|
) {
|
||||||
context.inVPre = true
|
context.inVPre++
|
||||||
// reset context
|
// reset context
|
||||||
extend(context, cursor)
|
extend(context, cursor)
|
||||||
context.source = currentSource
|
context.source = currentSource
|
||||||
|
@ -111,6 +111,22 @@ h1 { color: red }
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should parse correct range for root level self closing tag', () => {
|
||||||
|
const content = `\n <div/>\n`
|
||||||
|
const { descriptor } = parse(`<template>${content}</template>`)
|
||||||
|
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)', () => {
|
test('should parse correct range for blocks with no content (self closing)', () => {
|
||||||
const { descriptor } = parse(`<template/>`)
|
const { descriptor } = parse(`<template/>`)
|
||||||
expect(descriptor.template).toBeTruthy()
|
expect(descriptor.template).toBeTruthy()
|
||||||
|
Loading…
Reference in New Issue
Block a user