Files
pure-note/web/src/lib/sanitize.ts
T
wangairnan e9316c9169 前端:React 19 + Vite 8 + Tailwind 4 博客与管理后台 SPA
- 渲染管线(§8.2):react-markdown + remark-gfm + rehype-sanitize
  (GitHub schema 扩展 hljs class 与 checked)+ rehype-highlight 纯 class
  高亮;链接强制 target=_blank + rel=nofollow noopener noreferrer;
  schema 快照与恶意 Markdown 冒烟测试(vitest 6 用例)
- 编辑器:CodeMirror 6 源码编辑 + 分屏实时预览 + 工具栏 +
  粘贴/拖拽图片上传;slug 首存定稿(冲突 409 就地高亮)、
  摘要留空自动截取、2s 防抖自动保存
- 页面:博客首页(置顶/分页/标签云)、详情(面包屑/上一篇下一篇)、
  标签页、登录、管理列表/回收站/设置/改密、404
- lib:api 客户端(统一包络 + 内存态 CSRF,禁 localStorage)、
  AuthContext(/api/me 重取)、暗色主题(class 切换 + 系统跟随)
- index.html 内嵌 Go template 占位符供服务端 meta 注入;
  vite base 固定 '/'(防深链白屏);/api 代理 127.0.0.1:8080
2026-09-08 08:14:52 +08:00

42 lines
1.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// rehype-sanitize 白名单 schema(§8.2 渲染管线):
// - 默认 GitHub schema 之上扩展:任务列表 checkbox 所需属性、
// highlight.js 纯 class 高亮所需 className 白名单
// - 禁 script/iframe/style 属性/事件属性;链接协议白名单(javascript: 被剥除)
// - 链接 target/rel 由 <a> 组件强制(schema 不支持条件属性)
import { defaultSchema } from 'rehype-sanitize'
import rehypeSanitize from 'rehype-sanitize'
import type { Schema } from 'hast-util-sanitize'
import type { Pluggable } from 'unified'
export const sanitizeSchema: Schema = {
...defaultSchema,
tagNames: [
...(defaultSchema.tagNames ?? []),
// 允许任务列表所需的 input(GitHub schema 已含,显式声明以防上游变化)
'input',
],
attributes: {
...defaultSchema.attributes,
// 任务列表 checkbox:默认 schema 已含 ['type','checkbox'] 与 ['disabled',true],
// 显式补 'checked'
input: [
...(defaultSchema.attributes?.input ?? []),
['checked', true],
],
// highlight.js 输出纯 class(零内联样式,§3.2)
code: [
...(defaultSchema.attributes?.code ?? []),
['className', /^language-./, 'hljs'],
],
span: [
...(defaultSchema.attributes?.span ?? []),
['className', /^hljs(-\w+)?$/],
],
},
// 危险协议由默认 protocols 白名单(http/https/mailto/irc/xmpp…)剥除
clobberPrefix: defaultSchema.clobberPrefix ?? 'user-content-',
}
// rehypePlugins 元组:[rehypeSanitize, sanitizeSchema]
export const sanitizePlugin: Pluggable = [rehypeSanitize, sanitizeSchema]