Skip to content

Commit

Permalink
Merge 78e187d into b385a94
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW committed Feb 9, 2020
2 parents b385a94 + 78e187d commit 635a31f
Show file tree
Hide file tree
Showing 8 changed files with 542 additions and 100 deletions.
6 changes: 6 additions & 0 deletions lib/hexo/default_config.js
Expand Up @@ -48,6 +48,12 @@ module.exports = {
wrap: true,
hljs: false
},
prismjs: {
enable: false,
preprocess: true,
line_number: true,
tab_replace: ''
},
// Category & Tag
default_category: 'uncategorized',
category_map: {},
Expand Down
89 changes: 57 additions & 32 deletions lib/plugins/filter/before_post_render/backtick_code_block.js
@@ -1,51 +1,35 @@
'use strict';

const stripIndent = require('strip-indent');
const { highlight } = require('hexo-util');
let highlight, prismHighlight;

const rBacktick = /^((?:[^\S\r\n]*>){0,3}[^\S\r\n]*)(`{3,}|~{3,}) *(.*) *\n([\s\S]+?)\s*\2(\n+|$)/gm;
const rAllOptions = /([^\s]+)\s+(.+?)\s+(https?:\/\/\S+|\/\S+)\s*(.+)?/;
const rLangCaption = /([^\s]+)\s*(.+)?/;

function backtickCodeBlock(data) {
const config = this.config.highlight || {};
if (!config.enable) return;
data.content = data.content.replace(rBacktick, ($0, start, $2, _args, content, end) => {
const args = _args.split('=').shift();

const options = {
hljs: config.hljs,
autoDetect: config.auto_detect,
gutter: config.line_number,
tab: config.tab_replace,
wrap: config.wrap
};

if (options.gutter) {
config.first_line_number = config.first_line_number || 'always1';
if (config.first_line_number === 'inline') {
const hljsCfg = this.config.highlight || {};
const prismCfg = this.config.prismjs || {};

// setup line number by inline
_args = _args.replace('=+', '=');
options.gutter = _args.includes('=');
// neither highlight or prismjs is enabled, return directly.
if (!hljsCfg.enable && !prismCfg.enable) return;

// setup fiestLineNumber;
options.firstLine = options.gutter ? _args.split('=')[1] || 1 : 0;
}
}
data.content = data.content.replace(rBacktick, ($0, start, $2, _args, content, end) => {
// Extrace langauge and caption of code blocks
const args = _args.split('=').shift();
let lang, caption;

if (args) {
const match = rAllOptions.exec(args) || rLangCaption.exec(args);


if (match) {
options.lang = match[1];
lang = match[1];

if (match[2]) {
options.caption = `<span>${match[2]}</span>`;
caption = `<span>${match[2]}</span>`;

if (match[3]) {
options.caption += `<a href="${match[3]}">${match[4] ? match[4] : 'link'}</a>`;
caption += `<a href="${match[3]}">${match[4] ? match[4] : 'link'}</a>`;
}
}
}
Expand All @@ -59,11 +43,52 @@ function backtickCodeBlock(data) {
content = (content + paddingOnEnd).replace(regexp, '').replace(/\n$/, '');
}

content = highlight(stripIndent(content), options)
.replace(/{/g, '&#123;')
.replace(/}/g, '&#125;');
// Since prismjs have better performance, so prismjs should have higher priority.
if (prismCfg.enable) {
if (!prismHighlight) prismHighlight = require('hexo-util').prismHighlight;

const options = {
lineNumber: prismCfg.line_number,
tab: prismCfg.tab_replace,
isPreprocess: prismCfg.preprocess,
lang
};

content = prismHighlight(stripIndent(content), options);
} else if (hljsCfg.enable) {
if (!highlight) highlight = require('hexo-util').highlight;

const options = {
hljs: hljsCfg.hljs,
autoDetect: hljsCfg.auto_detect,
gutter: hljsCfg.line_number,
tab: hljsCfg.tab_replace,
wrap: hljsCfg.wrap,
lang,
caption
};

if (options.gutter) {
hljsCfg.first_line_number = hljsCfg.first_line_number || 'always1';
if (hljsCfg.first_line_number === 'inline') {

// setup line number by inline
_args = _args.replace('=+', '=');
options.gutter = _args.includes('=');

// setup firstLineNumber;
options.firstLine = options.gutter ? _args.split('=')[1] || 1 : 0;
}
}

content = highlight(stripIndent(content), options);
}

return `${start}<escape>${content}</escape>${end}`;
return start
+ '<escape>'
+ content.replace(/{/g, '&#123;').replace(/}/g, '&#125;')
+ '</escape>'
+ end;
});
}

Expand Down
87 changes: 78 additions & 9 deletions lib/plugins/tag/code.js
Expand Up @@ -2,7 +2,7 @@

// Based on: https://raw.github.com/imathis/octopress/master/plugins/code_block.rb

const { escapeHTML, highlight } = require('hexo-util');
const { escapeHTML, highlight, prismHighlight } = require('hexo-util');
const stripIndent = require('strip-indent');

const rCaptionUrlTitle = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)\s+(.+)/i;
Expand Down Expand Up @@ -35,7 +35,6 @@ const rWrap = /\s*wrap:(\w+)/i;
*/

function getHighlightOptions(config, arg) {

let lang = '';
if (rLang.test(arg)) {
arg = arg.replace(rLang, (match, _lang) => {
Expand Down Expand Up @@ -121,29 +120,99 @@ function getHighlightOptions(config, arg) {
};
}

function getPrismjsOptions(config, arg) {
let lang;
if (rLang.test(arg)) {
arg = arg.replace(rLang, (match, _lang) => {
lang = _lang;
return '';
});
}

let line_number = config.line_number;
if (rLineNumber.test(arg)) {
arg = arg.replace(rLineNumber, (match, _line_number) => {
line_number = _line_number === 'true';
return '';
});
}

let first_line = 1;
if (rFirstLine.test(arg)) {
arg = arg.replace(rFirstLine, (match, _first_line) => {
first_line = _first_line;
return '';
});
}

if (rWrap.test(arg)) arg = arg.replace(rWrap, '');

let mark = [];
if (rMark.test(arg)) {
arg = arg.replace(rMark, (match, _mark) => {
mark = _mark.split(',').reduce((prev, cur) => {
if (/-/.test(cur)) {
let a = Number(cur.substr(0, cur.indexOf('-')));
let b = Number(cur.substr(cur.indexOf('-') + 1));
if (b < a) { // switch a & b
const temp = a;
a = b;
b = temp;
}

for (; a <= b; a++) {
prev.push(a);
}

return prev;
}

prev.push(Number(cur));
return prev;
}, []);

return '';
});
}

return {
lang,
firstLine: first_line,
lineNumber: line_number,
mark,
tab: config.tab_replace,
isPreprocess: config.preprocess
};
}

module.exports = ctx => function codeTag(args, content) {
let arg = args.join(' ');
const config = ctx.config.highlight || {};
let enable = config.enable;
const hljsCfg = ctx.config.highlight || {};
const prismjsCfg = ctx.config.prismjs || {};

let _hljsEnable = hljsCfg.enable;

if (rHighlight.test(arg)) {
arg = arg.replace(rHighlight, (match, _enable) => {
enable = _enable === 'true';
_hljsEnable = _enable === 'true';
return '';
});
}

if (!enable) {
if (!_hljsEnable && !prismjsCfg.enable) {
content = escapeHTML(content);
return `<pre><code>${content}</code></pre>`;
}

content = stripIndent(content);

content = highlight(content, getHighlightOptions(config, arg));
if (prismjsCfg.enable) {
content = prismHighlight(content, getPrismjsOptions(prismjsCfg, arg));
} else {
content = highlight(content, getHighlightOptions(hljsCfg, arg));
}

content = content.replace(/{/g, '&#123;')
.replace(/}/g, '&#125;');
content = content.replace(/{/g, '&#123;').replace(/}/g, '&#125;');

return content;
};
34 changes: 22 additions & 12 deletions lib/plugins/tag/include_code.js
Expand Up @@ -3,7 +3,7 @@
const fs = require('hexo-fs');
const { basename, extname, join } = require('path');
const stripIndent = require('strip-indent');
const { highlight } = require('hexo-util');
const { highlight, prismHighlight } = require('hexo-util');

const rCaptionTitleFile = /(.*)?(?:\s+|^)(\/*\S+)/;
const rLang = /\s*lang:(\w+)/i;
Expand All @@ -18,7 +18,6 @@ const rTo = /\s*to:(\d+)/i;
*/

module.exports = ctx => function includeCodeTag(args) {
const config = ctx.config.highlight || {};
let codeDir = ctx.config.code_dir;
let arg = args.join(' ');

Expand Down Expand Up @@ -48,22 +47,31 @@ module.exports = ctx => function includeCodeTag(args) {

const path = match[2];

// If the title is not defined, use file name instead
const title = match[1] || basename(path);

// If the language is not defined, use file extension instead
lang = lang || extname(path).substring(1);

const src = join(ctx.source_dir, codeDir, path);

// If the title is not defined, use file name instead
const title = match[1] || basename(path);
const caption = `<span>${title}</span><a href="${ctx.config.root}${codeDir}${path}">view raw</a>`;

const options = {
const hljsCfg = ctx.config.highlight || {};
const prismjsCfg = ctx.config.prismjs || {};

const hljsOptions = {
lang,
caption,
gutter: config.line_number,
hljs: config.hljs,
tab: config.tab_replace
gutter: hljsCfg.line_number,
hljs: hljsCfg.hljs,
tab: hljsCfg.tab_replace
};

const prismjsOptions = {
lang,
lineNumber: prismjsCfg.line_number,
tab: prismjsCfg.tab_replace,
isPreprocess: prismjsCfg.preprocess
};

return fs.exists(src).then(exist => {
Expand All @@ -75,10 +83,12 @@ module.exports = ctx => function includeCodeTag(args) {
const lines = code.split('\n');
code = lines.slice(from, to).join('\n').trim();

if (!config.enable) {
return `<pre><code>${code}</code></pre>`;
if (prismjsCfg.enable) {
return prismHighlight(code, prismjsOptions);
} else if (hljsCfg.enable) {
return highlight(code, hljsOptions);
}

return highlight(code, options);
return `<pre><code>${code}</code></pre>`;
});
};
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -48,7 +48,7 @@
"hexo-fs": "^2.0.0",
"hexo-i18n": "^1.0.0",
"hexo-log": "^1.0.0",
"hexo-util": "^1.8.1",
"hexo-util": "github:hexojs/hexo-util",
"js-yaml": "^3.12.0",
"lodash": "^4.17.11",
"micromatch": "^4.0.2",
Expand Down

0 comments on commit 635a31f

Please sign in to comment.