在Hexo中使用Asciidoc格式编写文章

在Hexo中使用Asciidoc格式编写文章

前言

虽然markdown简单易懂, 但是其功能有时非常有限, 例如自定义的表格, mark等, 需要使用三方语法甚至内嵌html来实现, 于是打算使用asciidoc来编写文章, 但是hexo默认不支持asciidoc, 本文记录hexo适配asciidoc的过程.

安装asciidoc

虽然已经有了 hexo-renderer-asciidoc 这个插件, 但是有几点会导致这个插件并不好用

  1. 此插件使用的代码高亮是 hexo-utils 提供的, 但是它的代码高亮并不会读配置文件, 于是会和主题配置格格不入

  2. asciidoc需要引入额外的css, 但是这个插件并未限定作用域. 如果导入asciidoc的css会导致全局生效, 影响其他md的文章

所需要依赖

1
2
3
4
5
{
"asciidoctor": "^3.0.4",
"cheerio": "1.0.0-rc.12",
"entities": "^5.0.0"
}
Tip
请酌情对依赖进行升级

编写renderer

在hexo的根目录下创建一个`scripts`文件夹, 并创建一个 asciidoc-renderer.js 文件, 内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
const asciidoctor = require('asciidoctor')()
const entities = require('entities')
const cheerio = require('cheerio')
const p = require('path')
const fs = require('fs')

function wrapContainer(html) {
return `<div class="asciidoc-container">${html}</div>`
}


function renderer(data, options) {
const extension_registry = asciidoctor.Extensions.create()
extension_registry.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=html-pipeline'
],
extension_registry: extension_registry,
})


const $ = cheerio.load(wrapContainer(html), {
decodeEntities: false
})

$('pre.highlight').each((_index, elem) => {
const codeNode = elem.childNodes[0]
const lang = codeNode.attribs['data-lang']
const sourceCodeText = entities.decodeXML($(codeNode).text())
const content = hexo.extend.highlight.exec(hexo.config.syntax_highlighter, {
context: hexo,
args: [sourceCodeText, {
lang,
lines_length: sourceCodeText.split('\n').length
}]
})
$(elem).replaceWith(content)
})

return $.html()
.replace(/{/g, '{')
.replace(/}/g, '}')
}

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有一些样式, 这些样式需要引入 (当然不引入也可以)

  1. @asciidoctor/core 下的 asciidoctor.css 复制到 source/css

  2. source/css 下创建一个 asciidoc-renderer.less 文件, 内容如下

  3. 安装 hexo-renderer-less 插件

  4. 注入 asciidoc-renderer.css 到主题中

1
2
3
.asciidoc-container {
@import (less) "asciidoctor.css";
}

asciidoc-renderer.js 下面添加

1
2
3
4
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

在对应的代码处修改为

1
2
3
4
5
6
7
8
9
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 中添加

1
post_extension: [ 'md', "adoc" ]

即可支持md和adoc的混合渲染


在Hexo中使用Asciidoc格式编写文章
https://simonkimi.githubio.io/2024/07/27/在Hexo中使用Asciidoc格式编写文章/
作者
simonkimi
发布于
2024年7月27日
许可协议