优化模版
This commit is contained in:
parent
cdca9d4d3f
commit
c2a8ebbd01
@ -1,63 +0,0 @@
|
||||
import { Template } from '@/types/template'
|
||||
|
||||
export const templates: Template[] = [
|
||||
{
|
||||
id: 'wechat',
|
||||
name: '微信公众号',
|
||||
styles: 'wechat-template',
|
||||
subTemplates: [
|
||||
{
|
||||
id: 'default',
|
||||
name: '默认样式',
|
||||
styles: 'wechat-default',
|
||||
transform: (content: string) => {
|
||||
return content
|
||||
.replace(/<h1>/g, '<h1 style="font-size: 24px; font-weight: bold; margin-bottom: 1em;">')
|
||||
.replace(/<p>/g, '<p style="margin-bottom: 1em; color: #333; line-height: 1.75;">')
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'elegant',
|
||||
name: '优雅简约',
|
||||
styles: 'wechat-elegant',
|
||||
transform: (content: string) => {
|
||||
return content
|
||||
.replace(/<h1>/g, '<h1 style="font-size: 26px; font-weight: 600; margin-bottom: 1.2em; color: #2c3e50;">')
|
||||
.replace(/<p>/g, '<p style="margin-bottom: 1.2em; color: #34495e; line-height: 1.8; letter-spacing: 0.05em;">')
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'modern',
|
||||
name: '现代商务',
|
||||
styles: 'wechat-modern',
|
||||
transform: (content: string) => {
|
||||
return content
|
||||
.replace(/<h1>/g, '<h1 style="font-size: 28px; font-weight: bold; margin-bottom: 1em; color: #1a202c; border-bottom: 2px solid #e2e8f0; padding-bottom: 0.5em;">')
|
||||
.replace(/<p>/g, '<p style="margin-bottom: 1.1em; color: #4a5568; line-height: 1.85; font-size: 16px;">')
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'creative',
|
||||
name: '创意活力',
|
||||
styles: 'wechat-creative',
|
||||
transform: (content: string) => {
|
||||
return content
|
||||
.replace(/<h1>/g, '<h1 style="font-size: 24px; font-weight: bold; margin-bottom: 1em; color: #2d3748; background: linear-gradient(to right, #4299e1, #667eea); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">')
|
||||
.replace(/<p>/g, '<p style="margin-bottom: 1em; color: #4a5568; line-height: 1.75; border-left: 3px solid #4299e1; padding-left: 1em;">')
|
||||
}
|
||||
}
|
||||
],
|
||||
transform: (content: string) => content // 默认转换
|
||||
},
|
||||
{
|
||||
id: 'xiaohongshu',
|
||||
name: '小红书',
|
||||
styles: 'xiaohongshu-template',
|
||||
transform: (content: string) => {
|
||||
// 小红书特定的转换逻辑
|
||||
return content
|
||||
.replace(/<h1>/g, '<h1 style="font-size: 20px; font-weight: bold; margin-bottom: 0.5em;">')
|
||||
.replace(/<p>/g, '<p style="margin-bottom: 0.8em; color: #222; line-height: 1.6;">')
|
||||
}
|
||||
}
|
||||
]
|
@ -158,14 +158,7 @@ export const templates: Template[] = [
|
||||
}
|
||||
}
|
||||
},
|
||||
transform: (html) => `
|
||||
<section style="font-family: 'Georgia', serif;">
|
||||
<style>
|
||||
:root { --md-primary-color: #16a34a; }
|
||||
</style>
|
||||
${html}
|
||||
</section>
|
||||
`
|
||||
transform: (html) => html
|
||||
},
|
||||
{
|
||||
id: 'modern',
|
||||
@ -233,13 +226,8 @@ export const templates: Template[] = [
|
||||
}
|
||||
}
|
||||
},
|
||||
transform: (html) => `
|
||||
<section style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;">
|
||||
<div style="max-width: 100%; margin: 0 auto; color: #374151;">
|
||||
${html}
|
||||
</div>
|
||||
</section>
|
||||
`
|
||||
transform: (html) => html
|
||||
|
||||
},
|
||||
{
|
||||
id: 'creative',
|
||||
@ -376,10 +364,98 @@ export const templates: Template[] = [
|
||||
}
|
||||
}
|
||||
},
|
||||
transform: (html) => `
|
||||
<section style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;">
|
||||
${html}
|
||||
</section>
|
||||
`
|
||||
transform: (html) => html
|
||||
|
||||
},
|
||||
{
|
||||
id: 'ios-notes',
|
||||
name: '备忘录风格',
|
||||
description: '仿 iOS 备忘录风格',
|
||||
styles: 'prose-ios-notes',
|
||||
options: {
|
||||
base: {
|
||||
primaryColor: '#FF9500',
|
||||
textAlign: 'left',
|
||||
lineHeight: '1.6'
|
||||
},
|
||||
block: {
|
||||
h1: {
|
||||
fontSize: '24px',
|
||||
color: '#1C1C1E',
|
||||
margin: '32px 0 16px',
|
||||
fontWeight: '600',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Text"'
|
||||
},
|
||||
h2: {
|
||||
fontSize: '20px',
|
||||
color: '#1C1C1E',
|
||||
margin: '24px 0 12px',
|
||||
fontWeight: '600',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Text"'
|
||||
},
|
||||
h3: {
|
||||
fontSize: '18px',
|
||||
color: '#1C1C1E',
|
||||
margin: '20px 0 10px',
|
||||
fontWeight: '600',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Text"'
|
||||
},
|
||||
p: {
|
||||
fontSize: '17px',
|
||||
color: '#333333',
|
||||
margin: '16px 0',
|
||||
lineHeight: 1.6,
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro Text"'
|
||||
},
|
||||
blockquote: {
|
||||
fontSize: '17px',
|
||||
color: '#666666',
|
||||
borderLeft: '4px solid #FF9500',
|
||||
background: '#FAFAFA',
|
||||
padding: '12px 16px',
|
||||
margin: '16px 0',
|
||||
borderRadius: '4px'
|
||||
},
|
||||
code_pre: {
|
||||
fontSize: '15px',
|
||||
background: '#F2F2F7',
|
||||
padding: '12px 16px',
|
||||
borderRadius: '8px',
|
||||
margin: '16px 0',
|
||||
fontFamily: 'Menlo, Monaco, "SF Mono", monospace'
|
||||
},
|
||||
ul: {
|
||||
paddingLeft: '24px',
|
||||
margin: '16px 0'
|
||||
},
|
||||
ol: {
|
||||
paddingLeft: '24px',
|
||||
margin: '16px 0'
|
||||
}
|
||||
},
|
||||
inline: {
|
||||
strong: {
|
||||
color: '#1C1C1E',
|
||||
fontWeight: '600'
|
||||
},
|
||||
em: {
|
||||
color: '#666666',
|
||||
fontStyle: 'italic'
|
||||
},
|
||||
link: {
|
||||
color: '#007AFF',
|
||||
textDecoration: 'none'
|
||||
},
|
||||
codespan: {
|
||||
color: '#E73C3E',
|
||||
background: '#F2F2F7',
|
||||
padding: '2px 6px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '90%',
|
||||
fontFamily: 'Menlo, Monaco, "SF Mono", monospace'
|
||||
}
|
||||
}
|
||||
},
|
||||
transform: (html) => html
|
||||
}
|
||||
]
|
@ -40,8 +40,11 @@ function baseStylesToString(base: RendererOptions['base'] = {}): string {
|
||||
|
||||
// 预处理函数
|
||||
function preprocessMarkdown(markdown: string): string {
|
||||
// 处理 ** 语法,但排除已经是 HTML 的部分
|
||||
return markdown.replace(/(?<!<[^>]*)\*\*([^*]+)\*\*(?![^<]*>)/g, '<strong>$1</strong>')
|
||||
return markdown
|
||||
// 处理 ** 语法,但排除已经是 HTML 的部分
|
||||
.replace(/(?<!<[^>]*)\*\*([^*]+)\*\*(?![^<]*>)/g, '<strong>$1</strong>')
|
||||
// 处理无序列表的 - 标记,但排除代码块内的部分
|
||||
.replace(/^(?!\s*```)([ \t]*)-\s+/gm, '$1• ')
|
||||
}
|
||||
|
||||
// Initialize marked instance
|
||||
@ -129,23 +132,49 @@ export function convertToWechat(markdown: string, options: RendererOptions = {})
|
||||
return `<img src="${href}"${title ? ` title="${title}"` : ''} alt="${text}"${styleStr ? ` style="${styleStr}"` : ''} />`
|
||||
}
|
||||
|
||||
customRenderer.list = function(body: Tokens.List) {
|
||||
const ordered = body.ordered
|
||||
const tag = ordered ? 'ol' : 'ul'
|
||||
const style = options.block?.[ordered ? 'ol' : 'ul']
|
||||
const styleStr = cssPropertiesToString(style)
|
||||
const tokens = marked.Lexer.lexInline(body.raw)
|
||||
const content = marked.Parser.parseInline(tokens, { renderer: customRenderer })
|
||||
return `<${tag}${styleStr ? ` style="${styleStr}"` : ''}>${content}</${tag}>`
|
||||
}
|
||||
// 重写 list 方法
|
||||
customRenderer.list = function(token: Tokens.List): string {
|
||||
const tag = token.ordered ? 'ol' : 'ul'
|
||||
try {
|
||||
const style = options.block?.[token.ordered ? 'ol' : 'ul']
|
||||
const styleStr = cssPropertiesToString(style)
|
||||
const startAttr = token.ordered && token.start !== 1 ? ` start="${token.start}"` : ''
|
||||
|
||||
return `<${tag}${startAttr}${styleStr ? ` style="${styleStr}"` : ''}>${token.items.map(item => customRenderer.listitem(item)).join('')}</${tag}>`
|
||||
} catch (error) {
|
||||
console.error(`Error rendering list: ${error}`)
|
||||
return `<${tag}>${token.items.map(item => customRenderer.listitem(item)).join('')}</${tag}>`
|
||||
}
|
||||
}
|
||||
|
||||
customRenderer.listitem = function(item: Tokens.ListItem) {
|
||||
const style = options.inline?.listitem
|
||||
const styleStr = cssPropertiesToString(style)
|
||||
const tokens = marked.Lexer.lexInline(item.text)
|
||||
const content = marked.Parser.parseInline(tokens, { renderer: customRenderer })
|
||||
return `<li${styleStr ? ` style="${styleStr}"` : ''}>${content}</li>`
|
||||
// 重写 listitem 方法
|
||||
customRenderer.listitem = function(item: Tokens.ListItem) {
|
||||
try {
|
||||
const style = options.inline?.listitem
|
||||
const styleStr = cssPropertiesToString(style)
|
||||
|
||||
// 移除列表项开头的破折号和空格
|
||||
let itemText = item.text.replace(/^- /, '')
|
||||
|
||||
// 处理任务列表项
|
||||
if (item.task) {
|
||||
const checkbox = `<input type="checkbox"${item.checked ? ' checked=""' : ''} disabled="" /> `
|
||||
itemText = checkbox + itemText
|
||||
}
|
||||
|
||||
// 使用 Lexer 和 Parser 处理剩余的内联标记
|
||||
const tokens = marked.Lexer.lexInline(itemText)
|
||||
const content = marked.Parser.parseInline(tokens, { renderer: customRenderer })
|
||||
|
||||
return `<li${styleStr ? ` style="${styleStr}"` : ''}>${content}</li>`
|
||||
} catch (error) {
|
||||
console.error(`Error rendering list item: ${error}`)
|
||||
return `<li>${item.text}</li>`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Convert Markdown to HTML using the custom renderer
|
||||
const html = marked.parse(markdown, { renderer: customRenderer }) as string
|
||||
|
Loading…
Reference in New Issue
Block a user