diff --git a/src/generators/dom/preprocess.ts b/src/generators/dom/preprocess.ts index dc3ff59717..2fab6d45d6 100644 --- a/src/generators/dom/preprocess.ts +++ b/src/generators/dom/preprocess.ts @@ -34,7 +34,8 @@ const preprocessors = { generator: DomGenerator, block: Block, state: State, - node: Node + node: Node, + stripWhitespace: boolean ) => { const dependencies = block.findDependencies(node.expression); block.addDependencies(dependencies); @@ -48,7 +49,8 @@ const preprocessors = { generator: DomGenerator, block: Block, state: State, - node: Node + node: Node, + stripWhitespace: boolean ) => { const dependencies = block.findDependencies(node.expression); block.addDependencies(dependencies); @@ -59,7 +61,7 @@ const preprocessors = { node._state = getChildState(state, { basename, name }); }, - Text: (generator: DomGenerator, block: Block, state: State, node: Node) => { + Text: (generator: DomGenerator, block: Block, state: State, node: Node, stripWhitespace: boolean) => { node._state = getChildState(state); if (!/\S/.test(node.data)) { @@ -75,7 +77,8 @@ const preprocessors = { generator: DomGenerator, block: Block, state: State, - node: Node + node: Node, + stripWhitespace: boolean ) => { const blocks: Block[] = []; let dynamic = false; @@ -93,7 +96,7 @@ const preprocessors = { node._state = getChildState(state); blocks.push(node._block); - preprocessChildren(generator, node._block, node._state, node); + preprocessChildren(generator, node._block, node._state, node, stripWhitespace); if (node._block.dependencies.size > 0) { dynamic = true; @@ -117,7 +120,8 @@ const preprocessors = { generator, node.else._block, node.else._state, - node.else + node.else, + stripWhitespace ); if (node.else._block.dependencies.size > 0) { @@ -142,7 +146,8 @@ const preprocessors = { generator: DomGenerator, block: Block, state: State, - node: Node + node: Node, + stripWhitespace: boolean ) => { const dependencies = block.findDependencies(node.expression); block.addDependencies(dependencies); @@ -189,7 +194,7 @@ const preprocessors = { }); generator.blocks.push(node._block); - preprocessChildren(generator, node._block, node._state, node); + preprocessChildren(generator, node._block, node._state, node, stripWhitespace); block.addDependencies(node._block.dependencies); node._block.hasUpdateMethod = node._block.dependencies.size > 0; @@ -205,7 +210,8 @@ const preprocessors = { generator, node.else._block, node.else._state, - node.else + node.else, + stripWhitespace ); node.else._block.hasUpdateMethod = node.else._block.dependencies.size > 0; } @@ -215,7 +221,8 @@ const preprocessors = { generator: DomGenerator, block: Block, state: State, - node: Node + node: Node, + stripWhitespace: boolean ) => { node.attributes.forEach((attribute: Node) => { if (attribute.type === 'Attribute' && attribute.value !== true) { @@ -305,11 +312,12 @@ const preprocessors = { }); generator.blocks.push(node._block); - preprocessChildren(generator, node._block, node._state, node); + preprocessChildren(generator, node._block, node._state, node, stripWhitespace); block.addDependencies(node._block.dependencies); node._block.hasUpdateMethod = node._block.dependencies.size > 0; } else { - preprocessChildren(generator, block, node._state, node); + if (node.name === 'pre' || node.name === 'textarea') stripWhitespace = false; + preprocessChildren(generator, block, node._state, node, stripWhitespace); } } }, @@ -320,7 +328,7 @@ function preprocessChildren( block: Block, state: State, node: Node, - isTopLevel: boolean = false + stripWhitespace: boolean ) { // glue text nodes together const cleaned: Node[] = []; @@ -333,32 +341,22 @@ function preprocessChildren( lastChild.data += child.data; lastChild.end = child.end; } else { - cleaned.push(child); + if (child.type === 'Text' && stripWhitespace && cleaned.length === 0) { + child.data = trimStart(child.data); + if (child.data) cleaned.push(child); + } else { + cleaned.push(child); + } } lastChild = child; }); - if (isTopLevel) { - // trim leading and trailing whitespace from the top level - const firstChild = cleaned[0]; - if (firstChild && firstChild.type === 'Text') { - firstChild.data = trimStart(firstChild.data); - if (!firstChild.data) cleaned.shift(); - } - - const lastChild = cleaned[cleaned.length - 1]; - if (lastChild && lastChild.type === 'Text') { - lastChild.data = trimEnd(lastChild.data); - if (!lastChild.data) cleaned.pop(); - } - } - lastChild = null; cleaned.forEach((child: Node) => { - const preprocess = preprocessors[child.type]; - if (preprocess) preprocess(generator, block, state, child); + const preprocessor = preprocessors[child.type]; + if (preprocessor) preprocessor(generator, block, state, child, stripWhitespace); if (lastChild) { lastChild.next = child; @@ -368,6 +366,17 @@ function preprocessChildren( lastChild = child; }); + if (lastChild) { + if (stripWhitespace && lastChild.type === 'Text') { + lastChild.data = trimEnd(lastChild.data); + if (!lastChild.data) { + cleaned.pop(); + lastChild = cleaned[cleaned.length - 1]; + lastChild.next = null; + } + } + } + if (lastChild) { lastChild.needsAnchor = !state.parentNode; } diff --git a/src/generators/server-side-rendering/index.ts b/src/generators/server-side-rendering/index.ts index 549a111f61..7b48c8f764 100644 --- a/src/generators/server-side-rendering/index.ts +++ b/src/generators/server-side-rendering/index.ts @@ -117,7 +117,7 @@ export default function ssr( } `} - return \`${generator.renderCode}\`; + return \`${generator.renderCode}\`.trim(); }; ${name}.renderCss = function () { diff --git a/src/parse/index.ts b/src/parse/index.ts index 9962e38209..f50da4b911 100644 --- a/src/parse/index.ts +++ b/src/parse/index.ts @@ -4,6 +4,7 @@ import { whitespace } from '../utils/patterns'; import { trimStart, trimEnd } from '../utils/trim'; import getCodeFrame from '../utils/getCodeFrame'; import hash from './utils/hash'; +import stripWhitespace from './utils/stripWhitespace'; import { Node, Parsed } from '../interfaces'; import CompileError from '../utils/CompileError'; @@ -77,39 +78,9 @@ export class Parser { } // trim unnecessary whitespace - while (this.html.children.length) { - const firstChild = this.html.children[0]; - this.html.start = firstChild.start; - - if (firstChild.type !== 'Text') break; - - const length = firstChild.data.length; - firstChild.data = trimStart(firstChild.data); - - if (firstChild.data === '') { - this.html.children.shift(); - } else { - this.html.start += length - firstChild.data.length; - break; - } - } - - while (this.html.children.length) { - const lastChild = this.html.children[this.html.children.length - 1]; - this.html.end = lastChild.end; - - if (lastChild.type !== 'Text') break; - - const length = lastChild.data.length; - lastChild.data = trimEnd(lastChild.data); - - if (lastChild.data === '') { - this.html.children.pop(); - } else { - this.html.end -= length - lastChild.data.length; - break; - } - } + // stripWhitespace(this.html.children); + // this.html.start = this.html.children[0] && this.html.children.start; + // this.html.end = this.html.children[this.html.children.length] && this.html.children[this.html.children.length].end; } current() { diff --git a/src/parse/state/tag.ts b/src/parse/state/tag.ts index b40e3ad3fa..6fee187dd9 100644 --- a/src/parse/state/tag.ts +++ b/src/parse/state/tag.ts @@ -62,23 +62,6 @@ const disallowedContents = new Map([ ['th', new Set(['td', 'th', 'tr'])], ]); -function stripWhitespace(element) { - if (element.children.length) { - const firstChild = element.children[0]; - const lastChild = element.children[element.children.length - 1]; - - if (firstChild.type === 'Text') { - firstChild.data = trimStart(firstChild.data); - if (!firstChild.data) element.children.shift(); - } - - if (lastChild.type === 'Text') { - lastChild.data = trimEnd(lastChild.data); - if (!lastChild.data) element.children.pop(); - } - } -} - export default function tag(parser: Parser) { const start = parser.index++; @@ -147,9 +130,6 @@ export default function tag(parser: Parser) { parent = parser.current(); } - // strip leading/trailing whitespace as necessary - stripWhitespace(parent); - parent.end = parser.index; parser.stack.pop(); @@ -158,8 +138,6 @@ export default function tag(parser: Parser) { // can this be a child of the parent element, or does it implicitly // close it, like `
foo: lol
+foo: lol
baz: 42 (number)
qux: this is a piece of string
-quux: core
quux: core
+foo: ''
foo: ''
+foo: bar
-baz: 42 (number)
foo: bar
+baz: 42 (number)
+Hello
Hello
+i am a widget
i am a widget
+