Repository: vuejs/vue-loader
Pull request #230 (2016-05-17 01:14:23)

pad results with whitespace - re #190
Re: #190 – Padded the output to get line numbers accurate. Not sure if this is the correct strategy or not. Also did not test the effects on source maps.

indirectlylit: Unfortunately, it looks like this change does not work because it doesn't take into account multiple `style` blocks. I'll look into that.
indirectlylit: Actually that's not true: it does report proper line numbers, even with multiple style blocks. That said, the whole strategy feels a bit hacky, as though it should be handled with source maps or similar. Unfortunately that's outside my expertise.

Any feedback would be appreciated.

Patch:
diff --git a/README.md b/README.md
index e6f0cf0..fab68c1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# vue-loader [![Build Status](https://circleci.com/gh/vuejs/vue-loader/tree/master.svg?style=shield)](https://circleci.com/gh/vuejs/vue-loader/tree/master) [![npm package](https://badge.fury.io/js/vue-loader.svg)](https://www.npmjs.com/package/vue-loader)
+# vue-loader [![Build Status](https://circleci.com/gh/vuejs/vue-loader/tree/master.svg?style=shield)](https://circleci.com/gh/vuejs/vue-loader/tree/master) [![npm package](https://img.shields.io/npm/v/vue-loader.svg?maxAge=2592000)](https://www.npmjs.com/package/vue-loader)
 
 > Vue.js component loader for [Webpack](http://webpack.github.io).
 
diff --git a/docs/en/features/postcss.md b/docs/en/features/postcss.md
index 487b9e7..48c35b5 100644
--- a/docs/en/features/postcss.md
+++ b/docs/en/features/postcss.md
@@ -47,3 +47,18 @@ module.exports = {
   }
 }
 ```
+
+In addition to providing an Array of plugins, the `postcss` option also accepts:
+
+- A function that returns an array of plugins;
+
+- An object that contains options to be passed to the PostCSS processor. This is useful when you are using PostCSS projects that relies on custom parser/stringifiers:
+
+  ``` js
+  postcss: {
+    plugins: [...], // list of plugins
+    options: {
+      parser: sugarss // use sugarss parser
+    }
+  }
+  ```
diff --git a/docs/en/options.md b/docs/en/options.md
index 5b51f0d..bed156a 100644
--- a/docs/en/options.md
+++ b/docs/en/options.md
@@ -54,3 +54,10 @@
   Whether to enable source maps for CSS. Disabling this can avoid some relative path related bugs in `css-loader` and make the build a bit faster.
 
   Note this is automatically set to `false` if the `devtool` option is not present in the main Webpack config.
+
+### template
+
+- ^8.4.0
+- type: `Object`
+
+  Pass options to the template rendering engine (via [consolidate](https://github.com/tj/consolidate.js)) if you are using a non-html templating language.
diff --git a/docs/en/start/spec.md b/docs/en/start/spec.md
index 2582754..c69b6eb 100644
--- a/docs/en/start/spec.md
+++ b/docs/en/start/spec.md
@@ -83,7 +83,7 @@ Beware that `src` imports follow the same path resolution rules to CommonJS `req
 
 ### Syntax Highlighting
 
