diff --git a/docs/en/README.md b/docs/en/README.md
index 2bb3116c8..21e30088a 100644
--- a/docs/en/README.md
+++ b/docs/en/README.md
@@ -10,6 +10,7 @@ There are many cool features provided by `vue-loader`:
- ES2015 enabled by default;
- Allows using other Webpack loaders for each part of a Vue component, for example SASS for `
+
+
+ This could be e.g. documentation for the component.
+
```
`vue-loader` will parse the file, extract each language block, pipe them through other loaders if necessary, and finally assemble them back into a CommonJS module whose `module.exports` is a Vue.js component options object.
@@ -66,6 +70,66 @@ More details can be found in [Using Pre-Processors](../configurations/pre-proces
- By default, contents will be extracted and dynamically inserted into the document's `
` as an actual `
+```
+
+#### webpack.config.js
+
+``` js
+// Webpack 2.x (^2.1.0-beta.25)
+module.exports = {
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: 'vue',
+ // vue-loader options go here
+ options: {
+ loaders: {
+ unit-test: 'buble-loader',
+ }
+ }
+ }
+ ]
+ }
+}
+```
+
+
### Src Imports
If you prefer splitting up your `*.vue` components into multiple files, you can use the `src` attribute to import an external file for a language block:
@@ -83,6 +147,13 @@ Beware that `src` imports follow the same path resolution rules to CommonJS `req
diff --git a/test/fixtures/custom-language.vue b/test/fixtures/custom-language.vue
new file mode 100644
index 000000000..3684d135b
--- /dev/null
+++ b/test/fixtures/custom-language.vue
@@ -0,0 +1,31 @@
+
+ describe('example', function () {
+ it('basic', function (done) {
+ done();
+ })
+ })
+
+
+
+ This is example documentation for a component.
+
+
+
+ {{msg}}
+
+
+
+
+
diff --git a/test/fixtures/custom-options.vue b/test/fixtures/custom-options.vue
new file mode 100644
index 000000000..c8249bbd6
--- /dev/null
+++ b/test/fixtures/custom-options.vue
@@ -0,0 +1,7 @@
+
+ describe('example', function () {
+ it('basic', function (done) {
+ done();
+ })
+ })
+
diff --git a/test/fixtures/unit-test.js b/test/fixtures/unit-test.js
new file mode 100644
index 000000000..422357802
--- /dev/null
+++ b/test/fixtures/unit-test.js
@@ -0,0 +1,5 @@
+ describe('example', function () {
+ it('basic', function (done) {
+ done();
+ })
+ })
diff --git a/test/test.js b/test/test.js
index 2e7a8edd9..69e716505 100644
--- a/test/test.js
+++ b/test/test.js
@@ -57,12 +57,12 @@ function bundle (options, cb) {
})
}
expect(stats.compilation.errors).to.be.empty
- cb(mfs.readFileSync('/test.build.js').toString())
+ cb(mfs.readFileSync('/test.build.js').toString(), stats.compilation.warnings)
})
}
function test (options, assert) {
- bundle(options, function (code) {
+ bundle(options, function (code, warnings) {
jsdom.env({
html: '',
src: [code],
@@ -226,11 +226,10 @@ describe('vue-loader', function () {
})
it('source map', function (done) {
- var config = Object.assign({}, globalConfig, {
+ bundle({
entry: './test/fixtures/basic.vue',
devtool: '#source-map'
- })
- bundle(config, function (code) {
+ }, function (code, warnings) {
var map = mfs.readFileSync('/test.build.js.map').toString()
var smc = new SourceMapConsumer(JSON.parse(map))
var line
@@ -266,7 +265,7 @@ describe('vue-loader', function () {
})
it('extract CSS', function (done) {
- bundle(Object.assign({}, globalConfig, {
+ bundle({
entry: './test/fixtures/extract-css.vue',
vue: {
loaders: {
@@ -277,7 +276,7 @@ describe('vue-loader', function () {
plugins: [
new ExtractTextPlugin('test.output.css')
]
- }), function () {
+ }, function (code, warnings) {
var css = mfs.readFileSync('/test.output.css').toString()
css = normalizeNewline(css)
expect(css).to.contain('h1 {\n color: #f00;\n}\n\nh2 {\n color: green;\n}')
@@ -488,7 +487,7 @@ describe('vue-loader', function () {
output: Object.assign({}, globalConfig.output, {
libraryTarget: 'commonjs2'
})
- }, function (code) {
+ }, function (code, warnings) {
// http://stackoverflow.com/questions/17581830/load-node-js-module-from-string-in-memory
function requireFromString(src, filename) {
var Module = module.constructor;
@@ -570,4 +569,124 @@ describe('vue-loader', function () {
})
})
})
+
+ it('extract custom blocks to a separate file', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-language.vue',
+ vue: {
+ loaders: {
+ 'documentation': ExtractTextPlugin.extract('raw-loader')
+ }
+ },
+ plugins: [
+ new ExtractTextPlugin('doc.md')
+ ]
+ }, function (code, warnings) {
+ var unitTest = mfs.readFileSync('/doc.md').toString()
+ unitTest = normalizeNewline(unitTest)
+ expect(unitTest).to.contain('This is example documentation for a component.')
+ done()
+ })
+ })
+
+ it('add custom blocks to the webpack output', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-language.vue',
+ vue: {
+ loaders: {
+ 'unit-test': 'babel-loader'
+ }
+ }
+ }, function (code, warnings) {
+ expect(code).to.contain('describe(\'example\', function () {\n it(\'basic\', function (done) {\n done();\n });\n})')
+ done()
+ })
+ })
+
+ it('custom blocks work with src imports', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-import.vue',
+ vue: {
+ loaders: {
+ 'unit-test': 'babel-loader'
+ }
+ }
+ }, function (code, warnings) {
+ expect(code).to.contain('describe(\'example\', function () {\n it(\'basic\', function (done) {\n done();\n });\n})')
+ done()
+ })
+ })
+
+ it('custom blocks can be removed from the output', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-language.vue',
+ vue: {
+ loaders: {
+ 'unit-test': 'null-loader'
+ }
+ }
+ }, function (code, warnings) {
+ expect(code).not.to.contain('describe(\'example\', function () {\n it(\'basic\', function (done) {\n done();\n });\n})')
+ done()
+ })
+ })
+
+ it('no warnings when loaders are specified for all custom blocks', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-language.vue',
+ vue: {
+ loaders: {
+ 'documentation': 'null-loader',
+ 'unit-test': 'null-loader'
+ }
+ }
+ }, function (code, warnings) {
+ expect(warnings.length).to.equal(0)
+ done()
+ })
+ })
+
+ it('warning should be raised when a loader is not specified for a custom block', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-language.vue',
+ vue: {
+ loaders: {
+ 'documentation': 'null-loader'
+ }
+ }
+ }, function (code, warnings) {
+ expect(warnings.length).to.equal(1)
+ expect(warnings[0].message).to.equal('Loader for custom block type "unit-test" not found in webpack configuration')
+ done()
+ })
+ })
+
+ it('passes attributes as options to the loader', function (done) {
+ bundle({
+ entry: './test/fixtures/custom-options.vue',
+ vue: {
+ loaders: {
+ 'unit-test': 'babel-loader!skeleton-loader'
+ }
+ },
+ plugins: [
+ new webpack.LoaderOptionsPlugin({
+ options: {
+ skeletonLoader: {
+ procedure: function(content, sourceMap, callback, options) {
+ expect(options.foo).to.equal('bar');
+ expect(options.opt2).to.equal('value2');
+
+ // Return the content to output.
+ return content;
+ }
+ }
+ }
+ })
+ ]
+ }, function (code, warnings) {
+ expect(code).to.contain('describe(\'example\', function () {\n it(\'basic\', function (done) {\n done();\n });\n})')
+ done()
+ })
+ })
})