@mini-dev/markdown-math
v0.0.1
Published
Math 插件包(轻):math/inlineMath 节点 → md-math 组件段;MathJax 渲染拆到重包 @mini-dev/markdown-math-render,经 require.async 跨分包按需加载
Maintainers
Readme
@mini-dev/markdown-math
@mini-dev/markdown-core 的数学公式轻插件包 —— math 块定向到 md-math 组件段(原生 <image>),inlineMath 定向到 rich-text 内联 <img>(SVG dataUri,嵌段落内)。MathJax 渲染(TeX→SVG)拆到重包 @mini-dev/markdown-math-render,本包不含 mathjax(dist 仅几 KB)。
微信小程序 rich-text 不支持 position:absolute、也不保证 wx.loadFontFace 生效,KaTeX-HTML 路线在复杂公式上会布局塌缩、字形丢失;SVG 路线(字形路径内嵌进 SVG、无字体/定位依赖)绕开了这两个问题,组件用 <image> 展示。
1. 两条加载路径(二选一)
重包 @mini-dev/markdown-math-render 怎么进运行时,取决于是否用分包:
| | 同步 mathRenderModule(不分包) | 异步 resolveMathSvgModule(分包) |
|---|---|---|
| mathjax 位置 | 主包 miniprogram_npm | pkg-math 分包 |
| 主包 2MB 预算 | 占 ~1.5 MB(75%) | 零增长 |
| 首公式 | 模块已在主包,同步出图 | 进首公式时下载 pkg-math,ctx.defer 占位→升级 |
| 闪烁 | 无 | 首公式一次占位→SVG 升级 |
| 配置 | 默认「构建 npm」 | subPackages + packNpmManually + require.async |
设计细节与真机约束见 ../../docs/design/rfcs/math-subpackage-async.md。
2. 安装
npm i @mini-dev/markdown-core @mini-dev/markdown-adapter-wechat
npm i @mini-dev/markdown-math @mini-dev/markdown-math-render小程序侧执行「工具 → 构建 npm」(读 "miniprogram": "dist/cjs")。不分包时两个包默认都构建进主包 miniprogram_npm;分包时按 RFC §5.2 用 packNpmRelationList 把重包构建进 pkg-math、轻包进 pkg-doc。
3. 用法
3.1 同步路径(不分包,推荐给精简 app)
const { createMarkdown, createMathBlockPlugin } = require('@mini-dev/markdown-core');
const { createWeChatAdapter } = require('@mini-dev/markdown-adapter-wechat');
const { createMathPlugin } = require('@mini-dev/markdown-math');
const { renderMathSvg, svgToDataUri } = require('@mini-dev/markdown-math-render');
const md = createMarkdown();
md.use(createMathBlockPlugin()); // core:解析 $$…$$ / $…$ → math 节点
md.use(createMathPlugin({ mathRenderModule: { renderMathSvg, svgToDataUri } })); // 同步出图,零 defer/闪烁
const adapter = createWeChatAdapter();
adapter.registry.register('md-math', '/components/md-math/index');mathjax 内联进主包
miniprogram_npm,占主包 2MB 预算的 ~75%。总主包超 2MB 时改用分包路径。
3.2 异步路径(分包,mathjax 不进主包)
// 须由分包(pkg-doc)内的 math 页顶层发起 require.async(调用方=分包,见 RFC §4 推论1)
const mathRenderPromise = require.async('../../../pkg-math/render.js');
md.use(createMathBlockPlugin());
md.use(createMathPlugin({ resolveMathSvgModule: () => mathRenderPromise })); // 首公式 defer 回填
adapter.registry.register('md-math', '/components/md-math/index');首公式:renderer 返回 $$…$$ 源码占位 + ctx.defer 登记 resolver;require.async 下载 pkg-math → 拿到 renderMathSvg → 出 SVG → 引擎发 update patch 升级为 md-math 组件段。后续公式模块已缓存,同步出图。
4. md-math 组件
md-math 已瘦成纯 <image> 壳,收 dataUri/widthPx/heightPx props——MathJax 渲染在 plugin renderer 内完成(同步直接出图 / 异步 defer 回填),组件不再 import 重包、不再自行 renderMathSvg。
<view class="md-math {{display === 'inline' ? 'md-math--inline' : 'md-math--block'}}">
<image wx:if="{{dataUri}}" src="{{dataUri}}" mode="aspectFit"
style="width:{{widthPx}}px;height:{{heightPx}}px"></image>
</view>完整组件实现见仓库 sample-wechat/miniprogram/components/md-math/。
5. 降级
无 math 库时:只挂 createMathBlockPlugin() 不引入 math 包,math 块降级为展示 $$…$$ 源码的代码块(与不引入 mermaid 库时 ```mermaid 降级为代码块对称),不丢内容、无需注册组件。
异步路径加载失败:resolveMathSvgModule reject 后占位保持 $$…$$ 源码、经 StreamOptions.onDeferError 上报;loading 自动清空,后续 sealed 公式会重试(不永久卡死)。
6. 文档
7. License
MIT