-Currently there are syntax highlighting support for [Sublime Text](https://github.com/vuejs/vue-syntax-highlight), [Atom](https://atom.io/packages/language-vue), [Vim](https://github.com/posva/vim-vue), [Visual Studio Code](https://marketplace.visualstudio.com/items/liuji-jim.vue) and [Brackets](https://github.com/pandao/brackets-vue). Contributions for other editors/IDEs are highly appreciated! If you are not using any pre-processors in Vue components, you can also get by by treating `*.vue` files as HTML in your editor.
+Currently there is syntax highlighting support for [Sublime Text](https://github.com/vuejs/vue-syntax-highlight), [Atom](https://atom.io/packages/language-vue), [Vim](https://github.com/posva/vim-vue), [Visual Studio Code](https://marketplace.visualstudio.com/items/liuji-jim.vue), [Brackets](https://github.com/pandao/brackets-vue), and [JetBrains products](https://plugins.jetbrains.com/plugin/8057) (WebStorm, PhpStorm, etc). Contributions for other editors/IDEs are highly appreciated! If you are not using any pre-processors in Vue components, you can also get by by treating `*.vue` files as HTML in your editor.
 
 ### Comments
 
diff --git a/lib/loader.js b/lib/loader.js
index 1e889b2..c2e2644 100644
--- a/lib/loader.js
+++ b/lib/loader.js
@@ -218,9 +218,9 @@ module.exports = function (content) {
         'if (module.hot) {(function () {' +
         '  module.hot.accept()\n' +
         '  var hotAPI = require("vue-hot-reload-api")\n' +
-        '  hotAPI.install(require("vue"), true)\n' +
+        '  hotAPI.install(require("vue"), false)\n' +
         '  if (!hotAPI.compatible) return\n' +
-        '  var id = ' + JSON.stringify(filePath) + '\n' +
+        '  var id = ' + loaderUtils.stringifyRequest(loaderContext, filePath) + '\n' +
         '  if (!module.hot.data) {\n' +
         // initial insert
         '    hotAPI.createRecord(id, module.exports)\n' +
diff --git a/lib/parser.js b/lib/parser.js
index de7f533..a353635 100644
--- a/lib/parser.js
+++ b/lib/parser.js
@@ -97,9 +97,7 @@ module.exports = function (content, filename, needMap) {
     var start = node.childNodes[0].__location.startOffset
     var end = node.childNodes[node.childNodes.length - 1].__location.endOffset
     var result
-    var lineOffset
     if (type === 'script') {
-      lineOffset = 0
       // preserve other parts as commenets so that linters
       // and babel can output correct line numbers in warnings
       result =
@@ -107,8 +105,11 @@ module.exports = function (content, filename, needMap) {
         deindent(content.slice(start, end)) +
         commentScript(content.slice(end), lang)
     } else {
-      lineOffset = content.slice(0, start).split(splitRE).length - 1
+      var lineOffset = content.slice(0, start).split(splitRE).length - 1
       result = deindent(content.slice(start, end))
+
+      // pad whith whitespace so that error messages are correct
+      result = Array(lineOffset + 1).join('\n') + result
     }
 
     if (needMap) {
@@ -128,7 +129,7 @@ module.exports = function (content, filename, needMap) {
           map.addMapping({
             source: filenameWithHash,
             original: {
-              line: index + 1 + lineOffset,
+              line: index + 1,
               column: 0
             },
             generated: {
diff --git a/lib/style-rewriter.js b/lib/style-rewriter.js
index 23064b0..63ff2b7 100644
--- a/lib/style-rewriter.js
+++ b/lib/style-rewriter.js
@@ -3,8 +3,7 @@ var selectorParser = require('postcss-selector-parser')
 var loaderUtils = require('loader-utils')
 var assign = require('object-assign')
 
-var currentId
-var addId = postcss.plugin('add-id', function () {
+var addId = postcss.plugin('add-id', function (opts) {
   return function (root) {
     root.each(function rewriteSelector (node) {
       if (!node.selector) {
@@ -21,7 +20,7 @@ var addId = postcss.plugin('add-id', function () {
             if (n.type !== 'pseudo') node = n
           })
           selector.insertAfter(node, selectorParser.attribute({
-            attribute: currentId
+            attribute: opts.id
           }))
         })
       }).process(node.selector).result
@@ -41,12 +40,14 @@ module.exports = function (css, map) {
   var plugins = options.postcss
   if (typeof plugins === 'function') {
     plugins = plugins.call(this, this)
+  } else if (typeof options.postcss === 'object' && options.postcss.plugins) {
+    plugins = options.postcss.plugins
   }
   plugins = plugins ? plugins.slice() : [] // make sure to copy it
 
   // scoped css
   if (query.scoped) {
-    plugins.push(addId)
+    plugins.push(addId({ id: query.id }))
   }
 
   // autoprefixer
@@ -73,7 +74,8 @@ module.exports = function (css, map) {
     this.sourceMap &&
     !this.minimize &&
     options.cssSourceMap !== false &&
-    process.env.NODE_ENV !== 'production'
+    process.env.NODE_ENV !== 'production' &&
+    !options.postcss.options.map
   ) {
     opts.map = {
       inline: false,
@@ -82,7 +84,15 @@ module.exports = function (css, map) {
     }
   }
 
-  currentId = query.id
+  // postcss options from configuration
+  if (options.postcss && options.postcss.options) {
+    for (var option in options.postcss.options) {
+      if (!opts.hasOwnProperty(option)) {
+        opts[option] = options.postcss.options[option]
+      }
+    }
+  }
+
   postcss(plugins)
     .process(css, opts)
     .then(function (result) {
diff --git a/lib/template-loader.js b/lib/template-loader.js
index 575ea0c..af3d6e0 100644
--- a/lib/template-loader.js
+++ b/lib/template-loader.js
@@ -6,6 +6,12 @@ module.exports = function (content) {
   this.cacheable && this.cacheable()
   var callback = this.async()
   var opt = loaderUtils.parseQuery(this.query)
+  var vue = this.options.vue
+  if (vue && vue.template) {
+    for (var key in vue.template) {
+      opt[key] = vue.template[key]
+    }
+  }
 
   function exportContent (content) {
     if (opt.raw) {
diff --git a/package.json b/package.json
index 230263b..f0c4913 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vue-loader",
-  "version": "8.3.1",
+  "version": "8.5.0",
   "description": "Vue.js component loader for Webpack",
   "main": "index.js",
   "repository": {


Test patch:
diff --git a/test/test.js b/test/test.js
index 959ab05..038dc6c 100644
--- a/test/test.js
+++ b/test/test.js
@@ -215,7 +215,7 @@ describe('vue-loader', function () {
     }), function (err) {
       expect(err).to.be.null
       getFile('test.output.css', function (data) {
-        expect(data).to.contain('h1 {\n  color: #f00;\n}\n\nh2 {\n  color: green;\n}')
+        expect(data).to.contain('h1 {\n  color: #f00;\n}\n\n\n\n\n\n\nh2 {\n  color: green;\n}')
         done()
       })
     })