在 Markdown 中使用 JavaScript
虽然 Markdown 主要是一种用于格式化文本的标记语言,但你可以通过 JavaScript 增强 Markdown 文档,添加交互性和动态功能。
理解限制
标准的 Markdown 解析器不会执行 JavaScript 代码。然而,有几种方法可以将 JavaScript 与 Markdown 集成:
- HTML Script 标签:直接在 HTML 块中包含 JavaScript
- Markdown 处理器:使用支持 JavaScript 执行的处理器
- 静态网站生成器:利用构建时的 JavaScript 处理
- 客户端渲染:在 Markdown 转换为 HTML 后添加 JavaScript
基本 JavaScript 集成
内联脚本标签
你可以使用 HTML script 标签直接在 Markdown 中嵌入 JavaScript:
markdown
# 我的交互式文档
<script>
function greet() {
alert('来自 Markdown 的问候!');
}
</script>
<button onclick="greet()">点击我</button>外部脚本
引用外部 JavaScript 文件:
markdown
<script src="https://cdn.example.com/script.js"></script>
<div id="dynamic-content"></div>常见用例
1. 交互式表单
markdown
# 联系表单
<form id="contactForm">
<input type="text" id="name" placeholder="您的姓名">
<input type="email" id="email" placeholder="您的邮箱">
<button type="submit">提交</button>
</form>
<script>
document.getElementById('contactForm').addEventListener('submit', function(e) {
e.preventDefault();
const name = document.getElementById('name').value;
alert('谢谢,' + name + '!');
});
</script>2. 动态内容加载
markdown
# 最新文章
<div id="posts-container"></div>
<script>
fetch('/api/posts')
.then(response => response.json())
.then(posts => {
const container = document.getElementById('posts-container');
posts.forEach(post => {
container.innerHTML += `<h3>${post.title}</h3><p>${post.excerpt}</p>`;
});
});
</script>3. 数据可视化
markdown
# 销售图表
<canvas id="salesChart" width="400" height="200"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('salesChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: ['1月', '2月', '3月', '4月'],
datasets: [{
label: '销售额',
data: [12, 19, 3, 5]
}]
}
});
</script>静态网站生成器集成
Jekyll
Jekyll 不在构建时执行 JavaScript,但你可以在布局中包含它:
liquid
---
layout: default
---
{{ content }}
<script>
// 你的 JavaScript 代码
</script>Gatsby
Gatsby 支持在 MDX 中使用 React 组件:
mdx
import { useState } from 'react'
export const Counter = () => {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>计数: {count}</button>
}
# 我的文档
<Counter />Next.js
在 Next.js 中使用 MDX 实现完整的 React 集成:
mdx
import dynamic from 'next/dynamic'
const DynamicComponent = dynamic(() => import('../components/MyComponent'))
# 交互式内容
<DynamicComponent />安全注意事项
XSS 防护
在 Markdown 中使用 JavaScript 时,始终清理用户输入:
javascript
// 不好:直接 HTML 注入
element.innerHTML = userInput;
// 好:使用 textContent 或清理
element.textContent = userInput;
// 或者
element.innerHTML = DOMPurify.sanitize(userInput);内容安全策略
实施 CSP 头来限制脚本执行:
html
<meta http-equiv="Content-Security-Policy"
content="script-src 'self' https://trusted-cdn.com;">最佳实践
- 分离 JavaScript:尽可能将 JavaScript 存储在外部文件中
- 渐进增强:确保内容在没有 JavaScript 时也能工作
- 使用 CDN:从 CDN 加载流行的库以获得更好的缓存
- 最小化内联脚本:使用事件委托而不是内联处理程序
- 文档化依赖:清楚地说明所需的 JavaScript 库
高级技术
自定义 Markdown 扩展
创建处理 JavaScript 的自定义 Markdown 处理器:
javascript
const md = require('markdown-it')();
md.use(require('markdown-it-container'), 'runnable', {
validate: params => params.trim() === 'runnable',
render: (tokens, idx) => {
if (tokens[idx].nesting === 1) {
return '<div class="runnable-code">';
} else {
return '</div><button onclick="runCode(this)">运行</button>';
}
}
});WebAssembly 集成
将 Markdown 与 WebAssembly 结合用于高性能应用:
markdown
# 图像处理演示
<canvas id="canvas"></canvas>
<script>
WebAssembly.instantiateStreaming(fetch('image_processor.wasm'))
.then(module => {
// 使用 WebAssembly 函数
const result = module.instance.exports.process_image(imageData);
});
</script>工具和库
流行的 Markdown JavaScript 库
- Marked.js:快速的 Markdown 解析器,具有可扩展性
- Markdown-it:可插拔的 Markdown 解析器,速度快
- Showdown:双向 Markdown 转换器
- Remark:由插件驱动的 Markdown 处理器
交互式文档工具
- Docusaurus:基于 React 的文档生成器
- VuePress:由 Vue 驱动的静态网站生成器
- Docsify:轻量级文档生成器
- GitBook:现代化的文档平台
示例:完整的交互式文档
markdown
---
title: 交互式教程
---
# JavaScript 数组方法教程
<style>
.example-output {
background: #f4f4f4;
padding: 10px;
margin: 10px 0;
border-left: 3px solid #007acc;
}
</style>
## 自己试试
<input type="text" id="arrayInput" placeholder="输入数字:1,2,3,4,5">
<button onclick="processArray()">处理</button>
<div id="output" class="example-output"></div>
<script>
function processArray() {
const input = document.getElementById('arrayInput').value;
const numbers = input.split(',').map(Number);
const output = document.getElementById('output');
output.innerHTML = `
<p><strong>原始数组:</strong> [${numbers}]</p>
<p><strong>翻倍后:</strong> [${numbers.map(n => n * 2)}]</p>
<p><strong>总和:</strong> ${numbers.reduce((a, b) => a + b, 0)}</p>
`;
}
</script>结论
虽然 Markdown 本身不执行 JavaScript,但你可以有效地结合这两种技术来创建丰富的交互式文档。选择最适合你用例的方法,始终优先考虑安全性和用户体验。