TOP ⬆
纯静态的 Markdown 渲染模板
记录一个最近的业务需求:制作简单 HTML 页面来展示 Q&A 文档
你可以得到:一个打开即用的 HTML 直接展示 Markdown 格式的文件
效果展示
-
浅色模式
-
深色模式
资源
怎么足够简单?
既然要足够简单打开即用,那就 all in HTML + CSS + JS , 核心是要用 JS 来解析 Markdown ,这部分利用几个库来处理就好了
markdown-it.js
markdown-it-toc.js
用来解析 TOCmarkdown-it-named-headings
给文章的标题挂上标签kebabcase.js
依赖的子组件
这里需要解决的主要问题是解析 Markdown 的库的 CDN 引入的 JS 是使用 commonjs 模块来导出相关资源的,这就要求我们魔改用全局变量来承接这些导出的对象(函数),并使其满足各类依赖之间的调用。
具体的修改方式为:(细节就不赘述,有兴趣直接看资源即可)
// xxx.min.js
modules.export = (() => {
return sm;
})();
// after edited
window.a = (() => {
return sm;
})();
// use it in other dep.js
() => {
a.xxx();
};
怎么展示目录?
[[toc]] 关键字在我们使用 markdown-it-toc.js
时会自动解析成一块独立的元素,要展示这个目录的时候,我们可以直接把这块元素直接脱离页面布局固定在左边。
.table-of-contents {
position: fixed;
left: 0;
top: 0;
}
同时,这个库 markdown-it-table-of-contents 的配置项是很丰富的,欢迎大家去关注一下。例如以下配置就是只解析到一、二、三号标题。
md.use(window.markdownToc,{includeLevel:[1, 2, 3]})
怎么处理深色主题?
JS 部分
- 从 SessionStroage 中获取,这样能够满足刷新页面的要求
- 适配系统主题做初始化
// 处理主题
const theme = (() => {
if (typeof sessionStorage !== 'undefined' && sessionStorage.getItem('theme')) {
return sessionStorage.getItem('theme');
}
// 适配系统的主题
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
})();
// 处理点击事件
const btnID = 'modeBtn';
const btnElement = document.getElementById(btnID);
if (theme === 'light') {
btnElement.setAttribute('src', './assets/sun.svg');
document.documentElement.classList.remove('dark');
} else {
btnElement.setAttribute('src', './assets/moon.svg');
document.documentElement.classList.add('dark');
}
window.sessionStorage.setItem('theme', theme);
const handleToggleClick = (e) => {
const src = e.target.src;
const isMoon = src.endsWith('moon.svg');
// 处理显示图标
e.target.setAttribute('src', isMoon ? './assets/sun.svg' : './assets/moon.svg');
// 更新css主题
const element = document.documentElement;
element.classList.toggle('dark');
// 切换 sessionStorage 的存储变量
const isDark = element.classList.contains('dark');
sessionStorage.setItem('theme', isDark ? 'dark' : 'light');
};
document.getElementById('modeBtn').addEventListener('click', handleToggleClick);
CSS 部分
不同环境配置不同的变量
:root {
--tab-width: 480px;
--background-color: #fff;
--tab-background-color: #ffffff7f;
--text-color: #163b66;
--highlight: #163b6620;
}
:root.dark {
--background-color: #000;
--tab-background-color: #0000007f;
--text-color: #fff;
--highlight: #6666667f;
}
Markdown 数据源在哪
既然 HTML 本身就是一个文档,那么在 HTML 直接写 Markdown 是不是也很合理?🤔
<div id="markdown">
# Hello, Markdown!
这是一段写在 HTML 里面的 Markdown 语法
</div>
<main>
<div id="slot" />
</main>
<script>
const markdown = document.getElementById('markdown').textContent;
const result = markdownit.render(markdown);
document.getElementById('slot').innerHTML = result;
</script>