diff --git a/packages/core/src/utils/themeHelpers.ts b/packages/core/src/utils/themeHelpers.ts
index e1627c89a..79707912d 100644
--- a/packages/core/src/utils/themeHelpers.ts
+++ b/packages/core/src/utils/themeHelpers.ts
@@ -1,6 +1,10 @@
import type { Block, ExtendedProperties, Inline, Theme } from '@md/shared/types'
+
import type { PropertiesHyphen } from 'csstype'
+import { selectorComments } from '@md/shared'
+import { css2json, downloadFile } from '@md/shared/utils'
+
/**
* 自定义主题
* @param theme - 基础主题
@@ -60,27 +64,32 @@ export function customCssWithTemplate(jsonString: Partial `${key}: ${value}`).join(`; `)
}
+
+export function generateThemeCSS(theme: Theme): string {
+ const cssLines: string[] = []
+
+ // 添加注释说明
+ cssLines.push(`/**`)
+ cssLines.push(` * 按 Alt/Option + Shift + F 可格式化`)
+ cssLines.push(` * 如需使用主题色,请使用 var(--md-primary-color) 代替颜色值`)
+ cssLines.push(` * 如:color: var(--md-primary-color);`)
+ cssLines.push(` */`)
+ cssLines.push(``)
+
+ // 生成基础样式(顶层容器)
+ cssLines.push(`/* 顶层容器样式 */`)
+ cssLines.push(`container {`)
+ cssLines.push(`}`)
+ cssLines.push(``)
+
+ // 生成块级元素样式
+ Object.entries(theme.block).forEach(([selector, styles]) => {
+ if (selector !== `container`) {
+ const comment = selectorComments[selector as Block | Inline] || `${selector}样式`
+ cssLines.push(`/* ${comment} */`)
+ cssLines.push(`${selector} {`)
+ Object.entries(styles).forEach(([property, value]) => {
+ if (value) {
+ cssLines.push(` ${property}: ${value};`)
+ }
+ })
+ cssLines.push(`}`)
+ cssLines.push(``)
+ }
+ })
+
+ // 生成内联元素样式
+ Object.entries(theme.inline).forEach(([selector, styles]) => {
+ const comment = selectorComments[selector as Block | Inline] || `${selector}样式`
+ cssLines.push(`/* ${comment} */`)
+ cssLines.push(`${selector} {`)
+ Object.entries(styles).forEach(([property, value]) => {
+ if (value) {
+ cssLines.push(` ${property}: ${value};`)
+ }
+ })
+ cssLines.push(`}`)
+ cssLines.push(``)
+ })
+
+ return cssLines.join(`\n`)
+}
+
+/**
+ * 导出合并后的主题CSS
+ * @param customCSS - 用户自定义的CSS内容
+ * @param baseTheme - 基础主题
+ * @param primaryColor - 主色调
+ * @param fontSize - 字体大小
+ * @param fileName - 导出文件名
+ */
+export function exportMergedTheme(
+ customCSS: string,
+ baseTheme: Theme,
+ primaryColor: string,
+ fontSize: number,
+ fileName: string = `merged-theme`,
+): void {
+ // 将自定义CSS转换为JSON格式
+ const customThemeJson = css2json(customCSS)
+
+ // 使用基础主题和自定义样式合并
+ const customizedTheme = customizeTheme(baseTheme, {
+ fontSize,
+ color: primaryColor,
+ })
+
+ // 使用模板合并自定义CSS
+ const mergedTheme = customCssWithTemplate(
+ customThemeJson,
+ primaryColor,
+ customizedTheme,
+ )
+
+ // 生成最终的CSS内容
+ const finalCSS = generateMergedThemeCSS(mergedTheme)
+
+ // 下载文件
+ downloadFile(finalCSS, `${fileName}.css`, `text/css`)
+}
+
+/**
+ * 生成合并后主题的完整CSS
+ * @param theme - 合并后的主题对象
+ * @returns CSS字符串
+ */
+function generateMergedThemeCSS(theme: Theme): string {
+ const cssLines: string[] = []
+
+ // 添加文件头注释
+ cssLines.push(`/**`)
+ cssLines.push(` * 导出的合并主题CSS`)
+ cssLines.push(` * 包含内置主题和自定义样式的完整合并版本`)
+ cssLines.push(` * 生成时间: ${new Date().toLocaleString(`zh-CN`)}`)
+ cssLines.push(` */`)
+ cssLines.push(``)
+
+ // 添加CSS变量定义
+ cssLines.push(`:root {`)
+ Object.entries(theme.base).forEach(([property, value]) => {
+ cssLines.push(` ${property}: ${value};`)
+ })
+ cssLines.push(`}`)
+ cssLines.push(``)
+
+ // 生成块级元素样式
+ Object.entries(theme.block).forEach(([selector, styles]) => {
+ if (Object.keys(styles).length > 0) {
+ const comment = selectorComments[selector as Block | Inline] || `${selector}样式`
+ cssLines.push(`/* ${comment} */`)
+ cssLines.push(`${selector} {`)
+ Object.entries(styles).forEach(([property, value]) => {
+ if (value) {
+ cssLines.push(` ${property}: ${value};`)
+ }
+ })
+ cssLines.push(`}`)
+ cssLines.push(``)
+ }
+ })
+
+ // 生成内联元素样式
+ Object.entries(theme.inline).forEach(([selector, styles]) => {
+ if (Object.keys(styles).length > 0) {
+ const comment = selectorComments[selector as Block | Inline] || `${selector}样式`
+ cssLines.push(`/* ${comment} */`)
+ cssLines.push(`${selector} {`)
+ Object.entries(styles).forEach(([property, value]) => {
+ if (value) {
+ cssLines.push(` ${property}: ${value};`)
+ }
+ })
+ cssLines.push(`}`)
+ cssLines.push(``)
+ }
+ })
+
+ return cssLines.join(`\n`)
+}
diff --git a/packages/shared/src/configs/theme.ts b/packages/shared/src/configs/theme.ts
index e01b26572..f9d49a4fa 100644
--- a/packages/shared/src/configs/theme.ts
+++ b/packages/shared/src/configs/theme.ts
@@ -1,4 +1,4 @@
-import type { IConfigOption, Theme } from '../types'
+import type { Block, IConfigOption, Inline, Theme } from '../types'
import { toMerged } from 'es-toolkit'
const defaultTheme: Theme = {
@@ -632,6 +632,24 @@ export const themeMap = {
simple: simpleTheme,
}
+export const themeOptionsMap = {
+ default: {
+ label: `经典`,
+ value: `default`,
+ desc: ``,
+ },
+ grace: {
+ label: `优雅`,
+ value: `grace`,
+ desc: `@brzhang`,
+ },
+ simple: {
+ label: `简洁`,
+ value: `simple`,
+ desc: `@okooo5km`,
+ },
+}
+
export const themeOptions: IConfigOption[] = [
{
label: `经典`,
@@ -649,3 +667,64 @@ export const themeOptions: IConfigOption[] = [
desc: `@okooo5km`,
},
]
+
+/**
+ * 选择器注释
+ * 自定义 CSS 编辑器中使用
+ */
+export const selectorComments: Record = {
+ container: `顶层容器样式`,
+ h1: `一级标题样式`,
+ h2: `二级标题样式`,
+ h3: `三级标题样式`,
+ h4: `四级标题样式`,
+ h5: `五级标题样式`,
+ h6: `六级标题样式`,
+ image: `图片样式`,
+ blockquote: `引用样式`,
+ blockquote_p: `引用段落样式`,
+ p: `段落样式`,
+ hr: `分割线样式`,
+ codespan: `行内代码样式`,
+ em: `斜体样式`,
+ strong: `粗体样式`,
+ link: `链接样式`,
+ wx_link: `微信链接样式`,
+ ol: `有序列表样式`,
+ ul: `无序列表样式`,
+ listitem: `列表项样式`,
+ code: `代码块样式`,
+ code_pre: `代码块外层样式`,
+ inline_katex: `行内公式样式`,
+ block_katex: `公式块样式`,
+ table: `表格样式`,
+ thead: `表头样式`,
+ th: `表头单元格样式`,
+ td: `表格单元格样式`,
+ footnotes: `脚注样式`,
+ figure: `图表样式`,
+ figcaption: `图表标题样式`,
+ footnote: `脚注引用样式`,
+ blockquote_note: `GFM note 样式`,
+ blockquote_tip: `GFM tip 样式`,
+ blockquote_info: `GFM info 样式`,
+ blockquote_important: `GFM important 样式`,
+ blockquote_warning: `GFM warning 样式`,
+ blockquote_caution: `GFM caution 样式`,
+ blockquote_title: `GFM 通用标题`,
+ blockquote_title_note: `GFM note 标题`,
+ blockquote_title_tip: `GFM tip 标题`,
+ blockquote_title_info: `GFM info 标题`,
+ blockquote_title_important: `GFM important 标题`,
+ blockquote_title_warning: `GFM warning 标题`,
+ blockquote_title_caution: `GFM caution 标题`,
+ blockquote_p_note: `GFM note 段落样式`,
+ blockquote_p_tip: `GFM tip 段落样式`,
+ blockquote_p_info: `GFM info 段落样式`,
+ blockquote_p_important: `GFM important 段落样式`,
+ blockquote_p_warning: `GFM warning 段落样式`,
+ blockquote_p_caution: `GFM caution 段落样式`,
+ markup_highlight: `高亮标记样式`,
+ markup_underline: `下划线标记样式`,
+ markup_wavyline: `波浪线标记样式`,
+}