常见使用 创建Remark插件 setContent import { visit } from "unist-util-visit"; export function setContent() { return function (tree, file) { let content = ""; visit(tree, "paragraph", (node) => { node.children.forEach((child) => { content += child.value; }); }); file.data.astro.frontmatter.strippedContent = content; }; } 转换wiki语法![[]] import { unified } from "unified"; import { remark } from "remark"; import remarkParse from "remark-parse"; import remarkHtml from "remark-html"; import { visit } from "unist-util-visit"; import { toMarkdown } from "mdast-util-to-markdown"; import { gfmFootnoteToMarkdown } from "mdast-util-gfm-footnote"; import { gfmStrikethroughToMarkdown } from "mdast-util-gfm-strikethrough"; import remarkFrontmatter from "remark-frontmatter"; import remarkGfm from "remark-gfm"; const EMBED_LINK_REGEX = /!\[\[([\S]+)\]\]/g; export function remarkObsidianImage(options = { aFolder: "attachments" }) { return function (tree, file) { visit(tree, "paragraph", (node, index, parent) => { const markdown = toMarkdown(node, { extensions: [gfmFootnoteToMarkdown(), gfmStrikethroughToMarkdown], }); const paragraph = String( unified().use(remarkParse).use(remarkHtml).processSync(markdown) ); if (paragraph.match(EMBED_LINK_REGEX)) { const [, fileName] = EMBED_LINK_REGEX.exec(paragraph); const content = `![](${options.aFolder}/${fileName})`; console.log("content", content); const embedTree = remark() .use(remarkFrontmatter) .use(remarkGfm) .parse(content); parent.children.splice(index, 1, embedTree); return node; } }); }; } 在astro.config.ts 中使用。 import { remarkObsidianImage } from "./src/utils/remark-obsidian-image"; export default defineConfig({ markdown: { remarkPlugins: [[remarkObsidianImage, { aFolder: "attachments" }]], }, }); 修改Markdown 一级标题转换为二级标题。 # Hi, Saturn! ## Hi, Saturn! /** * @import {Root} from 'mdast' */ import remarkParse from 'remark-parse' import remarkStringify from 'remark-stringify' import {unified} from 'unified' import {visit} from 'unist-util-visit' const file = await unified() .use(remarkParse) .use(myRemarkPluginToIncreaseHeadings) .use(remarkStringify) .process('# Hi, Saturn!') console.log(String(file)) // => '## Hi, Saturn!' function myRemarkPluginToIncreaseHeadings() { /** * @param {Root} tree */ return function (tree) { visit(tree, function (node) { if (node.type === 'heading') { node.depth++ } }) } } 常用插件 remark-embed-images remark-images remark-admonitions remark-obsidian-callout remark-callout remark-wiki-link:支持双链语法 awesome-remark: 流行插件 remark-toc: 显示目录 remark-obsidian remark-directive:避免从头开始写一个插件 remark-parse:实例化 parser,使 parser 的输出为 mdast。 remark-stringify: 实例化 compiler,使 compiler 的输出为 markdown。 unist-util-visit: 遍历AST 节点。 estree-util-visit: ES 中遍历AST 节点。 unist-builder 扩展阅读 @编写 remark 插件实现自定义扩展语法 @如何编写 unified 插件 (1) remark 如何编写 unified 插件 (2) remark @结构化文本处理利器 unified 生态介绍 - 掘金 @Remark和unified学习与使用 - 掘金