优化模版样式

This commit is contained in:
tianyaxiang 2025-02-01 14:23:00 +08:00
parent 6db55b4dd9
commit d6806b2757
2 changed files with 59 additions and 34 deletions

View File

@ -20,7 +20,7 @@ export const templates: Template[] = [
themeColor: '#166534', themeColor: '#166534',
fontFamily: '-apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif', fontFamily: '-apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif',
textAlign: 'left', textAlign: 'left',
lineHeight: '1.75', lineHeight: '2',
padding: '1rem 1.5rem', padding: '1rem 1.5rem',
maxWidth: '100%', maxWidth: '100%',
margin: '0 auto', margin: '0 auto',

View File

@ -38,23 +38,27 @@ function preprocessMarkdown(markdown: string): string {
} }
// Initialize marked instance // Initialize marked instance
const marked = new Marked() const marked = new Marked({
// 创建基础渲染器
const baseRenderer = new marked.Renderer()
// 重写 strong 渲染器
baseRenderer.strong = function(text) {
return `<strong>${text}</strong>`
}
// 应用配置和渲染器
marked.setOptions({
gfm: true, gfm: true,
breaks: true, breaks: true,
async: false, async: false,
pedantic: false, pedantic: false
renderer: baseRenderer })
// 应用配置
marked.use({
breaks: true,
gfm: true,
walkTokens(token: Tokens.Generic) {
// 确保列表项被正确处理
if (token.type === 'list') {
(token as Tokens.List).items.forEach(item => {
if (item.task) {
item.checked = !!item.checked
}
})
}
}
}) })
const defaultOptions: RendererOptions = { const defaultOptions: RendererOptions = {
@ -83,9 +87,6 @@ const defaultOptions: RendererOptions = {
export function convertToWechat(markdown: string, options: RendererOptions = defaultOptions): string { export function convertToWechat(markdown: string, options: RendererOptions = defaultOptions): string {
const renderer = new marked.Renderer() const renderer = new marked.Renderer()
// 继承基础渲染器
Object.setPrototypeOf(renderer, baseRenderer)
// 合并选项 // 合并选项
const mergedOptions = { const mergedOptions = {
base: { ...defaultOptions.base, ...options.base }, base: { ...defaultOptions.base, ...options.base },
@ -156,14 +157,28 @@ export function convertToWechat(markdown: string, options: RendererOptions = def
} }
// 重写 list 方法 // 重写 list 方法
renderer.list = function(token: Tokens.List): string { renderer.list = function(token: Tokens.List) {
const tag = token.ordered ? 'ol' : 'ul' const tag = token.ordered ? 'ol' : 'ul'
try { try {
const style = mergedOptions.block?.[token.ordered ? 'ol' : 'ul'] const style = {
...(mergedOptions.block?.[token.ordered ? 'ol' : 'ul'] || {}),
listStyle: token.ordered ? 'decimal' : 'disc',
paddingLeft: '2em',
marginBottom: '16px'
}
const styleStr = cssPropertiesToString(style) const styleStr = cssPropertiesToString(style)
const startAttr = token.ordered && token.start !== 1 ? ` start="${token.start}"` : '' const startAttr = token.ordered && token.start !== 1 ? ` start="${token.start}"` : ''
return `<${tag}${startAttr}${styleStr ? ` style="${styleStr}"` : ''}>${token.items.map(item => renderer.listitem(item)).join('')}</${tag}>` const items = token.items.map(item => {
let itemText = item.text
if (item.task) {
const checkbox = `<input type="checkbox"${item.checked ? ' checked=""' : ''} disabled="" /> `
itemText = checkbox + itemText
}
return renderer.listitem({ ...item, text: itemText })
}).join('')
return `<${tag}${startAttr}${styleStr ? ` style="${styleStr}"` : ''}>${items}</${tag}>`
} catch (error) { } catch (error) {
console.error(`Error rendering list: ${error}`) console.error(`Error rendering list: ${error}`)
return `<${tag}>${token.items.map(item => renderer.listitem(item)).join('')}</${tag}>` return `<${tag}>${token.items.map(item => renderer.listitem(item)).join('')}</${tag}>`
@ -173,21 +188,31 @@ renderer.list = function(token: Tokens.List): string {
// 重写 listitem 方法 // 重写 listitem 方法
renderer.listitem = function(item: Tokens.ListItem) { renderer.listitem = function(item: Tokens.ListItem) {
try { try {
const style = mergedOptions.inline?.listitem const style = {
...(mergedOptions.inline?.listitem || {}),
marginBottom: '8px',
display: 'list-item'
}
const styleStr = cssPropertiesToString(style) const styleStr = cssPropertiesToString(style)
// 移除列表项开头的破折号和空格 // 处理嵌套列表
let itemText = item.text.replace(/^- /, '') let content = item.text
if (item.tokens) {
// 处理任务列表项 content = item.tokens.map(token => {
if (item.task) { if (token.type === 'list') {
const checkbox = `<input type="checkbox"${item.checked ? ' checked=""' : ''} disabled="" /> ` // 递归处理嵌套列表
itemText = checkbox + itemText return renderer.list(token as Tokens.List)
} else {
// 处理其他类型的 token
const tokens = marked.Lexer.lexInline(token.raw)
return marked.Parser.parseInline(tokens, { renderer })
}
}).join('')
} else {
// 如果没有 tokens则按普通文本处理
const tokens = marked.Lexer.lexInline(content)
content = marked.Parser.parseInline(tokens, { renderer })
} }
// 使用 Lexer 和 Parser 处理剩余的内联标记
const tokens = marked.Lexer.lexInline(itemText)
const content = marked.Parser.parseInline(tokens, { renderer })
return `<li${styleStr ? ` style="${styleStr}"` : ''}>${content}</li>` return `<li${styleStr ? ` style="${styleStr}"` : ''}>${content}</li>`
} catch (error) { } catch (error) {