Skip to content

feat: Call custom block loaders with Component as argument #664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions docs/en/configurations/custom-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

You can define custom language blocks inside `*.vue` files. The content of a custom block will be processed by the loaders specified in the `loaders` object of `vue-loader` options and then required by the component module. The configuration is similar to what is described in [Advanced Loader Configuration](../configurations/advanced.md), except the matching uses the tag name instead of the `lang` attribute.

If a matching loader is found for a custom block, it will be processed; otherwise the custom block will simply be ignored.
If a matching loader is found for a custom block, it will be processed; otherwise the custom block will simply be ignored. Additionally, if the found loader returns a function, that function will be called with the component of the `*.vue` file as a parameter.

## Example
## Single docs file example

Here's an example of extracting all `<docs>` custom blocks into a single docs file:

Expand Down Expand Up @@ -65,3 +65,69 @@ module.exports = {
]
}
```

## Runtime available docs

Here's an example of injecting the `<docs>` custom blocks into the component so that it's available during runtime.

#### docs-loader.js

In order for the custom block content to be injected, we'll need a custom loader:

``` js
module.exports = function (source, map) {
this.callback(null, 'module.exports = function(Component) {Component.options.__docs = ' +
JSON.stringify(source) +
'}', map)
}
```

#### webpack.config.js

Now we'll configure webpack to use our custom loader for `<docs>` custom blocks.

``` js
const docsLoader = require.resolve('./custom-loaders/docs-loader.js')

module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue',
options: {
loaders: {
'docs': docsLoader
}
}
}
]
}
}
```

#### component.vue

We are now able to access the `<docs>` block's content of imported components during runtime.

``` html
<template>
<div>
<component-b \>
<p>{{ docs }}</p>
</div>
</template>

<script>
import componentB from 'componentB';

export default = {
data () {
return {
docs: componentB.__docs
}
},
components: {componentB}
}
</script>
```
6 changes: 5 additions & 1 deletion lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,11 @@ module.exports = function (content) {
addedPrefix = true
}

output += requireString + '\n'
output +=
'var customBlock = ' + requireString + '\n' +
'if (typeof customBlock === "function") {' +
'customBlock(Component)' +
'}\n'
}
})

Expand Down
5 changes: 5 additions & 0 deletions test/mock-loaders/docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = function (source, map) {
this.callback(null, 'module.exports = function(Component) {Component.options.__docs = ' +
JSON.stringify(source) +
'}', map)
}
15 changes: 15 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,21 @@ describe('vue-loader', function () {
})
})

it('passes Component to custom block loaders', done => {
const mockLoaderPath = require.resolve('./mock-loaders/docs')
test({
entry: './test/fixtures/custom-language.vue',
vue: {
loaders: {
'documentation': mockLoaderPath
}
}
}, (window, module) => {
expect(module.__docs).to.contain('This is example documentation for a component.')
done()
})
})

it('custom blocks can be ignored', done => {
bundle({
entry: './test/fixtures/custom-language.vue'
Expand Down