simple-is-awesome / simple

A minimalist blogging system built specifically for bloggers.
https://demo.njxzc.top
MIT License
1 stars 1 forks source link

feat: 代码块高亮 #5

Closed real-jiakai closed 1 year ago

real-jiakai commented 1 year ago

使用remark-prism来高亮代码块,效果不错。但是中间存在一些不优雅之处。

image

1、部分实现代码

import { remark } from 'remark';
import html from 'remark-html';
import gfm from 'remark-gfm';
import prism from 'remark-prism';

# remark-gfm插件使得remark可以处理github风格的markdown语法
# 使用rehype库的remark-html插件将Markdown转换为HTML。
# sanitize: false表示不对生成的HTML进行清理,这意味着输出的HTML中可能包含一些不安全的内容。
# 在处理不受信任的用户输入时,应慎用此选项。
# 使用remark-prism插件对代码块进行语法高亮
# 使用自定义插件处理特殊字符
const contentHtml = await remark()
  .use(gfm)
  .use(html, { sanitize: false })
  .use(prism)
  .use(retoreSpecialCharacters)
  .process(matterResult.content)
  .then((processedContent) => processedContent.toString());
import 'styles/globals.css'
+ import 'public/css/prism-night-owl.css'

export default function App({ Component, pageProps }) {
    return <Component {...pageProps} />
}

2、弊端与问题

2.1、弊端

使用remark-html插件将markdown文件转换为html时,默认情况下会将一些特殊符号,转换为html实体(entity),如将>转换为&gt;<转换为&lt;

因此如果没有自定义的retoreSpecialCharacters处理函数,则在markdown转换为html后,原本包裹在markdown代码块语法(``)中的代码块中的特殊字符,如>`标注符号会变为\>

原本被纯文本代码块包裹的代码中出现特殊字符转为了html实体:

image

2.2、问题

remark-html插件中提供了一个选项sanitize,将其值设置为false时,危险的原始html代码不会被转换。但是我设置后,发现依然没解决此问题。

与此同时,remark-html仓库中的一个issue—Sanitize example does not work as described #24引起了我的注意。仓库的维护者是这样回复的:

image

作者说,要想实现对于特殊字符转换的控制,最好采用retype库中的插件。作者的意思是要想更加精细地将markdown转为html,以避免特殊字符转换,最好使用retype库及其插件来处理,remark-html插件的细粒度不够。

注:remark库是一个用于解析和处理markdown的库,retype是一个用于解析和处理HTML的库。

3、补充

其余一些类似的issue:

4、参考资料

real-jiakai commented 1 year ago

既然remark-html对于特殊字符转换的控制做不到精细,那就换retype库来处理markdown文件。

首先来明确一下remark、retype以及unified之间的关系。

以上定义源自 unifiedremarkretype的github仓库简介。

real-jiakai commented 1 year ago
const contentHtml = unified()
    .use(remarkParse)
    .use(gfm)
    .use(remark2rehype, { allowDangerousHtml: true })
    .use(rehypeRaw)
    .use(rehypeStringify)
    .use(rehypePrism)
    .use(rehypeSlug)
    .use(rehypeAutolinkHeadings)
    .process(matterResult.content)
    .then((processedContent) => processedContent.toString())

关于这段处理函数的chatgpt4解释:

image