在Hexo中使用Asciidoc格式编写文章
在Hexo中使用Asciidoc格式编写文章
前言
虽然markdown简单易懂, 但是其功能有时非常有限, 例如自定义的表格, mark等, 需要使用三方语法甚至内嵌html来实现, 于是打算使用asciidoc来编写文章, 但是hexo默认不支持asciidoc, 本文记录hexo适配asciidoc的过程.
安装asciidoc
虽然已经有了 hexo-renderer-asciidoc 这个插件, 但是有几点会导致这个插件并不好用
此插件使用的代码高亮是
hexo-utils提供的, 但是它的代码高亮并不会读配置文件, 于是会和主题配置格格不入asciidoc需要引入额外的css, 但是这个插件并未限定作用域. 如果导入asciidoc的css会导致全局生效, 影响其他md的文章
所需要依赖
{
"asciidoctor": "^3.0.4",
"cheerio": "1.0.0-rc.12",
}Tip | 请酌情对依赖进行升级 |
编写renderer
在hexo的根目录下创建一个 scripts 文件夹, 并创建一个 asciidoc-renderer.js 文件, 内容如下
const asciidoctor = require("asciidoctor")({
runtime: {
platform: "node",
engine: "v8",
}
});
const cheerio = require("cheerio");
const p = require("path");
const fs = require("fs");
function wrapContainer(html) {
return `<div class="asciidoc-container">${html}</div>`;
}
function highlight(code, lang) {
return hexo.extend.highlight.exec(hexo.config.syntax_highlighter, {
context: hexo,
args: [code, {
lang,
lines_length: code.split("\n").length,
}],
});
}
class HexoSyntaxHighlighter {
constructor(name, backend, opts) {
this.name = name
}
format(node, lang, opts) {
return highlight(node.getSource(), lang);
}
}
function renderer(data, options) {
// 注册高亮
asciidoctor.SyntaxHighlighter.register("hexo-highlighter", HexoSyntaxHighlighter);
// 修正include
asciidoctor.Extensions.register(function () {
this.includeProcessor(function () {
const self = this;
self.handles(function (target) {
return true;
});
self.process(function (doc, reader, target, attrs) {
const postDir = p.dirname(data.path);
const includePath = p.join(postDir, target);
const content = fs.readFileSync(includePath, "utf8");
return reader.pushInclude(content, target, target, 1, attrs);
})
})
});
const html = asciidoctor.convert(data.text, {
doctype: "article",
safe: "server",
attributes: {
"source-highlighter": "hexo-highlighter",
"table-grid": "rows",
},
});
const $ = cheerio.load(wrapContainer(html), {
decodeEntities: false,
});
// 修正图片路径
if (hexo.config.post_asset_folder) {
const blogName = p.basename(data.path, p.extname(data.path));
$("img").each((_, elem) => {
let src = $(elem).attr("src");
if (!src.startsWith(blogName)) {
return;
}
src = p.basename(src);
$(elem).attr("src", src);
});
}
return $.html();
}
hexo.extend.renderer.register("ad", "html", renderer, true);
hexo.extend.renderer.register("adoc", "html", renderer, true);
hexo.extend.renderer.register("asciidoc", "html", renderer, true);
const css = hexo.extend.helper.get("css").bind(hexo);
hexo.extend.injector.register("body_end", () => {
return css("/css/asciidoc-renderer.css");
});
编写css
由于asciidoc有一些样式, 这些样式需要引入 (当然不引入也可以)
将
@asciidoctor/core下的asciidoctor.css复制到source/css下在
source/css下创建一个asciidoc-renderer.less文件, 内容如下安装
hexo-renderer-less插件注入
asciidoc-renderer.css到主题中
.asciidoc-container {
@import (less) "asciidoctor.css";
}在 asciidoc-renderer.js 下面添加
const css = hexo.extend.helper.get("css").bind(hexo)
hexo.extend.injector.register('body_end', () => {
return css("/css/asciidoc-renderer.css")
})asciidoctor.css里有些主题和博客里的主题对不上, 我删除了部分样式例如
所有的
font-family所有的
font-color大部分
background-color
魔改Hexo
Warning | Hexo可能已经修复此问题, 请追踪Issue: #5523 |
由于Hexo的 这行代码, 导致在开启 post_asset_folder 的情况下, 只能渲染一种格式的文章, 于是需要魔改Hexo
在对应的代码处修改为
if (result.renderable && ctx.config.post_asset_folder) {
result.renderable = (extname(ctx.config.new_post_name) === extname(path))
if (!Array.isArray(ctx.config.post_extension) || ctx.config.post_extension.length === 0) {
ctx.log.debug('post_asset_folder is set, but no post_extension is defined. Defaulting to new_post_name extension.')
result.renderable = (extname(ctx.config.new_post_name) === extname(path))
} else {
result.renderable = ctx.config.post_extension.includes(extname(path).slice(1))
}
}在 _config.yml 中添加
post_extension: [ 'md', "adoc" ]即可支持md和adoc的混合渲染