编程 ·

代码块演示

展示博客的代码高亮功能,涵盖 Python、JavaScript、TypeScript、Rust、Bash 和 JSON 等多种语言。

代码块演示

本文展示博客的代码语法高亮功能,由 Shiki 提供支持。

Python

一个简单的异步 HTTP 客户端:

import asyncio
import aiohttp
from typing import Optional

async def fetch_json(
    url: str,
    headers: Optional[dict] = None,
    timeout: int = 30,
) -> dict:
    """异步获取 JSON 数据"""
    async with aiohttp.ClientSession() as session:
        async with session.get(
            url,
            headers=headers or {},
            timeout=aiohttp.ClientTimeout(total=timeout),
        ) as response:
            response.raise_for_status()
            return await response.json()

async def main():
    urls = [
        "https://api.example.com/users",
        "https://api.example.com/posts",
        "https://api.example.com/comments",
    ]
    tasks = [fetch_json(url) for url in urls]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    for url, result in zip(urls, results):
        if isinstance(result, Exception):
            print(f"Error fetching {url}: {result}")
        else:
            print(f"Got {len(result)} items from {url}")

if __name__ == "__main__":
    asyncio.run(main())

JavaScript / TypeScript

一个 React hook 实现的防抖功能:

import { useState, useEffect, useCallback, useRef } from 'react';

type DebounceOptions = {
  delay?: number;
  leading?: boolean;
  trailing?: boolean;
};

function useDebounce<T extends (...args: unknown[]) => unknown>(
  fn: T,
  options: DebounceOptions = {}
): T {
  const { delay = 300, leading = false, trailing = true } = options;
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const fnRef = useRef<T>(fn);
  
  // Keep latest function reference
  useEffect(() => {
    fnRef.current = fn;
  }, [fn]);

  const debouncedFn = useCallback(
    (...args: Parameters<T>) => {
      if (timerRef.current) {
        clearTimeout(timerRef.current);
      }
      if (leading && !timerRef.current) {
        fnRef.current(...args);
      }
      timerRef.current = setTimeout(() => {
        if (trailing) {
          fnRef.current(...args);
        }
        timerRef.current = null;
      }, delay);
    },
    [delay, leading, trailing]
  );

  return debouncedFn as T;
}

export default useDebounce;

Rust

一个简单的并发任务调度器:

use std::sync::{Arc, Mutex};
use std::thread;
use std::collections::VecDeque;

type Task = Box<dyn FnOnce() + Send + 'static>;

pub struct ThreadPool {
    workers: Vec<thread::JoinHandle<()>>,
    sender: std::sync::mpsc::Sender<Option<Task>>,
}

impl ThreadPool {
    pub fn new(size: usize) -> Self {
        let (sender, receiver) = std::sync::mpsc::channel::<Option<Task>>();
        let receiver = Arc::new(Mutex::new(receiver));
        
        let workers = (0..size)
            .map(|id| {
                let rx = Arc::clone(&receiver);
                thread::spawn(move || loop {
                    let msg = rx.lock().unwrap().recv().unwrap();
                    match msg {
                        Some(task) => {
                            println!("Worker {id} executing task");
                            task();
                        }
                        None => {
                            println!("Worker {id} shutting down");
                            break;
                        }
                    }
                })
            })
            .collect();

        ThreadPool { workers, sender }
    }

    pub fn execute<F: FnOnce() + Send + 'static>(&self, f: F) {
        self.sender.send(Some(Box::new(f))).unwrap();
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for _ in &self.workers {
            self.sender.send(None).unwrap();
        }
    }
}

Bash

一键部署脚本:

#!/usr/bin/env bash
set -euo pipefail

DEPLOY_ENV="${1:-production}"
REPO_URL="https://github.com/example/my-blog.git"
DEPLOY_DIR="/var/www/my-blog"
BACKUP_DIR="/var/backups/my-blog"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }

log "Starting deployment to ${DEPLOY_ENV}..."

# Backup current version
if [ -d "$DEPLOY_DIR" ]; then
  BACKUP_NAME="backup-$(date +%Y%m%d-%H%M%S)"
  log "Backing up to ${BACKUP_DIR}/${BACKUP_NAME}"
  mkdir -p "$BACKUP_DIR"
  cp -r "$DEPLOY_DIR" "${BACKUP_DIR}/${BACKUP_NAME}"
fi

# Pull latest code
log "Pulling latest code..."
git -C "$DEPLOY_DIR" pull origin main || git clone "$REPO_URL" "$DEPLOY_DIR"

# Install and build
cd "$DEPLOY_DIR"
npm ci --production
npm run build

log "Deployment complete!"

JSON

一个 package.json 配置示例:

{
  "name": "my-blog",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "astro dev",
    "build": "astro build && npx pagefind --site dist",
    "preview": "astro preview",
    "lint": "eslint src --ext .ts,.astro",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "astro": "^4.0.0",
    "@astrojs/mdx": "^2.0.0",
    "@astrojs/sitemap": "^3.0.0",
    "remark-math": "^6.0.0",
    "rehype-katex": "^7.0.0",
    "tailwindcss": "^3.4.0"
  },
  "devDependencies": {
    "@tailwindcss/typography": "^0.5.10",
    "pagefind": "^1.0.0",
    "typescript": "^5.3.0"
  },
  "engines": {
    "node": ">=18.0.0",
    "npm": ">=9.0.0"
  }
}

总结

以上代码块展示了 Shiki 对多种编程语言的语法高亮支持。每个代码块右上角都有一个复制按钮,方便你快速复制代码。