圍欄代碼塊
圍欄代碼塊是 Markdown 擴展語法的重要功能,提供了比基本代碼塊更強大的代碼展示能力,支持語法高亮、行號、文件名等高級特性。
基本圍欄代碼塊
三個反引號
使用三個反引號 ``` 創建代碼塊:
markdown
```
function hello() {
console.log("Hello, World!");
}
```
渲染效果:
function hello() {
console.log("Hello, World!");
}
三個波浪號
也可以使用三個波浪號 ~~~ 創建代碼塊:
markdown
~~~
function hello() {
console.log("Hello, World!");
}
~~~
渲染效果:
function hello() {
console.log("Hello, World!");
}
語法高亮
指定編程語言
在開頭標記後指定語言名稱啟用語法高亮:
markdown
```javascript
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10)); // 55
```
渲染效果:
javascript
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(10)); // 55
常用語言示例
Python
markdown
```python
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
# 示例使用
numbers = [3, 6, 8, 10, 1, 2, 1]
print(quicksort(numbers))
```
渲染效果:
python
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
# 示例使用
numbers = [3, 6, 8, 10, 1, 2, 1]
print(quicksort(numbers))
TypeScript
markdown
```typescript
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
class UserService {
private users: User[] = [];
async createUser(userData: Omit<User, 'id'>): Promise<User> {
const newUser: User = {
id: Date.now(),
...userData
};
this.users.push(newUser);
return newUser;
}
async getUserById(id: number): Promise<User | undefined> {
return this.users.find(user => user.id === id);
}
}
```
渲染效果:
typescript
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
class UserService {
private users: User[] = [];
async createUser(userData: Omit<User, 'id'>): Promise<User> {
const newUser: User = {
id: Date.now(),
...userData
};
this.users.push(newUser);
return newUser;
}
async getUserById(id: number): Promise<User | undefined> {
return this.users.find(user => user.id === id);
}
}
Go
markdown
```go
package main
import (
"fmt"
"net/http"
"log"
)
type Server struct {
port string
}
func NewServer(port string) *Server {
return &Server{port: port}
}
func (s *Server) Start() error {
http.HandleFunc("/", s.handleHome)
http.HandleFunc("/api/health", s.handleHealth)
fmt.Printf("Server starting on port %s\n", s.port)
return http.ListenAndServe(":"+s.port, nil)
}
func (s *Server) handleHome(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to Go Server!")
}
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"status": "healthy"}`)
}
func main() {
server := NewServer("8080")
log.Fatal(server.Start())
}
```
渲染效果:
go
package main
import (
"fmt"
"net/http"
"log"
)
type Server struct {
port string
}
func NewServer(port string) *Server {
return &Server{port: port}
}
func (s *Server) Start() error {
http.HandleFunc("/", s.handleHome)
http.HandleFunc("/api/health", s.handleHealth)
fmt.Printf("Server starting on port %s\n", s.port)
return http.ListenAndServe(":"+s.port, nil)
}
func (s *Server) handleHome(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to Go Server!")
}
func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"status": "healthy"}`)
}
func main() {
server := NewServer("8080")
log.Fatal(server.Start())
}
高級功能
行高亮
某些 Markdown 處理器支持高亮特定行:
markdown
```javascript {2,4-6}
function calculateTotal(items) {
let total = 0; // 這行被高亮
for (const item of items) { // 這幾行被高亮
total += item.price * item.quantity;
} // 高亮結束
return total;
}
```
行號顯示
顯示代碼行號:
markdown
```python:line-numbers
def binary_search(arr, target):
left, right = 0, len(arr) - 1
while left <= right:
mid = (left + right) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
```
文件名標題
顯示代碼文件名:
markdown
```typescript title="userService.ts"
export class UserService {
private apiUrl = '/api/users';
async getUsers(): Promise<User[]> {
const response = await fetch(this.apiUrl);
return response.json();
}
async createUser(user: CreateUserDto): Promise<User> {
const response = await fetch(this.apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(user)
});
return response.json();
}
}
```
代碼塊差異顯示
顯示代碼變更:
markdown
```diff
function calculateTax(amount) {
- return amount * 0.05; // 舊的稅率
+ return amount * 0.08; // 新的稅率
}
+ // 新增的函數
+ function calculateDiscount(amount, percentage) {
+ return amount * (percentage / 100);
+ }
```
渲染效果:
diff
function calculateTax(amount) {
- return amount * 0.05; // 舊的稅率
+ return amount * 0.08; // 新的稅率
}
+ // 新增的函數
+ function calculateDiscount(amount, percentage) {
+ return amount * (percentage / 100);
+ }
配置文件示例
JSON 配置
markdown
```json
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"build": "webpack --mode production",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.0.3",
"jsonwebtoken": "^9.0.0"
},
"devDependencies": {
"nodemon": "^2.0.22",
"jest": "^29.5.0",
"webpack": "^5.82.0"
}
}
```
渲染效果:
json
{
"name": "my-app",
"version": "1.0.0",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"build": "webpack --mode production",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.0.3",
"jsonwebtoken": "^9.0.0"
},
"devDependencies": {
"nodemon": "^2.0.22",
"jest": "^29.5.0",
"webpack": "^5.82.0"
}
}
YAML 配置
markdown
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web
image: nginx:1.21
ports:
- containerPort: 80
env:
- name: NODE_ENV
value: production
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
```
渲染效果:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web
image: nginx:1.21
ports:
- containerPort: 80
env:
- name: NODE_ENV
value: production
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
SQL 查詢
markdown
```sql
-- 創建用戶表
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 創建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
-- 查詢活躍用戶
SELECT
u.id,
u.username,
u.email,
COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
WHERE u.created_at >= NOW() - INTERVAL '30 days'
GROUP BY u.id, u.username, u.email
HAVING COUNT(p.id) > 0
ORDER BY post_count DESC
LIMIT 10;
```
渲染效果:
sql
-- 創建用戶表
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 創建索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
-- 查詢活躍用戶
SELECT
u.id,
u.username,
u.email,
COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
WHERE u.created_at >= NOW() - INTERVAL '30 days'
GROUP BY u.id, u.username, u.email
HAVING COUNT(p.id) > 0
ORDER BY post_count DESC
LIMIT 10;
Shell 腳本和命令
Bash 腳本
markdown
```bash
#!/bin/bash
# 部署腳本
set -e
APP_NAME="my-app"
DEPLOY_DIR="/var/www/${APP_NAME}"
BACKUP_DIR="/var/backups/${APP_NAME}"
CURRENT_DATE=$(date +%Y%m%d_%H%M%S)
echo "開始部署 ${APP_NAME}..."
# 創建備份
if [ -d "$DEPLOY_DIR" ]; then
echo "創建備份到 ${BACKUP_DIR}/${CURRENT_DATE}"
mkdir -p "$BACKUP_DIR"
cp -r "$DEPLOY_DIR" "${BACKUP_DIR}/${CURRENT_DATE}"
fi
# 停止服務
echo "停止服務..."
sudo systemctl stop $APP_NAME || true
# 部署新版本
echo "部署新版本..."
rm -rf "$DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR"
tar -xzf "${APP_NAME}.tar.gz" -C "$DEPLOY_DIR"
# 安裝依賴
echo "安裝依賴..."
cd "$DEPLOY_DIR"
npm ci --production
# 啟動服務
echo "啟動服務..."
sudo systemctl start $APP_NAME
sudo systemctl enable $APP_NAME
echo "部署完成!"
```
渲染效果:
bash
#!/bin/bash
# 部署腳本
set -e
APP_NAME="my-app"
DEPLOY_DIR="/var/www/${APP_NAME}"
BACKUP_DIR="/var/backups/${APP_NAME}"
CURRENT_DATE=$(date +%Y%m%d_%H%M%S)
echo "開始部署 ${APP_NAME}..."
# 創建備份
if [ -d "$DEPLOY_DIR" ]; then
echo "創建備份到 ${BACKUP_DIR}/${CURRENT_DATE}"
mkdir -p "$BACKUP_DIR"
cp -r "$DEPLOY_DIR" "${BACKUP_DIR}/${CURRENT_DATE}"
fi
# 停止服務
echo "停止服務..."
sudo systemctl stop $APP_NAME || true
# 部署新版本
echo "部署新版本..."
rm -rf "$DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR"
tar -xzf "${APP_NAME}.tar.gz" -C "$DEPLOY_DIR"
# 安裝依賴
echo "安裝依賴..."
cd "$DEPLOY_DIR"
npm ci --production
# 啟動服務
echo "啟動服務..."
sudo systemctl start $APP_NAME
sudo systemctl enable $APP_NAME
echo "部署完成!"
常見錯誤和解決方案
1. 反引號數量不匹配
markdown
❌ 錯誤:
```javascript
function hello() {
console.log("Hello");
}
`` ← 只有兩個反引號
✅ 正確:
```javascript
function hello() {
console.log("Hello");
}
``` ← 三個反引號
2. 語言標識符錯誤
markdown
❌ 錯誤:
```js ← 某些處理器不識別
function hello() {}
```
✅ 推薦:
```javascript ← 使用完整名稱
function hello() {}
```
3. 嵌套代碼塊
markdown
❌ 問題:無法顯示包含 ``` 的代碼
✅ 解決:使用四個反引號包裝三個反引號
````markdown
```javascript
console.log("hello");
```
### 4. 特殊字符處理
````markdown
```markdown
<!-- 在 markdown 代碼塊中顯示 markdown 語法 -->
\```javascript ← 轉義反引號
code here
\```
```
支持的語言列表
編程語言
語言 | 標識符 | 別名 |
---|---|---|
JavaScript | javascript | js |
TypeScript | typescript | ts |
Python | python | py |
Java | java | |
C++ | cpp | c++ , cxx |
C# | csharp | cs |
Go | go | golang |
Rust | rust | rs |
PHP | php | |
Ruby | ruby | rb |
Swift | swift | |
Kotlin | kotlin | kt |
標記和配置語言
語言 | 標識符 | 用途 |
---|---|---|
HTML | html | 網頁標記 |
CSS | css | 樣式表 |
XML | xml | 數據交換 |
JSON | json | 數據格式 |
YAML | yaml , yml | 配置文件 |
TOML | toml | 配置文件 |
Markdown | markdown , md | 文檔編寫 |
數據和查詢語言
語言 | 標識符 | 用途 |
---|---|---|
SQL | sql | 數據庫查詢 |
GraphQL | graphql | API查詢 |
R | r | 統計計算 |
MATLAB | matlab | 數值計算 |
Shell 和腳本
語言 | 標識符 | 用途 |
---|---|---|
Bash | bash , sh | Unix Shell |
PowerShell | powershell , ps1 | Windows Shell |
Batch | batch , bat | Windows 批處理 |
Dockerfile | dockerfile | 容器配置 |
最佳實踐
1. 選擇合適的語言標識符
markdown
✅ 推薦:使用准確的語言標識符
```typescript
interface User {
id: number;
name: string;
}
```
❌ 不推薦:使用錯誤的標識符
```javascript ← 這是 TypeScript 代碼
interface User {
id: number;
name: string;
}
```
2. 添加有意義的注釋
markdown
✅ 推薦:包含解釋性注釋
```python
def fibonacci(n):
"""計算斐波那契數列的第n項"""
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
```
❌ 不推薦:缺少說明的代碼
```python
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)
```
3. 保持代碼簡潔
markdown
✅ 推薦:展示核心邏輯
```javascript
// 用戶認證中間件
function authenticate(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
// 驗證邏輯...
next();
}
```
❌ 不推薦:包含過多細節
```javascript
// 省略大量無關代碼...
```
4. 使用文件名標題
markdown
✅ 推薦:顯示文件名
```javascript title="middleware/auth.js"
export function authenticate(req, res, next) {
// 認證邏輯
}
```
✅ 推薦:顯示配置文件名
```json title="package.json"
{
"name": "my-app",
"version": "1.0.0"
}
```
實際應用場景
1. API 文檔
markdown
## 用戶登錄 API
**請求示例:**
```bash
curl -X POST https://api.example.com/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123"
}'
```
**響應示例:**
```json
{
"success": true,
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"email": "user@example.com",
"name": "張三"
}
}
}
```
**錯誤響應:**
```json
{
"success": false,
"error": {
"code": "INVALID_CREDENTIALS",
"message": "Invalid email or password"
}
}
```
2. 安裝教程
markdown
## 環境配置
### 1. 安裝 Node.js
**macOS (使用 Homebrew):**
```bash
# 安裝 Homebrew(如果還沒有)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 安裝 Node.js
brew install node
# 驗證安裝
node --version
npm --version
```
**Ubuntu/Debian:**
```bash
# 更新包列表
sudo apt update
# 安裝 Node.js 和 npm
sudo apt install nodejs npm
# 驗證安裝
node --version
npm --version
```
**Windows (使用 Chocolatey):**
```powershell
# 安裝 Chocolatey(使用管理員權限)
Set-ExecutionPolicy Bypass -Scope Process -Force;
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
# 安裝 Node.js
choco install nodejs
# 驗證安裝
node --version
npm --version
```
3. 代碼對比
markdown
## 重構前後對比
**重構前(回調地獄):**
```javascript
function getUserData(userId, callback) {
getUser(userId, function(err, user) {
if (err) {
callback(err);
return;
}
getPosts(user.id, function(err, posts) {
if (err) {
callback(err);
return;
}
getComments(posts[0].id, function(err, comments) {
if (err) {
callback(err);
return;
}
callback(null, { user, posts, comments });
});
});
});
}
```
**重構後(async/await):**
```javascript
async function getUserData(userId) {
try {
const user = await getUser(userId);
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
return { user, posts, comments };
} catch (error) {
throw error;
}
}
```
HTML 輸出
圍欄代碼塊轉換為 HTML:
markdown
```javascript
function hello() {
console.log("Hello");
}
```
轉換為:
html
<pre><code class="language-javascript">
function hello() {
console.log("Hello");
}
</code></pre>
相關語法
練習
嘗試創建以下代碼塊:
- 一個包含多種編程語言的代碼示例集合
- 一個完整的 API 使用教程(包含請求和響應)
- 一個部署腳本的說明文檔
- 一個數據庫設計的 SQL 腳本
工具和插件
語法高亮庫
- Prism.js: 輕量級語法高亮
- highlight.js: 功能豐富的高亮庫
- CodeMirror: 在線代碼編輯器
- Monaco Editor: VS Code 編輯器核心
Markdown 處理器
- markdown-it: 可擴展的 Markdown 解析器
- remark: 統一的 Markdown 處理器
- marked: 快速的 Markdown 解析器
- gray-matter: Front Matter 解析
編輯器插件
- VS Code: Markdown Preview Enhanced
- Sublime Text: MarkdownEditing
- Atom: markdown-preview-plus
- Vim: vim-markdown