Skip to content

在 Markdown 中使用 JavaScript

虽然 Markdown 主要是一种用于格式化文本的标记语言,但你可以通过 JavaScript 增强 Markdown 文档,添加交互性和动态功能。

理解限制

标准的 Markdown 解析器不会执行 JavaScript 代码。然而,有几种方法可以将 JavaScript 与 Markdown 集成:

  1. HTML Script 标签:直接在 HTML 块中包含 JavaScript
  2. Markdown 处理器:使用支持 JavaScript 执行的处理器
  3. 静态网站生成器:利用构建时的 JavaScript 处理
  4. 客户端渲染:在 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;">

最佳实践

  1. 分离 JavaScript:尽可能将 JavaScript 存储在外部文件中
  2. 渐进增强:确保内容在没有 JavaScript 时也能工作
  3. 使用 CDN:从 CDN 加载流行的库以获得更好的缓存
  4. 最小化内联脚本:使用事件委托而不是内联处理程序
  5. 文档化依赖:清楚地说明所需的 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,但你可以有效地结合这两种技术来创建丰富的交互式文档。选择最适合你用例的方法,始终优先考虑安全性和用户体验。

其他资源

由 Markdownlang.com 整理创建