# Markdown 自渲染


一个很有意思的东西。

<!--more-->

水一篇博文，markdown 自渲染。

## 缘起

这个主意来自于 Markdeep。Markdeep 是挺好用的一个项目，是一个能让纯文本文档在浏览器中直接渲染为美观 HTML 的轻量级工具，无需安装任何软件或插件，只需一行代码即可将 Markdown 文件转化为自包含的网页。

- https://casual-effects.com/markdeep/

官网有个例子，大概这样 example.md.html

````md
**Example**

Welcome to **Markdeep**. It's the simple way to write
plain text with _style_.

```
 .---------.      .------.      .---------. 
 |  Write  +--+->|  Edit  +-+-->|  Share! |
 '---------' |    '------'   |  '---------' 
              '-------------'             
```

# Plan

1. Download [starter.md.html](templates/starter/starter.md.html)
2. Edit in any code or text editor
3. Double click to preview in a browser
4. Email, upload, or git commit to share

# More

Learn more at https://casual-effects.com/markdeep.

                                 
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>
````

一个 markdown 文件，加载 js 把自己渲染成 html。格格不入的就这一行：`<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js?"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script>`。

虽然看着长，但是确实是一行。前面纯 Markdown。然后文件名是 `starter.md.html`。

虽然不是规范的 HTML 但是能跑，哦，感谢浏览器宽容。

## 实现

不过我试了一下 Markdeep 后，发现难改样式。加个切换黑暗模式的功能费点劲，没有预留这个功能的样子。不过也可以理解，毕竟已经是老项目了。所以我自己也搞了一个版本。这个小玩意儿应该算是我笔记网站项目的一部分。使用了几个库： Alpine + AsyncAlpine + Marked + Medium Zoom + Water.css + Basscss

**代码在这**
- https://codeberg.org/kkbt/KNote/src/branch/main/src/pages/KMark

流程也很简单。读取内容，切分，渲染。其实是用原生 js 就能很好的完成功能，还轻量。然后加个 classless css 即可。不过这个小玩意儿算是我的笔记项目的一部分。这笔记软件，加上 Alpine.js 增加了很有趣的拓展功能。于是我实现的自渲染也用上了这一堆东西。

现在结果就是，虽然不能直接像 mdx 一样引入 jsx 使用组件。但是可以引入 Alpine.js “组件”。大概下面这样的形式。这总比 markdown 中写 HTML 要方便。而且还有 AsyncAlpine 可用。

```js
km.counter2 = function () {
    return {
        count: 0,
        init() {
            this.$root.innerHTML = `<button x-on:click="count--">Decrement</button><span x-text="count" class="px-1"></span>`;
            Alpine.initTree(this.$root);
        },
        // 传入 args
        kInit(...args) {
            console.log("kInit", args);
        }
    }
}
```

然后我增加了个正则表达式，这样算是与 obsidian 的语法兼容了，大概。现在

```md
![[km.counter|"计数器"]]
![[km.counter|]]
![[km.counter]]

![[km.counter2]]
``` 

这样的写法会被处理为 Alpine.js 的组件 HTML 。

这次本来想介绍一下我的笔记网站来着。但是我记着我好像发过文。最近就是加了个库，js 拆成几个 ts，然后用 Bun 打包。更方便维护拓展了。倒也没什么可说的。

不过 bun 处理这种小项目，运行单 HTML 或 Markdown 文件倒是很方便，开箱即用的 TS。

```bash
# 开发
bun src/pages/KMark/KMark.md.html --port=1313
# 运行 markdown
bun -e "await Bun.write('./temp.html', await Bun.file(process.argv[1]).text()); Bun.spawn(['bun', 'run', './temp.html'], { stdio: ['inherit', 'inherit', 'inherit'] })" ./KMark.md
# 创建临时 html 并使用默认程序打开
bun -e "await Bun.write('./temp.html', await Bun.file(process.argv[1]).text()); Bun.spawn(['cmd', '/c', 'temp.html'])" ./KMark.md
```

以上。
