Skip to content

Commit

Permalink
feat: add comments option to allow preserving comments in template (#…
Browse files Browse the repository at this point in the history
…5951)

close #5392
  • Loading branch information
Kingwl authored and yyx990803 committed Jun 30, 2017
1 parent 51c595a commit e4da249
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 4 deletions.
4 changes: 4 additions & 0 deletions flow/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ declare type CompilerOptions = {

// runtime user-configurable
delimiters?: [string, string]; // template delimiters

// allow user kept comments
comments?: boolean
};

declare type CompiledResult = {
Expand Down Expand Up @@ -151,6 +154,7 @@ declare type ASTText = {
type: 3;
text: string;
static?: boolean;
isComment?: boolean;
// 2.4 ssr optimization
ssrOptimizability?: number;
};
Expand Down
1 change: 1 addition & 0 deletions flow/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ declare type ComponentOptions = {
name?: string;
extends?: Class<Component> | Object;
delimiters?: [string, string];
comments?: boolean;

// private
_isComponent?: true;
Expand Down
6 changes: 6 additions & 0 deletions src/compiler/codegen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,8 @@ function needsNormalization (el: ASTElement): boolean {
function genNode (node: ASTNode, state: CodegenState): string {
if (node.type === 1) {
return genElement(node, state)
} if (node.type === 3 && node.isComment) {
return genComment(node)
} else {
return genText(node)
}
Expand All @@ -435,6 +437,10 @@ export function genText (text: ASTText | ASTExpression): string {
})`
}

export function genComment (comment: ASTText): string {
return `_e('${comment.text}')`
}

function genSlot (el: ASTElement, state: CodegenState): string {
const slotName = el.slotName || '"default"'
const children = genChildren(el, state)
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/parser/html-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ export function parseHTML (html, options) {
const commentEnd = html.indexOf('-->')

if (commentEnd >= 0) {
if (options.shouldKeepComment) {
options.comment(html.substring(4, commentEnd))
}
advance(commentEnd + 3)
continue
}
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export function parse (
isUnaryTag: options.isUnaryTag,
canBeLeftOpenTag: options.canBeLeftOpenTag,
shouldDecodeNewlines: options.shouldDecodeNewlines,
shouldKeepComment: options.comments,
start (tag, attrs, unary) {
// check namespace.
// inherit parent ns if there is one
Expand Down Expand Up @@ -274,6 +275,13 @@ export function parse (
})
}
}
},
comment (text: string) {
currentParent.children.push({
type: 3,
text,
isComment: true
})
}
})
return root
Expand Down
4 changes: 2 additions & 2 deletions src/core/vdom/vnode.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ export default class VNode {
}
}

export const createEmptyVNode = () => {
export const createEmptyVNode = (text: string = '') => {
const node = new VNode()
node.text = ''
node.text = text
node.isComment = true
return node
}
Expand Down
3 changes: 2 additions & 1 deletion src/platforms/web/entry-runtime-with-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ Vue.prototype.$mount = function (

const { render, staticRenderFns } = compileToFunctions(template, {
shouldDecodeNewlines,
delimiters: options.delimiters
delimiters: options.delimiters,
comments: options.comments
}, this)
options.render = render
options.staticRenderFns = staticRenderFns
Expand Down
16 changes: 16 additions & 0 deletions test/unit/features/options/comments.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Vue from 'vue'

describe('Comments', () => {
it('comments should be kept', () => {
const vm = new Vue({
comments: true,
data () {
return {
foo: 1
}
},
template: '<div><span>node1</span><!--comment1-->{{foo}}<!--comment2--></div>'
}).$mount()
expect(vm.$el.innerHTML).toEqual('<span>node1</span><!--comment1-->1<!--comment2-->')
})
})
15 changes: 14 additions & 1 deletion test/unit/modules/compiler/codegen.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { parse } from 'compiler/parser/index'
import { optimize } from 'compiler/optimizer'
import { generate } from 'compiler/codegen'
import { isObject } from 'shared/util'
import { isObject, extend } from 'shared/util'
import { isReservedTag } from 'web/util/index'
import { baseOptions } from 'web/compiler/options'

Expand Down Expand Up @@ -474,6 +474,19 @@ describe('codegen', () => {
)
})

it('generate component with comment', () => {
const options = extend({
comments: true
}, baseOptions)
const template = '<div><!--comment--></div>'
const generatedCode = `with(this){return _c('div',[_e('comment')])}`

const ast = parse(template, options)
optimize(ast, options)
const res = generate(ast, options)
expect(res.render).toBe(generatedCode)
})

it('not specified ast type', () => {
const res = generate(null, baseOptions)
expect(res.render).toBe(`with(this){return _c("div")}`)
Expand Down
14 changes: 14 additions & 0 deletions test/unit/modules/compiler/optimizer.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parse } from 'compiler/parser/index'
import { extend } from 'shared/util'
import { optimize } from 'compiler/optimizer'
import { baseOptions } from 'web/compiler/options'

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

it('simple with comment', () => {
const options = extend({
comments: true
}, baseOptions)
const ast = parse('<h1 id="section1"><span>hello world</span><!--comment--></h1>', options)
optimize(ast, options)
expect(ast.static).toBe(true) // h1
expect(ast.staticRoot).toBe(true)
expect(ast.children.length).toBe(2)
expect(ast.children[0].static).toBe(true) // span
expect(ast.children[1].static).toBe(true) // comment
})

it('skip simple nodes', () => {
const ast = parse('<h1 id="section1">hello</h1>', baseOptions)
optimize(ast, baseOptions)
Expand Down
23 changes: 23 additions & 0 deletions test/unit/modules/compiler/parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,4 +548,27 @@ describe('parser', () => {
const ast = parse(`<script type="x/template">&gt;<foo>&lt;</script>`, options)
expect(ast.children[0].text).toBe(`&gt;<foo>&lt;`)
})

it('should ignore comments', () => {
const options = extend({}, baseOptions)
const ast = parse(`<div>123<!--comment here--></div>`, options)
expect(ast.tag).toBe('div')
expect(ast.children.length).toBe(1)
expect(ast.children[0].type).toBe(3)
expect(ast.children[0].text).toBe('123')
})

it('should kept comments', () => {
const options = extend({
comments: true
}, baseOptions)
const ast = parse(`<div>123<!--comment here--></div>`, options)
expect(ast.tag).toBe('div')
expect(ast.children.length).toBe(2)
expect(ast.children[0].type).toBe(3)
expect(ast.children[0].text).toBe('123')
expect(ast.children[1].type).toBe(3) // parse comment with ASTText
expect(ast.children[1].isComment).toBe(true) // parse comment with ASTText
expect(ast.children[1].text).toBe('comment here')
})
})
1 change: 1 addition & 0 deletions types/options.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface ComponentOptions<V extends Vue> {
name?: string;
extends?: ComponentOptions<Vue> | typeof Vue;
delimiters?: [string, string];
comments?: boolean;
}

export interface FunctionalComponentOptions {
Expand Down

0 comments on commit e4da249

Please sign in to comment.