feat(compiler): preserve whitespace in pre tag, add tests
This commit is contained in:
		
							parent
							
								
									9298f46f92
								
							
						
					
					
						commit
						eb20730a67
					
				| @ -1600,6 +1600,55 @@ foo | ||||
|     }) | ||||
|   }) | ||||
| 
 | ||||
|   describe('whitespace management', () => { | ||||
|     it('should remove whitespaces at start/end inside an element', () => { | ||||
|       const ast = parse(`<div>   <span/>    </div>`) | ||||
|       expect((ast.children[0] as ElementNode).children.length).toBe(1) | ||||
|     }) | ||||
| 
 | ||||
|     it('should remove whitespaces w/ newline between elements', () => { | ||||
|       const ast = parse(`<div/> \n <div/> \n <div/>`) | ||||
|       expect(ast.children.length).toBe(3) | ||||
|       expect(ast.children.every(c => c.type === NodeTypes.ELEMENT)).toBe(true) | ||||
|     }) | ||||
| 
 | ||||
|     it('should remove whitespaces w/ newline between comments and elements', () => { | ||||
|       const ast = parse(`<div/> \n <!--foo--> \n <div/>`) | ||||
|       expect(ast.children.length).toBe(3) | ||||
|       expect(ast.children[0].type).toBe(NodeTypes.ELEMENT) | ||||
|       expect(ast.children[1].type).toBe(NodeTypes.COMMENT) | ||||
|       expect(ast.children[2].type).toBe(NodeTypes.ELEMENT) | ||||
|     }) | ||||
| 
 | ||||
|     it('should NOT remove whitespaces w/ newline between interpolations', () => { | ||||
|       const ast = parse(`{{ foo }} \n {{ bar }}`) | ||||
|       expect(ast.children.length).toBe(3) | ||||
|       expect(ast.children[0].type).toBe(NodeTypes.INTERPOLATION) | ||||
|       expect(ast.children[1]).toMatchObject({ | ||||
|         type: NodeTypes.TEXT, | ||||
|         content: ' ' | ||||
|       }) | ||||
|       expect(ast.children[2].type).toBe(NodeTypes.INTERPOLATION) | ||||
|     }) | ||||
| 
 | ||||
|     it('should NOT remove whitespaces w/o newline between elements', () => { | ||||
|       const ast = parse(`<div/> <div/> <div/>`) | ||||
|       expect(ast.children.length).toBe(5) | ||||
|       expect(ast.children.map(c => c.type)).toMatchObject([ | ||||
|         NodeTypes.ELEMENT, | ||||
|         NodeTypes.TEXT, | ||||
|         NodeTypes.ELEMENT, | ||||
|         NodeTypes.TEXT, | ||||
|         NodeTypes.ELEMENT | ||||
|       ]) | ||||
|     }) | ||||
| 
 | ||||
|     it('should condense consecutive whitespaces in text', () => { | ||||
|       const ast = parse(`   foo  \n    bar     baz     `) | ||||
|       expect((ast.children[0] as TextNode).content).toBe(` foo bar baz `) | ||||
|     }) | ||||
|   }) | ||||
| 
 | ||||
|   describe('Errors', () => { | ||||
|     const patterns: { | ||||
|       [key: string]: Array<{ | ||||
|  | ||||
| @ -32,6 +32,7 @@ import { extend } from '@vue/shared' | ||||
| export interface ParserOptions { | ||||
|   isVoidTag?: (tag: string) => boolean // e.g. img, br, hr
 | ||||
|   isNativeTag?: (tag: string) => boolean // e.g. loading-indicator in weex
 | ||||
|   isPreTag?: (tag: string) => boolean // e.g. <pre> where whitespace is intact
 | ||||
|   isCustomElement?: (tag: string) => boolean | ||||
|   getNamespace?: (tag: string, parent: ElementNode | undefined) => Namespace | ||||
|   getTextMode?: (tag: string, ns: Namespace) => TextModes | ||||
| @ -53,6 +54,7 @@ export const defaultParserOptions: MergedParserOptions = { | ||||
|   getNamespace: () => Namespaces.HTML, | ||||
|   getTextMode: () => TextModes.DATA, | ||||
|   isVoidTag: NO, | ||||
|   isPreTag: NO, | ||||
|   isCustomElement: NO, | ||||
|   namedCharacterReferences: { | ||||
|     'gt;': '>', | ||||
| @ -207,6 +209,7 @@ function parseChildren( | ||||
|   // Whitespace management for more efficient output
 | ||||
|   // (same as v2 whitespance: 'condense')
 | ||||
|   let removedWhitespace = false | ||||
|   if (!parent || !context.options.isPreTag(parent.tag)) { | ||||
|     for (let i = 0; i < nodes.length; i++) { | ||||
|       const node = nodes[i] | ||||
|       if (node.type === NodeTypes.TEXT) { | ||||
| @ -238,6 +241,7 @@ function parseChildren( | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return removedWhitespace ? nodes.filter(node => node !== null) : nodes | ||||
| } | ||||
|  | ||||
| @ -98,6 +98,15 @@ describe('DOM parser', () => { | ||||
|         } | ||||
|       }) | ||||
|     }) | ||||
| 
 | ||||
|     test('<pre> tag should preserve raw whitespace', () => { | ||||
|       const rawText = `  \na    b    \n   c` | ||||
|       const ast = parse(`<pre>${rawText}</pre>`, parserOptions) | ||||
|       expect((ast.children[0] as ElementNode).children[0]).toMatchObject({ | ||||
|         type: NodeTypes.TEXT, | ||||
|         content: rawText | ||||
|       }) | ||||
|     }) | ||||
|   }) | ||||
| 
 | ||||
|   describe('Interpolation', () => { | ||||
|  | ||||
| @ -15,8 +15,8 @@ export const enum DOMNamespaces { | ||||
| 
 | ||||
| export const parserOptionsMinimal: ParserOptions = { | ||||
|   isVoidTag, | ||||
| 
 | ||||
|   isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag), | ||||
|   isPreTag: tag => tag === 'pre', | ||||
| 
 | ||||
|   // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher
 | ||||
|   getNamespace(tag: string, parent: ElementNode | undefined): DOMNamespaces { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user