提交 f97e6766 编写于 作者: E Evan You

feat: support style/script hoisting + css modules

上级 c05448d5
<demo-1></demo-1>
<Demo>
<p>hello</p>
</Demo>
......@@ -79,10 +79,10 @@ Make sure a custom component's names either contains a hyphen or is in PascalCas
Sometimes you may need to apply some JavaScript or CSS only to the current page. In those case you can directly write root-level `<script>` or `<style>` blocks in the markdown file, and they will be hoisted out of the compiled HTML and used as the `<script>` and `<style>` blocks for the resulting Vue single-file component.
<div id="inline-script-style-example"></div>
<div :class="$style.example"></div>
<!-- <style>
#inline-script-style-example {
<style module>
.example {
color: #41b883;
}
</style>
......@@ -90,9 +90,8 @@ Sometimes you may need to apply some JavaScript or CSS only to the current page.
<script>
export default {
mounted () {
document.getElementById('inline-script-style-example')
document.querySelector(`.${this.$style.example}`)
.textContent = 'Hello from inline script!'
}
}
</script>
-->
// Replacing the default htmlBlock rule to allow using custom components at
// root level
const blockNames = require('markdown-it/lib/common/htmlBlocks')
const blockNames = require('markdown-it/lib/common/html_blocks')
const HTML_OPEN_CLOSE_TAG_RE = require('markdown-it/lib/common/html_re').HTML_OPEN_CLOSE_TAG_RE
// An array of opening and corresponding closing sequences for html tags,
......@@ -21,7 +21,7 @@ const HTML_SEQUENCES = [
]
module.exports = md => {
md.block.ruler.at('htmlBlock', htmlBlock)
md.block.ruler.at('html_block', htmlBlock)
}
function htmlBlock (state, startLine, endLine, silent) {
......@@ -73,7 +73,7 @@ function htmlBlock (state, startLine, endLine, silent) {
state.line = nextLine
const token = state.push('htmlBlock', '', 0)
const token = state.push('html_block', '', 0)
token.map = [startLine, nextLine]
token.content = state.getLines(startLine, nextLine, state.blkIndent, true)
......
module.exports = md => {
const RE = /^<(script|style)(?=(\s|>|$))/i
let hoistedTags
md.renderer.rules.html_block = (tokens, idx) => {
const content = tokens[idx].content
if (hoistedTags && RE.test(content.trim())) {
hoistedTags.push(content)
return ''
} else {
return content
}
}
md.renderWithHoisting = (...args) => {
hoistedTags = []
const html = md.render(...args)
return {
html,
hoistedTags
}
}
}
const highlight = require('./highlight')
const highlightLines = require('./highlightLines')
const component = require('./component')
const hoistScriptStyle = require('./hoist')
const convertRouterLink = require('./link')
const emoji = require('markdown-it-emoji')
const anchor = require('markdown-it-anchor')
......@@ -21,6 +22,7 @@ module.exports = ({ markdown = {}}) => {
.use(component)
.use(highlightLines)
.use(convertRouterLink)
.use(hoistScriptStyle)
// 3rd party plugins
.use(emoji)
.use(anchor, Object.assign({ permalink: true, permalinkBefore: true }, markdown.anchor))
......
......@@ -134,26 +134,33 @@ module.exports = function createBaseConfig ({
})
function createCSSRule (lang, test, loader, options) {
const rule = config.module
.rule(lang)
.test(test)
if (isProd) {
rule
.use('extract-css-loader').loader(CSSExtractPlugin.loader).end()
.use('css-loader').loader('css-loader').options({ minimize: true })
} else {
rule
.use('vue-style-loader').loader('vue-style-loader').end()
.use('css-loader').loader('css-loader')
}
rule.use('postcss-loader').loader('postcss-loader').options({
plugins: [require('autoprefixer')]
})
if (loader) {
rule.use(loader).loader(loader).options(options)
const baseRule = config.module.rule(lang).test(test)
const modulesRule = baseRule.oneOf('modules').resourceQuery(/module/)
const normalRule = baseRule.oneOf('normal')
applyLoaders(modulesRule, true)
applyLoaders(normalRule, false)
function applyLoaders (rule, modules) {
if (isProd) {
rule.use('extract-css-loader').loader(CSSExtractPlugin.loader)
} else {
rule.use('vue-style-loader').loader('vue-style-loader')
}
rule.use('css-loader').loader('css-loader').options({
modules,
minimize: isProd,
localIdentName: `[local]_[hash:base64:8]`
})
rule.use('postcss-loader').loader('postcss-loader').options({
plugins: [require('autoprefixer')]
})
if (loader) {
rule.use(loader).loader(loader).options(options)
}
}
}
......
......@@ -4,6 +4,11 @@ const frontmatter = require('yaml-front-matter')
module.exports = function (src) {
const { markdown } = getOptions(this)
const content = frontmatter.loadFront(src).__content
const html = markdown.render(content)
return `<template><div class="markdown">${html}</div></template>`
const { html, hoistedTags } = markdown.renderWithHoisting(content)
return (
`<template>\n` +
`<div class="markdown">${html}</div>\n` +
`</template>\n` +
hoistedTags.join('\n')
)
}
......@@ -5766,9 +5766,9 @@ vue-hot-reload-api@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
vue-loader@^15.0.0-beta.7:
version "15.0.0-beta.7"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.0.0-beta.7.tgz#2066ea26a940eed1fd97d2751c6abf5282f87b54"
vue-loader@^15.0.0-rc.1:
version "15.0.0-rc.1"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.0.0-rc.1.tgz#b34009276e7681f541967e151357b56158efa9b3"
dependencies:
"@vue/component-compiler-utils" "^1.0.0"
hash-sum "^1.0.2"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册