feat: support custom theme.
feat: support to set default theme color and css variable prefix options.
This commit is contained in:
parent
b3068350db
commit
c03510a8a7
14
README.md
14
README.md
@ -1,4 +1,6 @@
|
|||||||
# Hexo-Highlight-Shiki
|
# Hexo-Highlight-Shiki
|
||||||
|
![NPM Version](https://img.shields.io/npm/v/hexo-highlighter-shiki?style=flat)
|
||||||
|
|
||||||
English丨[简体中文](README_zh-CN.md)
|
English丨[简体中文](README_zh-CN.md)
|
||||||
|
|
||||||
A hexo plugin to use [Shiki](https://github.com/shikijs/shiki) as code block highlighter.
|
A hexo plugin to use [Shiki](https://github.com/shikijs/shiki) as code block highlighter.
|
||||||
@ -33,11 +35,15 @@ The complete configuration is as follows:
|
|||||||
```yaml
|
```yaml
|
||||||
shiki:
|
shiki:
|
||||||
theme: one-dark-pro # see https://shiki.style/themes for supported themes.
|
theme: one-dark-pro # see https://shiki.style/themes for supported themes.
|
||||||
line_number: false
|
line_number: false # default: false
|
||||||
strip_indent: true
|
strip_indent: true # default: true
|
||||||
tab_replace: " "
|
tab_replace: " " # default: " "
|
||||||
pre_style: true # Preserve the style of the <pre> tag, i.e., the theme's `background-color`.
|
pre_style: true # Preserve the style of the <pre> tag, i.e., the theme's `background-color`. default: true
|
||||||
|
default_color: light # Only take effect when using multiple themes. default: light
|
||||||
|
css_variable_prefix: --shiki- # Only take effect when using multiple themes. default: --shiki-
|
||||||
additional:
|
additional:
|
||||||
|
themes: # List of the TextMate theme json to be added.
|
||||||
|
- path/to/theme.json
|
||||||
langs: # List of the TextMate grammar json of languages to be added.
|
langs: # List of the TextMate grammar json of languages to be added.
|
||||||
- path/to/lang_grammar.json
|
- path/to/lang_grammar.json
|
||||||
lang_alias: # List of the alias of languages.
|
lang_alias: # List of the alias of languages.
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# Hexo-Highlight-Shiki
|
# Hexo-Highlight-Shiki
|
||||||
|
![NPM Version](https://img.shields.io/npm/v/hexo-highlighter-shiki?style=flat)
|
||||||
|
|
||||||
[English](README.md)丨简体中文
|
[English](README.md)丨简体中文
|
||||||
|
|
||||||
一个使用 [Shiki](https://github.com/shikijs/shiki) 作为代码块高亮器的 Hexo 插件。
|
一个使用 [Shiki](https://github.com/shikijs/shiki) 作为代码块高亮器的 Hexo 插件。
|
||||||
@ -31,15 +33,18 @@ shiki:
|
|||||||
完整配置如下:
|
完整配置如下:
|
||||||
```yaml
|
```yaml
|
||||||
shiki:
|
shiki:
|
||||||
theme: "one-dark-pro" # Theme, see https://shiki.style/themes for supported themes.
|
theme: "one-dark-pro" # 主题,请参阅 https://shiki.style/themes 以获取支持的主题列表。
|
||||||
line_number: false
|
line_number: false
|
||||||
strip_indent: true
|
strip_indent: true
|
||||||
tab_replace: " "
|
tab_replace: " "
|
||||||
pre_style: true # Preserve the style of the <pre> tag, i.e., the theme's `background-color`.
|
pre_style: true # 保留 <pre> 标签的样式,即主题的 `background-color`。
|
||||||
|
default_color: light # 仅在同时使用多个主题时生效。默认值:light
|
||||||
|
css_variable_prefix: --shiki- # 仅在同时使用多个主题时生效。默认值:--shiki-
|
||||||
additional:
|
additional:
|
||||||
langs: # List of the TextMate grammar json of languages to be added.
|
themes: # 要添加的主题的 TextMate 主题 json 列表。
|
||||||
|
langs: # 要添加的语言的 TextMate 语法 json 列表。
|
||||||
- path/to/lang_grammar.json
|
- path/to/lang_grammar.json
|
||||||
lang_alias: # List of the alias of languages.
|
lang_alias: # 语言的别名列表。
|
||||||
your_alias1: lang_name1
|
your_alias1: lang_name1
|
||||||
your_alias2: lang_name2
|
your_alias2: lang_name2
|
||||||
```
|
```
|
||||||
|
34
src/main.ts
34
src/main.ts
@ -1,5 +1,5 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
import { bundledLanguages, createHighlighter, ShikiTransformer } from "shiki";
|
import { bundledLanguages, bundledThemes, createHighlighter, ShikiTransformer } from "shiki";
|
||||||
import type Hexo from "hexo";
|
import type Hexo from "hexo";
|
||||||
import { HighlightOptions } from "hexo/dist/extend/syntax_highlight";
|
import { HighlightOptions } from "hexo/dist/extend/syntax_highlight";
|
||||||
import { stripIndent, htmlTag } from "hexo-util";
|
import { stripIndent, htmlTag } from "hexo-util";
|
||||||
@ -13,22 +13,41 @@ export async function init(hexo: Hexo) {
|
|||||||
strip_indent: true,
|
strip_indent: true,
|
||||||
tab_replace: " ",
|
tab_replace: " ",
|
||||||
pre_style: true,
|
pre_style: true,
|
||||||
|
default_color: "light",
|
||||||
|
css_variable_prefix: "--shiki-",
|
||||||
additional: {
|
additional: {
|
||||||
|
themes: [],
|
||||||
langs: [],
|
langs: [],
|
||||||
lang_alias: {},
|
lang_alias: {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
hexo.config.shiki || {}
|
hexo.config.shiki || {}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 处理自定义语言 json
|
||||||
let additional_langs = [];
|
let additional_langs = [];
|
||||||
if (config.additional.langs)
|
if (config.additional.langs)
|
||||||
for (const extra_lang of [].concat(config.additional.langs)) {
|
for (const extra_lang of [].concat(config.additional.langs)) {
|
||||||
additional_langs.push(JSON.parse(readFileSync(extra_lang, "utf8")));
|
additional_langs.push(JSON.parse(readFileSync(extra_lang, "utf8")));
|
||||||
}
|
}
|
||||||
const langs = [...Object.keys(bundledLanguages), ...additional_langs];
|
const langs = [...Object.keys(bundledLanguages), ...additional_langs];
|
||||||
|
|
||||||
|
// 处理自定义主题 json
|
||||||
|
let additional_themes = [];
|
||||||
|
if (config.additional.themes)
|
||||||
|
for (const extra_theme of [].concat(config.additional.themes)) {
|
||||||
|
additional_themes.push(JSON.parse(readFileSync(extra_theme, "utf8")));
|
||||||
|
}
|
||||||
|
const themes = additional_themes.concat(
|
||||||
|
(typeof config.theme === "string" ? [config.theme] : Object.values(config.theme)).filter(
|
||||||
|
(theme) => theme in bundledThemes
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 创建 highlighter
|
||||||
let highlighter_options = {
|
let highlighter_options = {
|
||||||
langs: langs,
|
langs: langs,
|
||||||
themes: typeof config.theme === "string" ? [config.theme] : Object.values(config.theme),
|
themes: themes,
|
||||||
};
|
};
|
||||||
if (config.additional.lang_alias && Object.keys(config.additional.lang_alias).length > 0) {
|
if (config.additional.lang_alias && Object.keys(config.additional.lang_alias).length > 0) {
|
||||||
highlighter_options["langAliases"] = config.additional.lang_alias;
|
highlighter_options["langAliases"] = config.additional.lang_alias;
|
||||||
@ -45,6 +64,7 @@ export async function init(hexo: Hexo) {
|
|||||||
ansi: true,
|
ansi: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const hexoHighlighter = (code: string, options: HighlightOptions) => {
|
const hexoHighlighter = (code: string, options: HighlightOptions) => {
|
||||||
var code = config.strip_indent ? (stripIndent(code) as string) : code;
|
var code = config.strip_indent ? (stripIndent(code) as string) : code;
|
||||||
code = config.tab_replace ? code.replace(/\t/g, config.tab_replace) : code;
|
code = config.tab_replace ? code.replace(/\t/g, config.tab_replace) : code;
|
||||||
@ -57,7 +77,7 @@ export async function init(hexo: Hexo) {
|
|||||||
|
|
||||||
// 处理代码块语法高亮
|
// 处理代码块语法高亮
|
||||||
let pre = "";
|
let pre = "";
|
||||||
const transformer = (): ShikiTransformer => {
|
const transformerMarkedLine = (): ShikiTransformer => {
|
||||||
return {
|
return {
|
||||||
line(node, line) {
|
line(node, line) {
|
||||||
if (options.mark && options.mark.includes(line)) {
|
if (options.mark && options.mark.includes(line)) {
|
||||||
@ -71,13 +91,15 @@ export async function init(hexo: Hexo) {
|
|||||||
pre = highlighter.codeToHtml(code, {
|
pre = highlighter.codeToHtml(code, {
|
||||||
lang,
|
lang,
|
||||||
theme: config.theme,
|
theme: config.theme,
|
||||||
transformers: [transformer()],
|
transformers: [transformerMarkedLine()],
|
||||||
});
|
});
|
||||||
else
|
else
|
||||||
pre = highlighter.codeToHtml(code, {
|
pre = highlighter.codeToHtml(code, {
|
||||||
lang,
|
lang,
|
||||||
themes: config.theme,
|
themes: config.theme,
|
||||||
transformers: [transformer()],
|
transformers: [transformerMarkedLine()],
|
||||||
|
defaultColor: config.default_color,
|
||||||
|
cssVariablePrefix: config.css_variable_prefix,
|
||||||
});
|
});
|
||||||
// 删除多余内容
|
// 删除多余内容
|
||||||
pre = pre.replace(/<pre[^>]*>/, (match) => {
|
pre = pre.replace(/<pre[^>]*>/, (match) => {
|
||||||
@ -97,7 +119,7 @@ export async function init(hexo: Hexo) {
|
|||||||
(options.line_number || true) && // 代码块中未设置不显示行号
|
(options.line_number || true) && // 代码块中未设置不显示行号
|
||||||
(options.line_threshold || 0) < options.lines_length; // 代码行数超过阈值
|
(options.line_threshold || 0) < options.lines_length; // 代码行数超过阈值
|
||||||
if (show_line_number) {
|
if (show_line_number) {
|
||||||
const firstLine = options.firstLine || 1
|
const firstLine = options.firstLine || 1;
|
||||||
for (let i = firstLine, len = code.split("\n").length + firstLine; i < len; i++) {
|
for (let i = firstLine, len = code.split("\n").length + firstLine; i < len; i++) {
|
||||||
numbers += htmlTag("span", { class: "line" }, `${i}`, false) + "<br>";
|
numbers += htmlTag("span", { class: "line" }, `${i}`, false) + "<br>";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user