md2xhs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +622 -0
- package/dist/assets/auto-render.min.js +1 -0
- package/dist/assets/katex.min.css +1 -0
- package/dist/assets/katex.min.js +1 -0
- package/dist/assets/mermaid.min.js +1646 -0
- package/dist/assets-loader.d.ts +27 -0
- package/dist/assets-loader.js +55 -0
- package/dist/converter.d.ts +87 -0
- package/dist/converter.js +421 -0
- package/dist/extensions.d.ts +20 -0
- package/dist/extensions.js +2 -0
- package/dist/file-utils.d.ts +21 -0
- package/dist/file-utils.js +69 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +24 -0
- package/dist/styles.d.ts +21 -0
- package/dist/styles.js +250 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.js +15 -0
- package/package.json +53 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isFile = isFile;
|
|
4
|
+
exports.isDirectory = isDirectory;
|
|
5
|
+
exports.readMarkdownFile = readMarkdownFile;
|
|
6
|
+
exports.getMarkdownFiles = getMarkdownFiles;
|
|
7
|
+
exports.generateOutputPath = generateOutputPath;
|
|
8
|
+
const promises_1 = require("fs/promises");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
/**
|
|
11
|
+
* 判断路径是否为文件
|
|
12
|
+
*/
|
|
13
|
+
async function isFile(path) {
|
|
14
|
+
try {
|
|
15
|
+
const stats = await (0, promises_1.stat)(path);
|
|
16
|
+
return stats.isFile();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 判断路径是否为目录
|
|
24
|
+
*/
|
|
25
|
+
async function isDirectory(path) {
|
|
26
|
+
try {
|
|
27
|
+
const stats = await (0, promises_1.stat)(path);
|
|
28
|
+
return stats.isDirectory();
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 读取 Markdown 文件内容
|
|
36
|
+
*/
|
|
37
|
+
async function readMarkdownFile(filePath) {
|
|
38
|
+
const content = await (0, promises_1.readFile)(filePath, 'utf-8');
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 获取目录中所有的 Markdown 文件
|
|
43
|
+
*/
|
|
44
|
+
async function getMarkdownFiles(dirPath, recursive = false) {
|
|
45
|
+
const files = [];
|
|
46
|
+
async function scan(dir) {
|
|
47
|
+
const entries = await (0, promises_1.readdir)(dir, { withFileTypes: true });
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const fullPath = (0, path_1.join)(dir, entry.name);
|
|
50
|
+
if (entry.isFile() && (0, path_1.extname)(entry.name).toLowerCase() === '.md') {
|
|
51
|
+
files.push(fullPath);
|
|
52
|
+
}
|
|
53
|
+
else if (entry.isDirectory() && recursive) {
|
|
54
|
+
await scan(fullPath);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
await scan(dirPath);
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 生成输出文件路径
|
|
63
|
+
* 例如: './docs/README.md' -> './docs/README.png'
|
|
64
|
+
*/
|
|
65
|
+
function generateOutputPath(inputPath, outputDir) {
|
|
66
|
+
const baseName = (0, path_1.basename)(inputPath, (0, path_1.extname)(inputPath));
|
|
67
|
+
const dir = outputDir || (0, path_1.dirname)(inputPath);
|
|
68
|
+
return (0, path_1.join)(dir, `${baseName}.png`);
|
|
69
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.default = void 0;
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
__exportStar(require("./converter"), exports);
|
|
20
|
+
__exportStar(require("./styles"), exports);
|
|
21
|
+
__exportStar(require("./file-utils"), exports);
|
|
22
|
+
// 默认导出
|
|
23
|
+
var converter_1 = require("./converter");
|
|
24
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return converter_1.Md2ImageConverter; } });
|
package/dist/styles.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BackgroundPreset, CustomBackground } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* CSS 变量定义
|
|
4
|
+
*/
|
|
5
|
+
export declare const CSS_VARIABLES = "\n:root {\n --primary-color: #6366f1;\n --primary-hover: #4f46e5;\n --secondary-color: #8b5cf6;\n --text-primary: #1e293b;\n --text-secondary: #334155;\n --text-muted: #64748b;\n --text-light: #475569;\n --background-light: #f8fafc;\n --background-gray: #f1f5f9;\n --border-color: #e2e8f0;\n --border-light: #cbd5e1;\n --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);\n --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);\n --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.1);\n --border-radius: 8px;\n --border-radius-lg: 12px;\n --font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;\n}\n";
|
|
6
|
+
/**
|
|
7
|
+
* 背景预设样式
|
|
8
|
+
*/
|
|
9
|
+
export declare const BACKGROUND_PRESETS: Record<BackgroundPreset, string>;
|
|
10
|
+
/**
|
|
11
|
+
* 完整样式表
|
|
12
|
+
*/
|
|
13
|
+
export declare const FULL_STYLES = "\n\n:root {\n --primary-color: #6366f1;\n --primary-hover: #4f46e5;\n --secondary-color: #8b5cf6;\n --text-primary: #1e293b;\n --text-secondary: #334155;\n --text-muted: #64748b;\n --text-light: #475569;\n --background-light: #f8fafc;\n --background-gray: #f1f5f9;\n --border-color: #e2e8f0;\n --border-light: #cbd5e1;\n --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);\n --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);\n --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.1);\n --border-radius: 8px;\n --border-radius-lg: 12px;\n --font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;\n}\n\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n background: var(--background-light);\n color: var(--text-secondary);\n line-height: 1.6;\n}\n\n.markdown-poster {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n border-radius: 0;\n padding: 40px;\n margin: 20px;\n box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n width: 640px;\n min-height: 600px;\n position: relative;\n overflow: hidden;\n box-sizing: border-box;\n}\n\n.markdown-poster::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 0;\n pointer-events: none;\n}\n\n.poster-content {\n background: rgba(255, 255, 255, 0.95) !important;\n border-radius: 12px;\n padding: 40px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);\n backdrop-filter: blur(10px);\n position: relative;\n z-index: 1;\n overflow: hidden;\n word-wrap: break-word;\n min-height: 400px;\n}\n\n.poster-content img {\n max-width: 100%;\n height: auto;\n border-radius: var(--border-radius);\n margin: 16px auto;\n box-shadow: var(--shadow-md);\n display: block;\n object-fit: cover;\n}\n\n.poster-content h1 {\n font-size: var(--dynamic-h1-size, 28px);\n font-weight: 700;\n color: var(--text-primary);\n margin-bottom: 16px;\n line-height: 1.3;\n}\n\n.poster-content h2 {\n font-size: var(--dynamic-h2-size, 22px);\n font-weight: 600;\n color: var(--text-secondary);\n margin: 24px 0 12px 0;\n line-height: 1.4;\n}\n\n.poster-content h3 {\n font-size: var(--dynamic-h3-size, 18px);\n font-weight: 600;\n color: var(--text-light);\n margin: 20px 0 8px 0;\n}\n\n.poster-content p {\n font-size: var(--dynamic-font-size, 16px);\n color: var(--text-light);\n margin-bottom: 16px;\n line-height: 1.7;\n}\n\n.poster-content em {\n font-style: italic;\n color: var(--primary-color);\n}\n\n.poster-content strong {\n font-weight: 700;\n color: var(--text-primary);\n}\n\n.poster-content a {\n color: var(--primary-color);\n text-decoration: none;\n border-bottom: 1px solid var(--primary-color);\n}\n\n.poster-content ul,\n.poster-content ol {\n margin: 16px 0;\n padding-left: 24px;\n}\n\n.poster-content li {\n font-size: var(--dynamic-font-size, 16px);\n color: var(--text-light);\n margin-bottom: 8px;\n line-height: 1.6;\n}\n\n.poster-content blockquote {\n border-left: 4px solid var(--primary-color);\n padding-left: 16px;\n background: var(--background-gray);\n padding-top: 12px;\n padding-bottom: 12px;\n margin: 16px 0;\n color: var(--text-muted);\n font-style: italic;\n font-size: var(--dynamic-quote-size, 16px);\n}\n\n.poster-content blockquote p {\n margin: 0;\n line-height: inherit;\n}\n\n.poster-content code {\n background: var(--background-gray);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: var(--font-mono);\n font-size: var(--dynamic-code-size, 14px);\n color: var(--primary-color);\n}\n\n.poster-content pre {\n background: var(--text-primary);\n color: #e2e8f0;\n padding: 16px;\n border-radius: var(--border-radius);\n margin: 16px 0;\n white-space: pre-wrap;\n word-wrap: break-word;\n}\n\n.poster-content pre code {\n background: transparent;\n color: inherit;\n padding: 0;\n}\n\n.poster-content table {\n width: 100%;\n border-collapse: collapse;\n margin: 16px 0;\n font-size: 14px;\n}\n\n.poster-content table th,\n.poster-content table td {\n padding: 8px 12px;\n border: 1px solid var(--border-color);\n text-align: left;\n}\n\n.poster-content table th {\n background: var(--background-light);\n font-weight: 600;\n}\n";
|
|
14
|
+
/**
|
|
15
|
+
* 生成自定义背景CSS
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateCustomBackground(config: CustomBackground): string;
|
|
18
|
+
/**
|
|
19
|
+
* 生成动态字体大小CSS变量
|
|
20
|
+
*/
|
|
21
|
+
export declare function generateFontSizeVars(baseFontSize: number): string;
|
package/dist/styles.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FULL_STYLES = exports.BACKGROUND_PRESETS = exports.CSS_VARIABLES = void 0;
|
|
4
|
+
exports.generateCustomBackground = generateCustomBackground;
|
|
5
|
+
exports.generateFontSizeVars = generateFontSizeVars;
|
|
6
|
+
/**
|
|
7
|
+
* CSS 变量定义
|
|
8
|
+
*/
|
|
9
|
+
exports.CSS_VARIABLES = `
|
|
10
|
+
:root {
|
|
11
|
+
--primary-color: #6366f1;
|
|
12
|
+
--primary-hover: #4f46e5;
|
|
13
|
+
--secondary-color: #8b5cf6;
|
|
14
|
+
--text-primary: #1e293b;
|
|
15
|
+
--text-secondary: #334155;
|
|
16
|
+
--text-muted: #64748b;
|
|
17
|
+
--text-light: #475569;
|
|
18
|
+
--background-light: #f8fafc;
|
|
19
|
+
--background-gray: #f1f5f9;
|
|
20
|
+
--border-color: #e2e8f0;
|
|
21
|
+
--border-light: #cbd5e1;
|
|
22
|
+
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
23
|
+
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
24
|
+
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
25
|
+
--border-radius: 8px;
|
|
26
|
+
--border-radius-lg: 12px;
|
|
27
|
+
--font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
/**
|
|
31
|
+
* 背景预设样式
|
|
32
|
+
*/
|
|
33
|
+
exports.BACKGROUND_PRESETS = {
|
|
34
|
+
purple: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
35
|
+
pink: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
|
|
36
|
+
blue: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
|
|
37
|
+
green: 'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
|
|
38
|
+
sunset: 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)',
|
|
39
|
+
pastel: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)',
|
|
40
|
+
peach: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)',
|
|
41
|
+
rose: 'linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%)',
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* 完整样式表
|
|
45
|
+
*/
|
|
46
|
+
exports.FULL_STYLES = `
|
|
47
|
+
${exports.CSS_VARIABLES}
|
|
48
|
+
|
|
49
|
+
* {
|
|
50
|
+
margin: 0;
|
|
51
|
+
padding: 0;
|
|
52
|
+
box-sizing: border-box;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
body {
|
|
56
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
57
|
+
background: var(--background-light);
|
|
58
|
+
color: var(--text-secondary);
|
|
59
|
+
line-height: 1.6;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.markdown-poster {
|
|
63
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
64
|
+
border-radius: 0;
|
|
65
|
+
padding: 40px;
|
|
66
|
+
margin: 20px;
|
|
67
|
+
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
|
68
|
+
width: 640px;
|
|
69
|
+
min-height: 600px;
|
|
70
|
+
position: relative;
|
|
71
|
+
overflow: hidden;
|
|
72
|
+
box-sizing: border-box;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.markdown-poster::before {
|
|
76
|
+
content: '';
|
|
77
|
+
position: absolute;
|
|
78
|
+
top: 0;
|
|
79
|
+
left: 0;
|
|
80
|
+
right: 0;
|
|
81
|
+
bottom: 0;
|
|
82
|
+
background: rgba(255, 255, 255, 0.1);
|
|
83
|
+
border-radius: 0;
|
|
84
|
+
pointer-events: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.poster-content {
|
|
88
|
+
background: rgba(255, 255, 255, 0.95) !important;
|
|
89
|
+
border-radius: 12px;
|
|
90
|
+
padding: 40px;
|
|
91
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
92
|
+
backdrop-filter: blur(10px);
|
|
93
|
+
position: relative;
|
|
94
|
+
z-index: 1;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
word-wrap: break-word;
|
|
97
|
+
min-height: 400px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.poster-content img {
|
|
101
|
+
max-width: 100%;
|
|
102
|
+
height: auto;
|
|
103
|
+
border-radius: var(--border-radius);
|
|
104
|
+
margin: 16px auto;
|
|
105
|
+
box-shadow: var(--shadow-md);
|
|
106
|
+
display: block;
|
|
107
|
+
object-fit: cover;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.poster-content h1 {
|
|
111
|
+
font-size: var(--dynamic-h1-size, 28px);
|
|
112
|
+
font-weight: 700;
|
|
113
|
+
color: var(--text-primary);
|
|
114
|
+
margin-bottom: 16px;
|
|
115
|
+
line-height: 1.3;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.poster-content h2 {
|
|
119
|
+
font-size: var(--dynamic-h2-size, 22px);
|
|
120
|
+
font-weight: 600;
|
|
121
|
+
color: var(--text-secondary);
|
|
122
|
+
margin: 24px 0 12px 0;
|
|
123
|
+
line-height: 1.4;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.poster-content h3 {
|
|
127
|
+
font-size: var(--dynamic-h3-size, 18px);
|
|
128
|
+
font-weight: 600;
|
|
129
|
+
color: var(--text-light);
|
|
130
|
+
margin: 20px 0 8px 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.poster-content p {
|
|
134
|
+
font-size: var(--dynamic-font-size, 16px);
|
|
135
|
+
color: var(--text-light);
|
|
136
|
+
margin-bottom: 16px;
|
|
137
|
+
line-height: 1.7;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.poster-content em {
|
|
141
|
+
font-style: italic;
|
|
142
|
+
color: var(--primary-color);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.poster-content strong {
|
|
146
|
+
font-weight: 700;
|
|
147
|
+
color: var(--text-primary);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.poster-content a {
|
|
151
|
+
color: var(--primary-color);
|
|
152
|
+
text-decoration: none;
|
|
153
|
+
border-bottom: 1px solid var(--primary-color);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.poster-content ul,
|
|
157
|
+
.poster-content ol {
|
|
158
|
+
margin: 16px 0;
|
|
159
|
+
padding-left: 24px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.poster-content li {
|
|
163
|
+
font-size: var(--dynamic-font-size, 16px);
|
|
164
|
+
color: var(--text-light);
|
|
165
|
+
margin-bottom: 8px;
|
|
166
|
+
line-height: 1.6;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.poster-content blockquote {
|
|
170
|
+
border-left: 4px solid var(--primary-color);
|
|
171
|
+
padding-left: 16px;
|
|
172
|
+
background: var(--background-gray);
|
|
173
|
+
padding-top: 12px;
|
|
174
|
+
padding-bottom: 12px;
|
|
175
|
+
margin: 16px 0;
|
|
176
|
+
color: var(--text-muted);
|
|
177
|
+
font-style: italic;
|
|
178
|
+
font-size: var(--dynamic-quote-size, 16px);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.poster-content blockquote p {
|
|
182
|
+
margin: 0;
|
|
183
|
+
line-height: inherit;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.poster-content code {
|
|
187
|
+
background: var(--background-gray);
|
|
188
|
+
padding: 2px 6px;
|
|
189
|
+
border-radius: 4px;
|
|
190
|
+
font-family: var(--font-mono);
|
|
191
|
+
font-size: var(--dynamic-code-size, 14px);
|
|
192
|
+
color: var(--primary-color);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.poster-content pre {
|
|
196
|
+
background: var(--text-primary);
|
|
197
|
+
color: #e2e8f0;
|
|
198
|
+
padding: 16px;
|
|
199
|
+
border-radius: var(--border-radius);
|
|
200
|
+
margin: 16px 0;
|
|
201
|
+
white-space: pre-wrap;
|
|
202
|
+
word-wrap: break-word;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.poster-content pre code {
|
|
206
|
+
background: transparent;
|
|
207
|
+
color: inherit;
|
|
208
|
+
padding: 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.poster-content table {
|
|
212
|
+
width: 100%;
|
|
213
|
+
border-collapse: collapse;
|
|
214
|
+
margin: 16px 0;
|
|
215
|
+
font-size: 14px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.poster-content table th,
|
|
219
|
+
.poster-content table td {
|
|
220
|
+
padding: 8px 12px;
|
|
221
|
+
border: 1px solid var(--border-color);
|
|
222
|
+
text-align: left;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.poster-content table th {
|
|
226
|
+
background: var(--background-light);
|
|
227
|
+
font-weight: 600;
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
/**
|
|
231
|
+
* 生成自定义背景CSS
|
|
232
|
+
*/
|
|
233
|
+
function generateCustomBackground(config) {
|
|
234
|
+
return `linear-gradient(${config.direction}, ${config.colorStart} 0%, ${config.colorEnd} 100%)`;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 生成动态字体大小CSS变量
|
|
238
|
+
*/
|
|
239
|
+
function generateFontSizeVars(baseFontSize) {
|
|
240
|
+
return `
|
|
241
|
+
--dynamic-font-size: ${baseFontSize}px;
|
|
242
|
+
--dynamic-h1-size: ${Math.round(baseFontSize * 1.75)}px;
|
|
243
|
+
--dynamic-h2-size: ${Math.round(baseFontSize * 1.375)}px;
|
|
244
|
+
--dynamic-h3-size: ${Math.round(baseFontSize * 1.125)}px;
|
|
245
|
+
--dynamic-h4-size: ${Math.round(baseFontSize * 1.05)}px;
|
|
246
|
+
--dynamic-h5-h6-size: ${Math.round(baseFontSize * 0.95)}px;
|
|
247
|
+
--dynamic-code-size: ${Math.round(baseFontSize * 0.875)}px;
|
|
248
|
+
--dynamic-quote-size: ${Math.round(baseFontSize * 0.95)}px;
|
|
249
|
+
`;
|
|
250
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 导出模式枚举
|
|
3
|
+
*/
|
|
4
|
+
export declare enum ExportMode {
|
|
5
|
+
/** 自由模式,根据内容自适应高度 */
|
|
6
|
+
FREE = "free",
|
|
7
|
+
/** 小红书模式,固定 3:4 比例 */
|
|
8
|
+
XHS = "xhs",
|
|
9
|
+
/** 朋友圈模式,固定 1290:2796 比例 */
|
|
10
|
+
PYQ = "pyq"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 背景渐变预设
|
|
14
|
+
*/
|
|
15
|
+
export type BackgroundPreset = 'purple' | 'pink' | 'blue' | 'green' | 'sunset' | 'pastel' | 'peach' | 'rose';
|
|
16
|
+
/**
|
|
17
|
+
* 渐变方向
|
|
18
|
+
*/
|
|
19
|
+
export type GradientDirection = '0deg' | '45deg' | '90deg' | '135deg' | '180deg' | '270deg';
|
|
20
|
+
/**
|
|
21
|
+
* 自定义背景配置
|
|
22
|
+
*/
|
|
23
|
+
export interface CustomBackground {
|
|
24
|
+
colorStart: string;
|
|
25
|
+
colorEnd: string;
|
|
26
|
+
direction: GradientDirection;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 扩展功能配置
|
|
30
|
+
*/
|
|
31
|
+
export interface ExtensionOptions {
|
|
32
|
+
/**
|
|
33
|
+
* 是否启用数学公式支持 (KaTeX)
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
enableMath?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* 是否启用图表支持 (Mermaid)
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
enableDiagram?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 是否启用卡片语法
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
enableCard?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 转换配置选项
|
|
50
|
+
*/
|
|
51
|
+
export interface Md2ImageOptions {
|
|
52
|
+
/**
|
|
53
|
+
* 导出模式
|
|
54
|
+
* @default ExportMode.XHS
|
|
55
|
+
*/
|
|
56
|
+
mode?: ExportMode | 'free' | 'xhs' | 'pyq';
|
|
57
|
+
/**
|
|
58
|
+
* 整体宽度(像素)
|
|
59
|
+
* @default 640
|
|
60
|
+
*/
|
|
61
|
+
width?: number;
|
|
62
|
+
/**
|
|
63
|
+
* 内边距(像素)
|
|
64
|
+
* @default 40
|
|
65
|
+
*/
|
|
66
|
+
padding?: number;
|
|
67
|
+
/**
|
|
68
|
+
* 基础字体大小(像素)
|
|
69
|
+
* @default 18
|
|
70
|
+
*/
|
|
71
|
+
fontSize?: number;
|
|
72
|
+
/**
|
|
73
|
+
* 背景预设
|
|
74
|
+
*/
|
|
75
|
+
backgroundPreset?: BackgroundPreset;
|
|
76
|
+
/**
|
|
77
|
+
* 自定义背景
|
|
78
|
+
*/
|
|
79
|
+
customBackground?: CustomBackground;
|
|
80
|
+
/**
|
|
81
|
+
* 导出缩放倍数,影响输出图片清晰度
|
|
82
|
+
* @default 2
|
|
83
|
+
*/
|
|
84
|
+
scale?: number;
|
|
85
|
+
/**
|
|
86
|
+
* 输出文件路径
|
|
87
|
+
*/
|
|
88
|
+
outputPath?: string;
|
|
89
|
+
/**
|
|
90
|
+
* 扩展功能配置
|
|
91
|
+
*/
|
|
92
|
+
extensions?: ExtensionOptions;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 转换结果
|
|
96
|
+
*/
|
|
97
|
+
export interface ConvertResult {
|
|
98
|
+
/**
|
|
99
|
+
* 生成的图片路径
|
|
100
|
+
*/
|
|
101
|
+
imagePath: string;
|
|
102
|
+
/**
|
|
103
|
+
* 图片宽度
|
|
104
|
+
*/
|
|
105
|
+
width: number;
|
|
106
|
+
/**
|
|
107
|
+
* 图片高度
|
|
108
|
+
*/
|
|
109
|
+
height: number;
|
|
110
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExportMode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 导出模式枚举
|
|
6
|
+
*/
|
|
7
|
+
var ExportMode;
|
|
8
|
+
(function (ExportMode) {
|
|
9
|
+
/** 自由模式,根据内容自适应高度 */
|
|
10
|
+
ExportMode["FREE"] = "free";
|
|
11
|
+
/** 小红书模式,固定 3:4 比例 */
|
|
12
|
+
ExportMode["XHS"] = "xhs";
|
|
13
|
+
/** 朋友圈模式,固定 1290:2796 比例 */
|
|
14
|
+
ExportMode["PYQ"] = "pyq";
|
|
15
|
+
})(ExportMode || (exports.ExportMode = ExportMode = {}));
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "md2xhs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "将 Markdown 转换为适合小红书发布的精美图片 - Convert Markdown to beautiful images for Xiaohongshu",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc && npm run copy-assets",
|
|
14
|
+
"copy-assets": "mkdir -p dist/assets && cp -r src/assets/* dist/assets/",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"dev": "tsc --watch"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"markdown",
|
|
20
|
+
"markdown-to-image",
|
|
21
|
+
"image",
|
|
22
|
+
"xiaohongshu",
|
|
23
|
+
"social-media",
|
|
24
|
+
"converter",
|
|
25
|
+
"export",
|
|
26
|
+
"markdown-converter",
|
|
27
|
+
"image-generator",
|
|
28
|
+
"katex",
|
|
29
|
+
"mermaid",
|
|
30
|
+
"typescript"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/yourusername/md2xhs.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/yourusername/md2xhs/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/yourusername/md2xhs#readme",
|
|
40
|
+
"author": "",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=16.0.0"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"marked": "^11.0.0",
|
|
47
|
+
"puppeteer": "^24.15.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^20.10.0",
|
|
51
|
+
"typescript": "^5.3.3"
|
|
52
|
+
}
|
|
53
|
+
}
|