diff --git a/flow/compiler.js b/flow/compiler.js index a3dc1c920fd..5c4edeb48c6 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -7,6 +7,8 @@ declare type CompilerOptions = { canBeLeftOpenTag?: (tag: string) => ?boolean; // check if a tag can be left opened isReservedTag?: (tag: string) => ?boolean; // check if a tag is a native for the platform preserveWhitespace?: boolean; // preserve whitespace between elements? + trimTextWhitespace?: boolean; // trim whitespaces from text nodes? + collapseTextWhitespace?: boolean; // collapse multiple whitespaces into one within text nodes? optimize?: boolean; // optimize static content? // web specific diff --git a/src/compiler/parser/index.js b/src/compiler/parser/index.js index ba1b726870a..0970f4d6cb0 100644 --- a/src/compiler/parser/index.js +++ b/src/compiler/parser/index.js @@ -78,13 +78,16 @@ export function parse ( delimiters = options.delimiters const stack = [] - const preserveWhitespace = options.preserveWhitespace !== false let root let currentParent let inVPre = false let inPre = false let warned = false + const preserveWhitespace = options.preserveWhitespace !== false + const trimTextWhitespace = options.trimTextWhitespace === true + const collapseTextWhitespace = options.collapseTextWhitespace === true + function warnOnce (msg) { if (!warned) { warned = true @@ -258,10 +261,27 @@ export function parse ( return } const children = currentParent.children - text = inPre || text.trim() - ? isTextTag(currentParent) ? text : decodeHTMLCached(text) - // only preserve whitespace if its not right after a starting tag - : preserveWhitespace && children.length ? ' ' : '' + if (inPre || text.trim()) { + text = isTextTag(currentParent) ? text : decodeHTMLCached(text) + } else { + text = '' + } + // disable text optimizations within pre-elements + if (!inPre) { + if (trimTextWhitespace) { + text = text.trim() + } + if (collapseTextWhitespace) { + // replace spaces around newlines with just the newline + text = text.replace(/\s*\n\s*/g, '\n') + // collapse more than one sequential whitespace into one space + text = text.replace(/\s{2,}/g, ' ') + } + } + // only preserve whitespace if its not right after a starting tag + if (text === '' && preserveWhitespace && children.length) { + text = ' ' + } if (text) { let res if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) { diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js index 750e371105f..b859bfd9b36 100644 --- a/test/unit/modules/compiler/parser.spec.js +++ b/test/unit/modules/compiler/parser.spec.js @@ -717,4 +717,19 @@ describe('parser', () => { expect(ast.children[1].isComment).toBe(true) // parse comment with ASTText expect(ast.children[1].text).toBe('comment here') }) + + it('trims and collapses whitespaces in text nodes when configured to do so', () => { + const html = `\t
\n\t\t\t Test 2\n\t\t\t Test \t \t 3 \n\t\t
\n\t