Repository: vuejs/vue-loader
Pull request #897 (2017-07-21 08:16:05)

support comment option in template
add a keyword ```comment``` to support  allow keep comments in sfc:  
```
<template comment>
  <div>
    ...
   <!-- comment -->
    ...
  </div>
</template>
```




Patch:
diff --git a/docs/en/configurations/advanced.md b/docs/en/configurations/advanced.md
index 2a4a33b..9056330 100644
--- a/docs/en/configurations/advanced.md
+++ b/docs/en/configurations/advanced.md
@@ -10,7 +10,7 @@ Sometimes you may want to:
 
 To do that, specify the `loaders` option for `vue-loader`:
 
-> Note that `preLoaders` and `postLoaders` are only supported in >=10.3.0
+> Note that `preLoaders` and `postLoaders` are only supported in 10.3.0+
 
 ### Webpack 2.x
 
diff --git a/docs/en/options.md b/docs/en/options.md
index dcb2ad3..09e6168 100644
--- a/docs/en/options.md
+++ b/docs/en/options.md
@@ -64,14 +64,14 @@ module.exports = {
 ### preLoaders
 
 - type: `{ [lang: string]: string }`
-- only supported in >=10.3.0
+- only supported in 10.3.0+
 
   The config format is the same as `loaders`, but `preLoaders` are applied to corresponding language blocks before the default loaders. You can use this to pre-process language blocks - a common use case would be build-time i18n.
 
 ### postLoaders
 
 - type: `{ [lang: string]: string }`
-- only supported in >=10.3.0
+- only supported in 10.3.0+
 
   The config format is the same as `loaders`, but `postLoaders` are applied after the default loaders. You can use this to post-process language blocks. However note that this is a bit more complicated:
 
@@ -81,7 +81,7 @@ module.exports = {
 
 ### postcss
 
-> Note: in >=11.0.0 it is recommended to use a PostCSS config file instead. [The usage is the same as `postcss-loader`](https://github.com/postcss/postcss-loader#usage).
+> Note: in 11.0.0+ it is recommended to use a PostCSS config file instead. [The usage is the same as `postcss-loader`](https://github.com/postcss/postcss-loader#usage).
 
 - type: `Array` or `Function` or `Object`
 
@@ -124,10 +124,12 @@ module.exports = {
 ### esModule
 
 - type: `boolean`
-- default: `false`
+- default: `true` (v13.0+)
 
   Whether to emit esModule compatible code. By default vue-loader will emit default export in commonjs format like `module.exports = ....`. When `esModule` is set to true, default export will be transpiled into `exports.__esModule = true; exports = ...`. Useful for interoperating with transpiler other than Babel, like TypeScript.
 
+  > version note: up to v12.x, default value is `false`.
+
 ### preserveWhitespace
 
 - type: `boolean`
diff --git a/docs/ja/configurations/advanced.md b/docs/ja/configurations/advanced.md
index 13ef1d2..b471629 100644
--- a/docs/ja/configurations/advanced.md
+++ b/docs/ja/configurations/advanced.md
@@ -8,7 +8,7 @@
 
 そうするためには、`vue-loader` に `loaders` オプションを指定してください:
 
-> メモ: `preLoaders` と `postLoaders` は 10.3.0 以上でのみサポートされます
+> メモ: `preLoaders` と `postLoaders` は 10.3.0 以降でのみサポートされます
 
 ### Webpack 2.x
 
diff --git a/docs/ja/options.md b/docs/ja/options.md
index 722ce1b..d5bc5f3 100644
--- a/docs/ja/options.md
+++ b/docs/ja/options.md
@@ -64,14 +64,14 @@ module.exports = {
 ### preLoaders
 
 - 型: `{ [lang: string]: string }`
-- 10.3.0 以上でサポートされます。
+- 10.3.0 以降でサポートされます。
 
   config 形式は `loaders` と同じですが、`preLoaders` はデフォルト loader の前に対応する言語ブロックに適用されます。これを使用して言語ブロックを前処理することができます。一般的な使用例としては、i18n のビルド時です。
 
 ### postLoaders
 
 - 型: `{ [lang: string]: string }`
-- 10.3.0 以上でサポートされます。
+- 10.3.0 以降でサポートされます。
 
   config 形式は `loaders` と同じですが、` postLoaders` はデフォルト loader の後に適用されます。これを使用して言語ブロックを後処理することができます。ただしこれは少し複雑になります:
 
@@ -80,7 +80,7 @@ module.exports = {
 
 ### postcss
 
-  > メモ: 11.0.0 以上では代わりに PostCSS の設定ファイル推奨されています。[使用法は `postcss-loader` と同じです](https://github.com/postcss/postcss-loader#usage)。
+  > メモ: 11.0.0 以降では代わりに PostCSS の設定ファイル推奨されています。[使用法は `postcss-loader` と同じです](https://github.com/postcss/postcss-loader#usage)。
 
 - 型: `Array` もしくは `Function` か `Object`
 
@@ -123,10 +123,12 @@ module.exports = {
 ### esModule
 
 - 型: `boolean`
-- デフォルト: `false`
+- デフォルト: `true` (v13.0以降)
 
   esModule 互換コードを発行するかどうか。デフォルトの vue-loader のデフォルトの出力は `module.exports = ....` のような commonjs 形式で発行します。 `esModule` が true にセットされているとき、デフォルトの出力は `exports.__esModule = true; exports = ...` にトランスパイルされます。TypeScript のような Babel 以外の transpiler との相互運用に役立ちます。
 
+  > バージョンメモ: v12.x までは、デフォルトは `false` です。
+
 ### preserveWhitespace
 
 - 型: `boolean`
@@ -251,7 +253,7 @@ module.exports = {
 
 ### optimizeSSR
 
-> 12.1.1 で追加
+> 12.1.1 で新規追加
 
 - 型: `boolean`
 - デフォルト: webpack 設定が `target: 'node'` でかつ `vue-template-compiler` が バージョン 2.4.0 以上であれば、`true`
diff --git a/docs/pt_BR/features/hot-reload.md b/docs/pt_BR/features/hot-reload.md
index 6757643..a5dea56 100644
--- a/docs/pt_BR/features/hot-reload.md
+++ b/docs/pt_BR/features/hot-reload.md
@@ -4,4 +4,4 @@
 
 ![hot-reload](http://blog.evanyou.me/images/vue-hot.gif)
 
-Quando o esqueleto do projeto é criado com `vue-cli`, Hot Reload é ativado e proto para o uso.
\ No newline at end of file
+Quando o esqueleto do projeto é criado com `vue-cli`, Hot Reload é ativado e pronto para o uso.
diff --git a/lib/loader.js b/lib/loader.js
index cc574b8..49ec3f2 100644
--- a/lib/loader.js
+++ b/lib/loader.js
@@ -89,10 +89,12 @@ module.exports = function (content) {
   var output = ''
   var parts = parse(content, fileName, this.sourceMap)
   var hasScoped = parts.styles.some(function (s) { return s.scoped })
+  var hasComment = parts.template && parts.template.attrs.comments
 
   var templateCompilerOptions = '?' + JSON.stringify({
     id: moduleId,
     hasScoped: hasScoped,
+    hasComment: hasComment,
     transformToRequire: options.transformToRequire,
     preserveWhitespace: options.preserveWhitespace,
     buble: options.buble,
@@ -182,7 +184,10 @@ module.exports = function (content) {
               invokeStyle(`cssModules["${moduleName}"] = ${requireString}`) +
               `Object.defineProperty(this, "${moduleName}", { get: function () { return cssModules["${moduleName}"] }})\n`
 
-            var requirePath = getRequireString('styles', style, i, style.scoped)
+            var requirePath = style.src
+              ? getRequireForImportString('styles', style, style.scoped)
+              : getRequireString('styles', style, i, style.scoped)
+
             output +=
               `module.hot && module.hot.accept([${requirePath}], function () {\n` +
               // 1. check if style has been injected
diff --git a/lib/style-compiler/plugins/scope-id.js b/lib/style-compiler/plugins/scope-id.js
index d0be6c1..20aba44 100644
--- a/lib/style-compiler/plugins/scope-id.js
+++ b/lib/style-compiler/plugins/scope-id.js
@@ -9,7 +9,7 @@ module.exports = postcss.plugin('add-id', function (opts) {
       if (!node.selector) {
         // handle media queries
         if (node.type === 'atrule') {
-          if (node.name === 'media') {
+          if (node.name === 'media' || node.name === 'supports') {
             node.each(rewriteSelector)
           } else if (node.name === 'keyframes') {
             // register keyframes
diff --git a/lib/template-compiler/index.js b/lib/template-compiler/index.js
index 3d123b3..72da533 100644
--- a/lib/template-compiler/index.js
+++ b/lib/template-compiler/index.js
@@ -23,7 +23,8 @@ module.exports = function (html) {
   var compilerOptions = {
     preserveWhitespace: options.preserveWhitespace,
     modules: defaultModules.concat(userModules || []),
-    scopeId: options.hasScoped ? options.id : null
+    scopeId: options.hasScoped ? options.id : null,
+    comments: options.hasComment
   }
 
   var compile = isServer && compiler.ssrCompile && vueOptions.optimizeSSR !== false


Test patch:
diff --git a/test/fixtures/supports-query.vue b/test/fixtures/supports-query.vue
new file mode 100644
index 0000000..88db497
--- /dev/null
+++ b/test/fixtures/supports-query.vue
@@ -0,0 +1,7 @@
+<style scoped>
+@supports ( color: #000 ) {
+  .foo {
+    color: #000;
+  }
+}
+</style>
diff --git a/test/fixtures/template-comment.vue b/test/fixtures/template-comment.vue
new file mode 100644
index 0000000..a72b02f
--- /dev/null
+++ b/test/fixtures/template-comment.vue
@@ -0,0 +1,16 @@
+<template comments>
+  <div>
+    <h2 class="red">{{msg}}</h2><!-- comment here -->
+  </div>
+</template>
+
+<script>
+export default {
+  comments: true,
+  data () {
+    return {
+      msg: 'Hello from Component A!'
+    }
+  }
+}
+</script>
diff --git a/test/test.js b/test/test.js
index 65c7488..60781e2 100644
--- a/test/test.js
+++ b/test/test.js
@@ -98,11 +98,18 @@ function mockRender (options, data) {
       children: children
     }
   }
+  function e (text = '') {
+    return {
+      text:  text,
+      isComment: true
+    }
+  }
   return options.render.call(Object.assign({
     _v (val) {
       return val
     },
     _self: {},
+    _e: e,
     $createElement: h,
     _m (index) {
       return options.staticRenderFns[index].call(this)
@@ -309,6 +316,18 @@ describe('vue-loader', function () {
     })
   })
 
+  it('supports-query', done => {
+    test({
+      entry: './test/fixtures/supports-query.vue'
+    }, (window) => {
+      var style = window.document.querySelector('style').textContent
+      style = normalizeNewline(style)
+      var id = 'data-v-' + hash('vue-loader/test/fixtures/supports-query.vue')
+      expect(style).to.contain('@supports ( color: #000 ) {\n.foo[' + id + '] {\n    color: #000;\n}\n}')
+      done()
+    })
+  })
+
   it('extract CSS', done => {
     bundle({
       entry: './test/fixtures/extract-css.vue',
@@ -895,4 +914,22 @@ describe('vue-loader', function () {
       done()
     })
   })
+
+  it('template with comments', done => {
+    test({
+      entry: './test/fixtures/template-comment.vue'
+    }, (window, module, rawModule) => {
+      expect(module.comments).to.equal(true)
+      var vnode = mockRender(module, {
+        msg: 'hi'
+      })
+      expect(vnode.tag).to.equal('div')
+      expect(vnode.children.length).to.equal(2)
+      expect(vnode.children[0].data.staticClass).to.equal('red')
+      expect(vnode.children[0].children[0]).to.equal('hi')
+      expect(vnode.children[1].isComment).to.true
+      expect(vnode.children[1].text).to.equal(' comment here ')
+      done()
+    })
+  })
 })