Skip to content

Commit ef9cc17

Browse files
author
kingwl
committed
add comments option to allow user kept comments in template (vuejs#5392)
1 parent b5f08f3 commit ef9cc17

File tree

14 files changed

+107
-7
lines changed

14 files changed

+107
-7
lines changed

flow/compiler.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ declare type CompilerOptions = {
2121

2222
// runtime user-configurable
2323
delimiters?: [string, string]; // template delimiters
24+
25+
// allow user kept comments
26+
comments?: boolean
2427
};
2528

2629
declare type CompiledResult = {
@@ -61,7 +64,7 @@ declare type ASTDirective = {
6164
modifiers: ?ASTModifiers;
6265
};
6366

64-
declare type ASTNode = ASTElement | ASTText | ASTExpression;
67+
declare type ASTNode = ASTElement | ASTText | ASTExpression | ASTComment;
6568

6669
declare type ASTElement = {
6770
type: 1;
@@ -155,6 +158,15 @@ declare type ASTText = {
155158
ssrOptimizability?: number;
156159
};
157160

161+
declare type ASTComment = {
162+
type: 4;
163+
text: string;
164+
static?: boolean;
165+
166+
// 2.4 ssr optimization
167+
ssrOptimizability?: number;
168+
};
169+
158170
// SFC-parser related declarations
159171

160172
// an object format describing a single-file component.

flow/options.js

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ declare type ComponentOptions = {
6868
name?: string;
6969
extends?: Class<Component> | Object;
7070
delimiters?: [string, string];
71+
comments?: boolean;
7172

7273
// private
7374
_isComponent?: true;

src/compiler/codegen/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ function needsNormalization (el: ASTElement): boolean {
423423
function genNode (node: ASTNode, state: CodegenState): string {
424424
if (node.type === 1) {
425425
return genElement(node, state)
426+
} if (node.type === 4) {
427+
return genComment(node)
426428
} else {
427429
return genText(node)
428430
}
@@ -435,6 +437,10 @@ export function genText (text: ASTText | ASTExpression): string {
435437
})`
436438
}
437439

440+
export function genComment (comment: ASTComment): string {
441+
return `_e('${comment.text}')`
442+
}
443+
438444
function genSlot (el: ASTElement, state: CodegenState): string {
439445
const slotName = el.slotName || '"default"'
440446
const children = genChildren(el, state)

src/compiler/optimizer.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function markStaticRoots (node: ASTNode, isInFor: boolean) {
7777
// outweigh the benefits and it's better off to just always render it fresh.
7878
if (node.static && node.children.length && !(
7979
node.children.length === 1 &&
80-
node.children[0].type === 3
80+
(node.children[0].type === 3 || node.children[0].type === 4)
8181
)) {
8282
node.staticRoot = true
8383
return
@@ -104,6 +104,9 @@ function isStatic (node: ASTNode): boolean {
104104
if (node.type === 3) { // text
105105
return true
106106
}
107+
if (node.type === 4) { // comment
108+
return true
109+
}
107110
return !!(node.pre || (
108111
!node.hasBindings && // no dynamic bindings
109112
!node.if && !node.for && // not v-if or v-for or v-else

src/compiler/parser/html-parser.js

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ export function parseHTML (html, options) {
8282
const commentEnd = html.indexOf('-->')
8383

8484
if (commentEnd >= 0) {
85+
if (options.shouldKeptComment) {
86+
options.comment(html.substring(4, commentEnd))
87+
}
8588
advance(commentEnd + 3)
8689
continue
8790
}

src/compiler/parser/index.js

+7
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export function parse (
9090
isUnaryTag: options.isUnaryTag,
9191
canBeLeftOpenTag: options.canBeLeftOpenTag,
9292
shouldDecodeNewlines: options.shouldDecodeNewlines,
93+
shouldKeptComment: options.comments,
9394
start (tag, attrs, unary) {
9495
// check namespace.
9596
// inherit parent ns if there is one
@@ -274,6 +275,12 @@ export function parse (
274275
})
275276
}
276277
}
278+
},
279+
comment (text: string) {
280+
currentParent.children.push({
281+
type: 4,
282+
text
283+
})
277284
}
278285
})
279286
return root

src/core/vdom/vnode.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ export default class VNode {
6464
}
6565
}
6666

67-
export const createEmptyVNode = () => {
67+
export const createEmptyVNode = (text: string = '') => {
6868
const node = new VNode()
69-
node.text = ''
69+
node.text = text
7070
node.isComment = true
7171
return node
7272
}

src/platforms/web/entry-runtime-with-compiler.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ Vue.prototype.$mount = function (
6464

6565
const { render, staticRenderFns } = compileToFunctions(template, {
6666
shouldDecodeNewlines,
67-
delimiters: options.delimiters
67+
delimiters: options.delimiters,
68+
comments: options.comments
6869
}, this)
6970
options.render = render
7071
options.staticRenderFns = staticRenderFns

src/server/optimizing-compiler/optimizer.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ function optimizeSiblings (el) {
107107
}
108108

109109
function isUnOptimizableTree (node: ASTNode): boolean {
110-
if (node.type === 2 || node.type === 3) { // text or expression
110+
// text or expression or comment
111+
if (node.type === 2 || node.type === 3 || node.type === 4) {
111112
return false
112113
}
113114
return (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import Vue from 'vue'
2+
3+
describe('Comments', () => {
4+
it('comments should be kept', () => {
5+
const vm = new Vue({
6+
comments: true,
7+
data () {
8+
return {
9+
foo: 1
10+
}
11+
},
12+
template: '<div><span>node1</span><!--comment1-->{{foo}}<!--comment2--></div>'
13+
}).$mount()
14+
expect(vm.$el.innerHTML).toEqual('<span>node1</span><!--comment1-->1<!--comment2-->')
15+
})
16+
})

test/unit/modules/compiler/codegen.spec.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { parse } from 'compiler/parser/index'
22
import { optimize } from 'compiler/optimizer'
33
import { generate } from 'compiler/codegen'
4-
import { isObject } from 'shared/util'
4+
import { isObject, extend } from 'shared/util'
55
import { isReservedTag } from 'web/util/index'
66
import { baseOptions } from 'web/compiler/options'
77

@@ -460,6 +460,19 @@ describe('codegen', () => {
460460
)
461461
})
462462

463+
it('generate component with comment', () => {
464+
const options = extend({
465+
comments: true
466+
}, baseOptions)
467+
const template = '<div><!--comment--></div>'
468+
const generatedCode = `with(this){return _c('div',[_e('comment')])}`
469+
470+
const ast = parse(template, options)
471+
optimize(ast, options)
472+
const res = generate(ast, options)
473+
expect(res.render).toBe(generatedCode)
474+
})
475+
463476
it('not specified ast type', () => {
464477
const res = generate(null, baseOptions)
465478
expect(res.render).toBe(`with(this){return _c("div")}`)

test/unit/modules/compiler/optimizer.spec.js

+14
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { parse } from 'compiler/parser/index'
2+
import { extend } from 'shared/util'
23
import { optimize } from 'compiler/optimizer'
34
import { baseOptions } from 'web/compiler/options'
45

@@ -11,6 +12,19 @@ describe('optimizer', () => {
1112
expect(ast.children[0].static).toBe(true) // span
1213
})
1314

15+
it('simple with comment', () => {
16+
const options = extend({
17+
comments: true
18+
}, baseOptions)
19+
const ast = parse('<h1 id="section1"><span>hello world</span><!--comment--></h1>', options)
20+
optimize(ast, options)
21+
expect(ast.static).toBe(true) // h1
22+
expect(ast.staticRoot).toBe(true)
23+
expect(ast.children.length).toBe(2)
24+
expect(ast.children[0].static).toBe(true) // span
25+
expect(ast.children[1].static).toBe(true) // comment
26+
})
27+
1428
it('skip simple nodes', () => {
1529
const ast = parse('<h1 id="section1">hello</h1>', baseOptions)
1630
optimize(ast, baseOptions)

test/unit/modules/compiler/parser.spec.js

+22
Original file line numberDiff line numberDiff line change
@@ -548,4 +548,26 @@ describe('parser', () => {
548548
const ast = parse(`<script type="x/template">&gt;<foo>&lt;</script>`, options)
549549
expect(ast.children[0].text).toBe(`&gt;<foo>&lt;`)
550550
})
551+
552+
it('should ignore comments', () => {
553+
const options = extend({}, baseOptions)
554+
const ast = parse(`<div>123<!--comment here--></div>`, options)
555+
expect(ast.tag).toBe('div')
556+
expect(ast.children.length).toBe(1)
557+
expect(ast.children[0].type).toBe(3)
558+
expect(ast.children[0].text).toBe('123')
559+
})
560+
561+
it('should kept comments', () => {
562+
const options = extend({
563+
comments: true
564+
}, baseOptions)
565+
const ast = parse(`<div>123<!--comment here--></div>`, options)
566+
expect(ast.tag).toBe('div')
567+
expect(ast.children.length).toBe(2)
568+
expect(ast.children[0].type).toBe(3)
569+
expect(ast.children[0].text).toBe('123')
570+
expect(ast.children[1].type).toBe(4)
571+
expect(ast.children[1].text).toBe('comment here')
572+
})
551573
})

types/options.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export interface ComponentOptions<V extends Vue> {
5454
name?: string;
5555
extends?: ComponentOptions<Vue> | typeof Vue;
5656
delimiters?: [string, string];
57+
comments?: boolean;
5758
}
5859

5960
export interface FunctionalComponentOptions {

0 commit comments

Comments
 (0)