@sdoc/markdown-loader
Version:
san markdown loader
147 lines (133 loc) • 4.79 kB
JavaScript
/**
* @file 解析器
* @author ksky521
*/
const MdIt = require('markdown-it');
function getCompiler(opt = {}) {
// {
// anchor
// toc
// lineNumbers
// extend
// extractHeaders
// }
const {
link,
lineNumbers = false,
anchor = {permalink: false, permalinkBefore: false},
extend = () => {},
toc = {includeLevel: [2, 3]},
table = {
multiline: false,
rowspan: true,
headerless: false
}
} = opt;
const preset = opt.preset;
// prettier-ignore
let parser = preset === 'default' || preset === 'commonmark' || preset === 'zero' ? new MdIt(opt) : new MdIt(
Object.assign({
xhtmlOut: true,
html: true,
highlight: require('./markdown/prismjs')({lineNumbers})
}, preset)
);
parser.use(require('markdown-it-cjk-breaks'));
parser.use(require('markdown-it-emoji'));
parser.use(require('markdown-it-deflist'));
parser.use(require('markdown-it-footnote'));
parser.use(require('markdown-it-ins'));
parser.use(require('markdown-it-anchor'), anchor);
parser.use(require('markdown-it-table-of-contents'), toc);
parser.use(require('markdown-it-sub'));
parser.use(require('markdown-it-imsize'));
parser.use(require('markdown-it-sup'));
parser.use(require('markdown-it-attrs'));
parser.use(require('markdown-it-task-lists'));
parser.use(require('markdown-it-multimd-table'), table);
parser.use(require('markdown-it-div'), {
render(tokens, idx, options, env, slf) {
const info = tokens[idx].info.trim();
const m = info.match(/(\]\(["']*\.\/).*(png|gif|jpg)/);
console.log('info:', info, m);
}
});
parser.use(require('markdown-it-div'), {
render(tokens, idx, options, env, slf) {
const map = {
warn: 'warning',
danger: 'error',
tip: 'info'
};
const info = tokens[idx].info.trim();
const m = info.match(/^(warning|error|danger|warn|tip|info|success)\s+(.*)$/);
if (tokens[idx].nesting === 1) {
// opening tag
let rs = '';
if (m) {
const cls = map[m[1]] ? map[m[1]] : m[1];
rs += `<div class="${cls}">`;
const title = m[2];
if (title) {
rs += `<p class="info-title">${parser.utils.escapeHtml(title)}</p>\n`;
}
return rs;
}
// add a class to the opening tag
const params = info.split(/\s+/);
let id = null;
let classes = [];
for (let i = 0; i < params.length; i++) {
let cls = params[i];
if (cls.includes('=')) {
let [set0, set1] = cls.split('=', 2);
tokens[idx].attrJoin(set0, set1);
}
else if (cls[0] === '#') {
id = cls.slice(1);
}
else if (cls[0] === '.') {
classes.push(cls.slice(1));
}
else {
classes.push(cls);
}
}
if (id) {
tokens[idx].attrJoin('id', id);
}
if (classes.length > 0) {
tokens[idx].attrJoin('class', classes.join(' '));
}
return slf.renderToken(tokens, idx, options, env, slf);
}
// closing tag
return '</div>\n';
}
});
parser.use(require('./markdown/jsx'));
parser.use(require('./markdown/link'), link);
parser.use(require('./markdown/snippet'));
if (typeof extend === 'function') {
extend(parser);
}
const render = parser.render.bind(parser);
parser.render = content => {
let result = render(content)
.replace(/{{/g, '{{')
// 解决 a.md 渲染 /a/index.html 后,图片 ./ 开始的相对路径问题
// css 的图片路径 webpack 会处理
// .replace(/(<img\s+.*src=")(\.\/.*)/mg, '$1.$2');
return result;
};
return parser;
}
module.exports = (text, options = {}) => {
text = String(text);
const parser = getCompiler(options);
let html = parser.render(text);
// 解决{{}}被 san 误当成变量解析的情况
// html = html.replace('{{', '{{');
return html;
};
module.exports.getCompiler = getCompiler;