Compare commits

..

No commits in common. "0375954bfc09511322419f5ebd629227cca3f693" and "5e2535f143dd31edf488379d2046b02205284185" have entirely different histories.

6 changed files with 74 additions and 131 deletions

View File

@ -33,53 +33,29 @@ blockquote {
/* 引用段落样式 */ /* 引用段落样式 */
blockquote_p { blockquote_p {
} }
/* GFM note 样式 */ /* GFM 警告块 */
blockquote_note { markdown-alert {
} }
/* GFM tip 样式 */ /* GFM 警告块标题 */
blockquote_tip { markdown-alert-title {
} }
/* GFM important 样式 */ /* GFM 警告块内容,抵消 p 默认的 margin */
blockquote_important { markdown-alert-content-wrapper {
} }
/* GFM warning 样式 */ /* GFM note */
blockquote_warning { markdown-alert-title-note {
} }
/* GFM caution 样式 */ /* GFM tip */
blockquote_caution { markdown-alert-title-tip {
} }
/* GFM 通用标题 */ /* GFM important */
blockquote_title { markdown-alert-title-important {
} }
/* GFM note 标题 */ /* GFM warning */
blockquote_title_note { markdown-alert-title-warning {
} }
/* GFM tip 标题 */ /* GFM caution */
blockquote_title_tip { markdown-alert-title-caution {
}
/* GFM important 标题 */
blockquote_title_important {
}
/* GFM warning 标题 */
blockquote_title_warning {
}
/* GFM caution 标题 */
blockquote_title_caution {
}
/* GFM note 段落样式 */
blockquote_p_note {
}
/* GFM tip 段落样式 */
blockquote_p_tip {
}
/* GFM important 段落样式 */
blockquote_p_important {
}
/* GFM warning 段落样式 */
blockquote_p_warning {
}
/* GFM caution 段落样式 */
blockquote_p_caution {
} }
/* 段落样式 */ /* 段落样式 */
p { p {

View File

@ -10,7 +10,7 @@ const defaultTheme: Theme = {
}, },
block: { block: {
// 一级标题 // 一级标题
h1: { 'h1': {
'display': `table`, 'display': `table`,
'padding': `0 1em`, 'padding': `0 1em`,
'border-bottom': `2px solid var(--md-primary-color)`, 'border-bottom': `2px solid var(--md-primary-color)`,
@ -22,7 +22,7 @@ const defaultTheme: Theme = {
}, },
// 二级标题 // 二级标题
h2: { 'h2': {
'display': `table`, 'display': `table`,
'padding': `0 0.2em`, 'padding': `0 0.2em`,
'margin': `4em auto 2em`, 'margin': `4em auto 2em`,
@ -34,7 +34,7 @@ const defaultTheme: Theme = {
}, },
// 三级标题 // 三级标题
h3: { 'h3': {
'padding-left': `8px`, 'padding-left': `8px`,
'border-left': `3px solid var(--md-primary-color)`, 'border-left': `3px solid var(--md-primary-color)`,
'margin': `2em 8px 0.75em 0`, 'margin': `2em 8px 0.75em 0`,
@ -45,7 +45,7 @@ const defaultTheme: Theme = {
}, },
// 四级标题 // 四级标题
h4: { 'h4': {
'margin': `2em 8px 0.5em`, 'margin': `2em 8px 0.5em`,
'color': `var(--md-primary-color)`, 'color': `var(--md-primary-color)`,
'font-size': `1em`, 'font-size': `1em`,
@ -53,7 +53,7 @@ const defaultTheme: Theme = {
}, },
// 五级标题 // 五级标题
h5: { 'h5': {
'margin': `1.5em 8px 0.5em`, 'margin': `1.5em 8px 0.5em`,
'color': `var(--md-primary-color)`, 'color': `var(--md-primary-color)`,
'font-size': `1em`, 'font-size': `1em`,
@ -61,14 +61,14 @@ const defaultTheme: Theme = {
}, },
// 六级标题 // 六级标题
h6: { 'h6': {
'margin': `1.5em 8px 0.5em`, 'margin': `1.5em 8px 0.5em`,
'font-size': `1em`, 'font-size': `1em`,
'color': `var(--md-primary-color)`, 'color': `var(--md-primary-color)`,
}, },
// 段落 // 段落
p: { 'p': {
'margin': `1.5em 8px`, 'margin': `1.5em 8px`,
'letter-spacing': `0.1em`, 'letter-spacing': `0.1em`,
'color': `var(--el-text-color-regular)`, 'color': `var(--el-text-color-regular)`,
@ -76,7 +76,7 @@ const defaultTheme: Theme = {
}, },
// 引用 // 引用
blockquote: { 'blockquote': {
'font-style': `normal`, 'font-style': `normal`,
'border-left': `none`, 'border-left': `none`,
'padding': `1em`, 'padding': `1em`,
@ -87,73 +87,57 @@ const defaultTheme: Theme = {
}, },
// 引用内容 // 引用内容
blockquote_p: { 'blockquote_p': {
'display': `block`, 'display': `block`,
'font-size': `1em`, 'font-size': `1em`,
'letter-spacing': `0.1em`, 'letter-spacing': `0.1em`,
'color': `var(--el-text-color-regular)`, 'color': `var(--el-text-color-regular)`,
}, },
blockquote_note: { // GFM 警告块
}, 'markdown-alert': {
'font-style': `normal`,
blockquote_tip: { 'border-left': `none`,
}, 'padding': `1em`,
'border-radius': `8px`,
blockquote_important: { 'background': `var(--blockquote-background)`,
}, 'margin': `2em 8px`,
blockquote_warning: {
},
blockquote_caution: {
}, },
// GFM 警告块标题 // GFM 警告块标题
blockquote_title: { 'markdown-alert-title': {
'display': `flex`, 'display': `flex`,
'align-items': `center`, 'align-items': `center`,
'gap': `0.5em`, 'gap': `0.5em`,
'margin-bottom': `0.5em`,
}, },
blockquote_title_note: { // GFM 警告块内容,抵消 p 默认的 margin
'markdown-alert-content-wrapper': {
margin: `-1em -8px -1.5em;`,
},
'markdown-alert-title-note': {
color: `#478be6`, color: `#478be6`,
}, },
blockquote_title_tip: { 'markdown-alert-title-tip': {
color: `#57ab5a`, color: `#57ab5a`,
}, },
blockquote_title_important: { 'markdown-alert-title-important': {
color: `#986ee2`, color: `#986ee2`,
}, },
blockquote_title_warning: { 'markdown-alert-title-warning': {
color: `#c69026`, color: `#c69026`,
}, },
blockquote_title_caution: { 'markdown-alert-title-caution': {
color: `#e5534b`, color: `#e5534b`,
}, },
blockquote_p_note: {
},
blockquote_p_tip: {
},
blockquote_p_important: {
},
blockquote_p_warning: {
},
blockquote_p_caution: {
},
// 代码块 // 代码块
code_pre: { 'code_pre': {
'font-size': `14px`, 'font-size': `14px`,
'overflow-x': `auto`, 'overflow-x': `auto`,
'border-radius': `8px`, 'border-radius': `8px`,
@ -163,14 +147,14 @@ const defaultTheme: Theme = {
}, },
// 行内代码 // 行内代码
code: { 'code': {
'margin': 0, 'margin': 0,
'white-space': `nowrap`, 'white-space': `nowrap`,
'font-family': `Menlo, Operator Mono, Consolas, Monaco, monospace`, 'font-family': `Menlo, Operator Mono, Consolas, Monaco, monospace`,
}, },
// 图片 // 图片
image: { 'image': {
'display': `block`, 'display': `block`,
'width': `100% !important`, 'width': `100% !important`,
'margin': `0.1em auto 0.5em`, 'margin': `0.1em auto 0.5em`,
@ -178,32 +162,32 @@ const defaultTheme: Theme = {
}, },
// 有序列表 // 有序列表
ol: { 'ol': {
'padding-left': `1em`, 'padding-left': `1em`,
'margin-left': `0`, 'margin-left': `0`,
'color': `var(--el-text-color-regular)`, 'color': `var(--el-text-color-regular)`,
}, },
// 无序列表 // 无序列表
ul: { 'ul': {
'list-style': `circle`, 'list-style': `circle`,
'padding-left': `1em`, 'padding-left': `1em`,
'margin-left': `0`, 'margin-left': `0`,
'color': `var(--el-text-color-regular)`, 'color': `var(--el-text-color-regular)`,
}, },
footnotes: { 'footnotes': {
'margin': `0.5em 8px`, 'margin': `0.5em 8px`,
'font-size': `80%`, 'font-size': `80%`,
'color': `var(--el-text-color-regular)`, 'color': `var(--el-text-color-regular)`,
}, },
figure: { 'figure': {
margin: `1.5em 8px`, margin: `1.5em 8px`,
color: `var(--el-text-color-regular)`, color: `var(--el-text-color-regular)`,
}, },
hr: { 'hr': {
'border-style': `solid`, 'border-style': `solid`,
'border-width': `1px 0 0`, 'border-width': `1px 0 0`,
'border-color': `rgba(0,0,0,0.1)`, 'border-color': `rgba(0,0,0,0.1)`,

View File

@ -2,8 +2,7 @@ import type { PropertiesHyphen } from 'csstype'
import type { Token } from 'marked' import type { Token } from 'marked'
type GFMBlock = `blockquote_note` | `blockquote_tip` | `blockquote_important` | `blockquote_warning` | `blockquote_caution` | `blockquote_title` | `blockquote_title_note` | `blockquote_title_tip` | `blockquote_title_important` | `blockquote_title_warning` | `blockquote_title_caution` | `blockquote_p` | `blockquote_p_note` | `blockquote_p_tip` | `blockquote_p_important` | `blockquote_p_warning` | `blockquote_p_caution` export type Block = `h1` | `h2` | `h3` | `h4` | `h5` | `h6` | `p` | `blockquote` | `blockquote_p` | `code_pre` | `code` | `image` | `ol` | `ul` | `footnotes` | `figure` | `hr`
export type Block = `h1` | `h2` | `h3` | `h4` | `h5` | `h6` | `p` | `blockquote` | `blockquote_p` | `code_pre` | `code` | `image` | `ol` | `ul` | `footnotes` | `figure` | `hr` | GFMBlock
export type Inline = `listitem` | `codespan` | `link` | `wx_link` | `strong` | `table` | `thead` | `td` | `footnote` | `figcaption` | `em` export type Inline = `listitem` | `codespan` | `link` | `wx_link` | `strong` | `table` | `thead` | `td` | `footnote` | `figcaption` | `em`
interface CustomCSSProperties { interface CustomCSSProperties {
@ -15,8 +14,8 @@ export type ExtendedProperties = PropertiesHyphen & CustomCSSProperties
export interface Theme { export interface Theme {
base: ExtendedProperties base: ExtendedProperties
block: Record<Block, ExtendedProperties> block: Record<Block | string, ExtendedProperties>
inline: Record<Inline, ExtendedProperties> inline: Record<Inline | string, ExtendedProperties>
} }
export interface IOpts { export interface IOpts {
@ -42,7 +41,7 @@ export interface IConfigOption<VT = string> {
export interface AlertOptions { export interface AlertOptions {
className?: string className?: string
variants?: AlertVariantItem[] variants?: AlertVariantItem[]
styles?: ThemeStyles theme?: Theme
} }
/** /**

View File

@ -29,8 +29,6 @@ export default function markedAlert(options: AlertOptions = {}): MarkedExtension
} = matchedVariant } = matchedVariant
const typeRegexp = new RegExp(createSyntaxPattern(variantType), `i`) const typeRegexp = new RegExp(createSyntaxPattern(variantType), `i`)
const { styles } = options
Object.assign(token, { Object.assign(token, {
type: `alert`, type: `alert`,
meta: { meta: {
@ -39,21 +37,25 @@ export default function markedAlert(options: AlertOptions = {}): MarkedExtension
icon, icon,
title, title,
titleClassName, titleClassName,
wrapperStyle: { style: {
...styles?.blockquote, ...options.theme?.block[className],
...styles?.[`blockquote_${variantType}` as keyof typeof styles], ...options.theme?.block[`${className}-${variantType}`],
}, },
titleStyle: { titleStyle: {
...styles?.blockquote_title, ...options.theme?.block[titleClassName],
...styles?.[`blockquote_title_${variantType}` as keyof typeof styles], ...options.theme?.block[`${titleClassName}-${variantType}`],
}, },
contentStyle: { contentWrapperStyle: {
...styles?.blockquote_p, margin: options.theme?.block[`${className}-content-wrapper`]?.margin,
...styles?.[`blockquote_p_${variantType}` as keyof typeof styles],
}, },
}, },
}) })
console.log({
...options.theme?.block[className],
...options.theme?.block[`${className}-${variantType}`],
}, `style`)
const firstLine = token.tokens?.[0] as Tokens.Paragraph const firstLine = token.tokens?.[0] as Tokens.Paragraph
const firstLineText = firstLine.raw?.replace(typeRegexp, ``).trim() const firstLineText = firstLine.raw?.replace(typeRegexp, ``).trim()
@ -79,17 +81,15 @@ export default function markedAlert(options: AlertOptions = {}): MarkedExtension
name: `alert`, name: `alert`,
level: `block`, level: `block`,
renderer({ meta, tokens = [] }) { renderer({ meta, tokens = [] }) {
let text = this.parser.parse(tokens) let tmpl = `<blockquote class="${meta.className} ${meta.className}-${meta.variant}" style='${getStyleString(meta.style)}'>\n`
text = text.replace(/<p .*?>/g, `<p style="${getStyleString(meta.contentStyle)}">`) tmpl += `<p class="${meta.titleClassName}" style='${getStyleString(meta.titleStyle)}'>`
let tmpl = `<blockquote class="${meta.className} ${meta.className}-${meta.variant}" style="${getStyleString(meta.wrapperStyle)}">\n`
tmpl += `<p class="${meta.titleClassName}" style="${getStyleString(meta.titleStyle)}">`
tmpl += meta.icon.replace( tmpl += meta.icon.replace(
`<svg`, `<svg`,
`<svg style="fill: ${meta.titleStyle?.color ?? `inherit`}"`, `<svg style="fill: ${meta.titleStyle?.color ?? `inherit`}"`,
) )
tmpl += meta.title tmpl += meta.title
tmpl += `</p>\n` tmpl += `</p>\n`
tmpl += text tmpl += `<span style="${`${getStyleString(meta.contentWrapperStyle)} display: block;`}">${this.parser.parse(tokens)}</span>`
tmpl += `</blockquote>\n` tmpl += `</blockquote>\n`
return tmpl return tmpl
@ -121,7 +121,7 @@ const defaultAlertVariant: AlertVariantItem[] = [
}, },
{ {
type: `caution`, type: `caution`,
icon: `<svg class="octicon octicon-stop" style="margin-right: 0.25em;" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>`, icon: `<svg class="octicon octicon-stop mr-2" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>`,
}, },
] ]

View File

@ -34,7 +34,7 @@ export function customizeTheme(theme: Theme, options: {
export function customCssWithTemplate(jsonString: Partial<Record<Block | Inline, PropertiesHyphen>>, color: string, theme: Theme) { export function customCssWithTemplate(jsonString: Partial<Record<Block | Inline, PropertiesHyphen>>, color: string, theme: Theme) {
const newTheme = customizeTheme(theme, { color }) const newTheme = customizeTheme(theme, { color })
const mergeProperties = <T extends Block | Inline = Block>(target: Record<T, PropertiesHyphen>, source: Partial<Record<Block | Inline | string, PropertiesHyphen>>, keys: T[]) => { const mergeProperties = <T extends Block | Inline = Block>(target: Record<T, PropertiesHyphen>, source: Partial<Record<Block | Inline, PropertiesHyphen>>, keys: T[]) => {
keys.forEach((key) => { keys.forEach((key) => {
if (source[key]) { if (source[key]) {
target[key] = Object.assign(target[key] || {}, source[key]) target[key] = Object.assign(target[key] || {}, source[key])
@ -54,23 +54,7 @@ export function customCssWithTemplate(jsonString: Partial<Record<Block | Inline,
`p`, `p`,
`hr`, `hr`,
`blockquote`, `blockquote`,
`blockquote_note`,
`blockquote_tip`,
`blockquote_important`,
`blockquote_warning`,
`blockquote_caution`,
`blockquote_p`, `blockquote_p`,
`blockquote_p_note`,
`blockquote_p_tip`,
`blockquote_p_important`,
`blockquote_p_warning`,
`blockquote_p_caution`,
`blockquote_title`,
`blockquote_title_note`,
`blockquote_title_tip`,
`blockquote_title_important`,
`blockquote_title_warning`,
`blockquote_title_caution`,
`image`, `image`,
`ul`, `ul`,
`ol`, `ol`,

View File

@ -126,7 +126,7 @@ export function initRenderer(opts: IOpts) {
function setOptions(newOpts: Partial<IOpts>): void { function setOptions(newOpts: Partial<IOpts>): void {
opts = { ...opts, ...newOpts } opts = { ...opts, ...newOpts }
styleMapping = buildTheme(opts) styleMapping = buildTheme(opts)
marked.use(markedAlert({ styles: styleMapping })) marked.use(markedAlert({ theme: opts.theme }))
} }
const buildFootnotes = () => { const buildFootnotes = () => {