优化模版样式
This commit is contained in:
parent
6db55b4dd9
commit
d6806b2757
@ -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',
|
||||||
|
@ -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,28 +188,38 @@ 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) {
|
||||||
console.error(`Error rendering list item: ${error}`)
|
console.error(`Error rendering list item: ${error}`)
|
||||||
return `<li>${item.text}</li>`
|
return `<li>${item.text}</li>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert Markdown to HTML using the custom renderer
|
// Convert Markdown to HTML using the custom renderer
|
||||||
const html = marked.parse(markdown, { renderer }) as string
|
const html = marked.parse(markdown, { renderer }) as string
|
||||||
|
Loading…
Reference in New Issue
Block a user