Skip to content

Commit 0f09e8b

Browse files
committed
feat: add preventExtract option, fixed QingWei-Li#27
1 parent aea714f commit 0f09e8b

File tree

4 files changed

+2410
-440
lines changed

4 files changed

+2410
-440
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ module.exports = {
5050

5151
## Options
5252

53+
### preventExtract
54+
55+
Since `v2.0.0`, this loader will automatically extract script and style tags from html token content (#26). If you do not need, you can set this option
56+
57+
```js
58+
{
59+
test: /\.md$/,
60+
loader: 'vue-markdown-loader',
61+
options: {
62+
preventExtract: true
63+
}
64+
}
65+
```
66+
67+
### markdownIt
68+
5369
reference [markdown-it](https://github.com/markdown-it/markdown-it#init-with-presets-and-options)
5470
```javascript
5571
{

example/webpack.config.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,40 @@
1-
var resolve = require('path').resolve
2-
var webpack = require('webpack')
1+
var resolve = require("path").resolve;
2+
var webpack = require("webpack");
33

44
module.exports = {
5-
entry: './src/entry.js',
5+
entry: "./src/entry.js",
66
output: {
7-
path: resolve(__dirname, './dist'),
8-
publicPath: '/dist/',
9-
filename: 'build.js'
7+
path: resolve(__dirname, "./dist"),
8+
publicPath: "/dist/",
9+
filename: "build.js"
1010
},
1111
module: {
1212
rules: [
1313
{
1414
test: /\.vue$/,
15-
loader: 'vue-loader'
15+
loader: "vue-loader"
1616
},
1717
{
1818
test: /\.js$/,
19-
loader: 'babel-loader',
19+
loader: "babel-loader",
2020
exclude: /node_modules/,
2121
options: {
22-
presets: ['es2015']
22+
presets: ["es2015"]
2323
}
2424
},
2525
{
2626
test: /\.css$/,
27-
use: ['style-loader', 'css-loader']
27+
use: ["style-loader", "css-loader"]
2828
},
2929
{
3030
test: /\.md$/,
31-
loader: resolve(__dirname, '../index.js')
31+
loader: resolve(__dirname, "../index.js"),
32+
options: {}
3233
}
3334
]
3435
},
3536
devServer: {
3637
historyApiFallback: true,
3738
noInfo: true
3839
}
39-
}
40+
};

lib/markdown-compiler.js

Lines changed: 102 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,164 @@
1-
var loaderUtils = require('loader-utils')
2-
var hljs = require('highlight.js')
3-
var cheerio = require('cheerio')
4-
var markdown = require('markdown-it')
5-
var Token = require('markdown-it/lib/token');
1+
var loaderUtils = require("loader-utils");
2+
var hljs = require("highlight.js");
3+
var cheerio = require("cheerio");
4+
var markdown = require("markdown-it");
5+
var Token = require("markdown-it/lib/token");
66

77
/**
88
* `<pre></pre>` => `<pre v-pre></pre>`
99
* `<code></code>` => `<code v-pre></code>`
1010
* @param {string} str
1111
* @return {string}
1212
*/
13-
var addVuePreviewAttr = function (str) {
14-
return str.replace(/(<pre|<code)/g, '$1 v-pre')
15-
}
13+
var addVuePreviewAttr = function(str) {
14+
return str.replace(/(<pre|<code)/g, "$1 v-pre");
15+
};
1616

1717
/**
1818
* renderHighlight
1919
* @param {string} str
2020
* @param {string} lang
2121
*/
22-
var renderHighlight = function (str, lang) {
22+
var renderHighlight = function(str, lang) {
2323
if (!(lang && hljs.getLanguage(lang))) {
24-
return ''
24+
return "";
2525
}
2626

27-
return hljs.highlight(lang, str, true).value
28-
}
27+
return hljs.highlight(lang, str, true).value;
28+
};
2929

3030
/**
3131
* html => vue file template
3232
* @param {[type]} html [description]
3333
* @return {[type]} [description]
3434
*/
35-
var renderVueTemplate = function (html) {
35+
var renderVueTemplate = function(html) {
3636
var $ = cheerio.load(html, {
3737
decodeEntities: false,
3838
lowerCaseAttributeNames: false,
39-
lowerCaseTags: false,
40-
})
39+
lowerCaseTags: false
40+
});
4141

4242
var output = {
43-
style: $.html('style'),
44-
script: $.html('script'),
43+
style: $.html("style"),
44+
script: $.html("script")
45+
};
46+
var result;
47+
48+
$("style").remove();
49+
$("script").remove();
50+
51+
result =
52+
"<template><section>" +
53+
$.html() +
54+
"</section></template>\n" +
55+
output.style +
56+
"\n" +
57+
output.script;
58+
59+
return result;
60+
};
61+
62+
module.exports = function(source) {
63+
this.cacheable && this.cacheable();
64+
var parser, preprocess;
65+
var params = loaderUtils.parseQuery(this.query) || {};
66+
var vueMarkdownOptions = this.options.__vueMarkdownOptions__;
67+
var opts = Object.create(vueMarkdownOptions.__proto__); // inherit prototype
68+
var preventExtract = false;
69+
70+
opts = Object.assign(opts, params, vueMarkdownOptions); // assign attributes
71+
72+
if (opts.preventExtract) {
73+
delete opts.preventExtract;
74+
preventExtract = true;
4575
}
46-
var result
4776

48-
$('style').remove()
49-
$('script').remove()
50-
51-
result = '<template><section>' + $.html() + '</section></template>\n' +
52-
output.style + '\n' +
53-
output.script
54-
55-
return result
56-
}
57-
58-
module.exports = function (source) {
59-
this.cacheable && this.cacheable()
60-
var parser, preprocess
61-
var params = loaderUtils.parseQuery(this.query) || {}
62-
var vueMarkdownOptions = this.options.__vueMarkdownOptions__
63-
var opts = Object.create(vueMarkdownOptions.__proto__) // inherit prototype
64-
opts = Object.assign(opts, params, vueMarkdownOptions) // assign attributes
65-
66-
if (typeof opts.render === 'function') {
67-
parser = opts
77+
if (typeof opts.render === "function") {
78+
parser = opts;
6879
} else {
69-
opts = Object.assign({
70-
preset: 'default',
71-
html: true,
72-
highlight: renderHighlight,
73-
}, opts)
80+
opts = Object.assign(
81+
{
82+
preset: "default",
83+
html: true,
84+
highlight: renderHighlight
85+
},
86+
opts
87+
);
7488

75-
var plugins = opts.use
76-
preprocess = opts.preprocess
89+
var plugins = opts.use;
90+
preprocess = opts.preprocess;
7791

78-
delete opts.use
79-
delete opts.preprocess
92+
delete opts.use;
93+
delete opts.preprocess;
8094

81-
parser = markdown(opts.preset, opts)
95+
parser = markdown(opts.preset, opts);
8296

8397
//add ruler:extract script and style tags from html token content
84-
parser.core.ruler.push('extract_script_or_style', function replace(state) {
85-
let tag_reg=new RegExp("<(script|style)(?:[^<]|<)+<\/\\1>",'g');
86-
let newTokens=[];
87-
state.tokens.filter(token=>token.type=='fence' && token.info=='html').forEach(token=>{
88-
let tokens=(token.content.match(tag_reg)||[]).map(content=>{
89-
let t=new Token('html_block', '', 0);
90-
t.content=content;
91-
return t;
92-
});
93-
if(tokens.length>0){
94-
newTokens.push.apply(newTokens, tokens);
95-
}
96-
})
97-
state.tokens.push.apply(state.tokens, newTokens);
98-
});
98+
!preventExtract &&
99+
parser.core.ruler.push("extract_script_or_style", function replace(
100+
state
101+
) {
102+
let tag_reg = new RegExp("<(script|style)(?:[^<]|<)+</\\1>", "g");
103+
let newTokens = [];
104+
state.tokens
105+
.filter(token => token.type == "fence" && token.info == "html")
106+
.forEach(token => {
107+
let tokens = (token.content.match(tag_reg) || []).map(content => {
108+
let t = new Token("html_block", "", 0);
109+
t.content = content;
110+
return t;
111+
});
112+
if (tokens.length > 0) {
113+
newTokens.push.apply(newTokens, tokens);
114+
}
115+
});
116+
state.tokens.push.apply(state.tokens, newTokens);
117+
});
99118

100119
if (plugins) {
101-
plugins.forEach(function (plugin) {
120+
plugins.forEach(function(plugin) {
102121
if (Array.isArray(plugin)) {
103-
parser.use.apply(parser, plugin)
122+
parser.use.apply(parser, plugin);
104123
} else {
105-
parser.use(plugin)
124+
parser.use(plugin);
106125
}
107-
})
126+
});
108127
}
109128
}
110129

111130
/**
112131
* override default parser rules by adding v-pre attribute on 'code' and 'pre' tags
113132
* @param {Array<string>} rules rules to override
114133
*/
115-
function overrideParserRules (rules) {
134+
function overrideParserRules(rules) {
116135
if (parser && parser.renderer && parser.renderer.rules) {
117-
var parserRules = parser.renderer.rules
118-
rules.forEach(function (rule) {
136+
var parserRules = parser.renderer.rules;
137+
rules.forEach(function(rule) {
119138
if (parserRules && parserRules[rule]) {
120-
var defaultRule = parserRules[rule]
121-
parserRules[rule] = function () {
122-
return addVuePreviewAttr(defaultRule.apply(this, arguments))
123-
}
139+
var defaultRule = parserRules[rule];
140+
parserRules[rule] = function() {
141+
return addVuePreviewAttr(defaultRule.apply(this, arguments));
142+
};
124143
}
125-
})
144+
});
126145
}
127146
}
128147

129-
overrideParserRules([ 'code_inline', 'code_block', 'fence' ])
148+
overrideParserRules(["code_inline", "code_block", "fence"]);
130149

131150
if (preprocess) {
132-
source = preprocess.call(this, parser, source)
151+
source = preprocess.call(this, parser, source);
133152
}
134153

135-
source = source.replace(/@/g, '__at__')
154+
source = source.replace(/@/g, "__at__");
136155

137-
var content = parser.render(source).replace(/__at__/g, '@')
138-
var result = renderVueTemplate(content)
156+
var content = parser.render(source).replace(/__at__/g, "@");
157+
var result = renderVueTemplate(content);
139158

140159
if (opts.raw) {
141-
return result
160+
return result;
142161
} else {
143-
return 'module.exports = ' + JSON.stringify(result)
162+
return "module.exports = " + JSON.stringify(result);
144163
}
145-
}
164+
};

0 commit comments

Comments
 (0)