diff --git a/src/lib/markdown.ts b/src/lib/markdown.ts
index 6330b11..415ba69 100644
--- a/src/lib/markdown.ts
+++ b/src/lib/markdown.ts
@@ -1,11 +1,6 @@
-import { marked, type Tokens } from 'marked'
+import { Marked } from 'marked'
import type { CSSProperties } from 'react'
-
-// 配置 marked 选项
-marked.setOptions({
- gfm: true,
- breaks: true
-})
+import type { Tokens } from 'marked'
// 将 React CSSProperties 转换为 CSS 字符串
function cssPropertiesToString(style: React.CSSProperties = {}): string {
@@ -43,129 +38,144 @@ function baseStylesToString(base: RendererOptions['base'] = {}): string {
return styles.join(';')
}
+// 预处理函数
+function preprocessMarkdown(markdown: string): string {
+ // 处理 ** 语法,但排除已经是 HTML 的部分
+ return markdown.replace(/(?]*)\*\*([^*]+)\*\*(?![^<]*>)/g, '$1')
+}
+
+// Initialize marked instance
+const marked = new Marked()
+
+// 创建基础渲染器
+const baseRenderer = new marked.Renderer()
+
+// 重写 strong 渲染器
+baseRenderer.strong = function(text) {
+ return `${text}`
+}
+
+// 应用配置和渲染器
+marked.setOptions({
+ gfm: true,
+ breaks: true,
+ async: false,
+ pedantic: false,
+ renderer: baseRenderer
+})
+
export function convertToWechat(markdown: string, options: RendererOptions = {}): string {
- const renderer = new marked.Renderer()
- // 标题渲染
- renderer.heading = ({ text, depth }: Tokens.Heading) => {
+ // 预处理 markdown
+ markdown = preprocessMarkdown(markdown)
+
+ // 创建渲染器
+ const customRenderer = new marked.Renderer()
+
+ // 继承基础渲染器
+ Object.setPrototypeOf(customRenderer, baseRenderer)
+
+ customRenderer.heading = function({ text, depth }: Tokens.Heading) {
const style = options.block?.[`h${depth}` as keyof typeof options.block]
const styleStr = cssPropertiesToString(style)
return `
${content}
` + return `${text}
` } - // 引用渲染 - renderer.blockquote = (quote) => { + customRenderer.blockquote = function({ text }: Tokens.Blockquote) { const style = options.block?.blockquote const styleStr = cssPropertiesToString(style) - const content = typeof quote === 'object' ? (quote.text || quote.toString()) : quote - - return `${content}` + return `
${text}` } - // 代码块渲染 - renderer.code = ({ text, lang = '' }: { text: string; lang?: string }) => { + customRenderer.code = function({ text, lang }: Tokens.Code) { const style = options.block?.code_pre const styleStr = cssPropertiesToString(style) - return `
${text}
`
+ return `${text}
`
}
- // 行内代码渲染
- renderer.codespan = (code) => {
+ customRenderer.codespan = function({ text }: Tokens.Codespan) {
const style = options.inline?.codespan
const styleStr = cssPropertiesToString(style)
- return `${code}
`
+ return `${text}
`
}
- // 强调(斜体)渲染
- renderer.em = (text) => {
+ customRenderer.em = function({ text }: Tokens.Em) {
const style = options.inline?.em
const styleStr = cssPropertiesToString(style)
return `${text}`
}
- // 加粗渲染
- renderer.strong = (text) => {
+ customRenderer.strong = function({ text }: Tokens.Strong) {
const style = options.inline?.strong
const styleStr = cssPropertiesToString(style)
return `${text}`
}
- // 链接渲染
- renderer.link = ({ href, title, tokens }: Tokens.Link) => {
+ customRenderer.link = function({ href, title, text }: Tokens.Link) {
const style = options.inline?.link
const styleStr = cssPropertiesToString(style)
- const text = tokens?.map(t => 'text' in t ? t.text : '').join('') || ''
return `${text}`
}
- // 图片渲染
- renderer.image = ({ href, title, text }: Tokens.Image) => {
+ customRenderer.image = function({ href, title, text }: Tokens.Image) {
const style = options.block?.image
const styleStr = cssPropertiesToString(style)
return `${text}
` } - marked.setOptions({ renderer: xiaohongshuRenderer }) - - let html = marked(markdown) - html = `