]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(compiler): improve whitespace: 'preserve' behavior from #1600
authorEvan You <yyx990803@gmail.com>
Mon, 26 Apr 2021 14:49:21 +0000 (10:49 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 26 Apr 2021 15:46:17 +0000 (11:46 -0400)
- discard leading/ending whitespace inside an element
- condense preserved whitesapce into single space

packages/compiler-core/__tests__/parse.spec.ts
packages/compiler-core/src/parse.ts

index e0608fde46580211ba8e48692e7cef9b71948f97..1c7c878539abde49133f5d7f5a0adf394771a8ae 100644 (file)
@@ -1837,9 +1837,9 @@ foo
         ...options
       })
 
-    it('should preserve whitespaces at start/end inside an element', () => {
+    it('should still remove whitespaces at start/end inside an element', () => {
       const ast = parse(`<div>   <span/>    </div>`)
-      expect((ast.children[0] as ElementNode).children.length).toBe(3)
+      expect((ast.children[0] as ElementNode).children.length).toBe(1)
     })
 
     it('should preserve whitespaces w/ newline between elements', () => {
@@ -1884,7 +1884,7 @@ foo
       expect(ast.children[0].type).toBe(NodeTypes.INTERPOLATION)
       expect(ast.children[1]).toMatchObject({
         type: NodeTypes.TEXT,
-        content: ' \n '
+        content: ' '
       })
       expect(ast.children[2].type).toBe(NodeTypes.INTERPOLATION)
     })
index cb5f6183112f7aa47d00babaa18d0d1a0028263b..784d85fb455e22c90f76603801657bf43ea73f89 100644 (file)
@@ -38,6 +38,7 @@ import {
 } from './compat/compatConfig'
 
 type OptionalOptions =
+  | 'whitespace'
   | 'isNativeTag'
   | 'isBuiltInComponent'
   | keyof CompilerCompatOptions
@@ -65,7 +66,6 @@ const decodeMap: Record<string, string> = {
 
 export const defaultParserOptions: MergedParserOptions = {
   delimiters: [`{{`, `}}`],
-  whitespace: 'condense',
   getNamespace: () => Namespaces.HTML,
   getTextMode: () => TextModes.DATA,
   isVoidTag: NO,
@@ -222,35 +222,37 @@ function parseChildren(
 
   // Whitespace handling strategy like v2
   let removedWhitespace = false
-  if (context.options.whitespace === 'condense' && mode !== TextModes.RAWTEXT && mode !== TextModes.RCDATA) {
+  if (mode !== TextModes.RAWTEXT && mode !== TextModes.RCDATA) {
+    const preserve = context.options.whitespace === 'preserve'
     for (let i = 0; i < nodes.length; i++) {
       const node = nodes[i]
       if (!context.inPre && node.type === NodeTypes.TEXT) {
         if (!/[^\t\r\n\f ]/.test(node.content)) {
           const prev = nodes[i - 1]
           const next = nodes[i + 1]
-          // If:
+          // Remove if:
           // - the whitespace is the first or last node, or:
-          // - the whitespace is adjacent to a comment, or:
-          // - the whitespace is between two elements AND contains newline
-          // Then the whitespace is ignored.
+          // - (condense mode) the whitespace is adjacent to a comment, or:
+          // - (condense mode) the whitespace is between two elements AND contains newline
           if (
             !prev ||
             !next ||
-            prev.type === NodeTypes.COMMENT ||
-            next.type === NodeTypes.COMMENT ||
-            (prev.type === NodeTypes.ELEMENT &&
-              next.type === NodeTypes.ELEMENT &&
-              /[\r\n]/.test(node.content))
+            (!preserve &&
+              (prev.type === NodeTypes.COMMENT ||
+                next.type === NodeTypes.COMMENT ||
+                (prev.type === NodeTypes.ELEMENT &&
+                  next.type === NodeTypes.ELEMENT &&
+                  /[\r\n]/.test(node.content))))
           ) {
             removedWhitespace = true
             nodes[i] = null as any
           } else {
-            // Otherwise, condensed consecutive whitespace inside the text
-            // down to a single space
+            // Otherwise, the whitespace is condensed into a single space
             node.content = ' '
           }
-        } else {
+        } else if (!preserve) {
+          // in condense mode, consecutive whitespaces in text are condensed
+          // down to a single space.
           node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ')
         }
       }