xhs-md-renderer 0.1.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 +21 -0
- package/README.md +49 -0
- package/bin/xhs-md-render.js +3 -0
- package/dist/browser-renderer.d.ts +8 -0
- package/dist/browser-renderer.js +156 -0
- package/dist/browser-renderer.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +418 -0
- package/dist/index.js.map +1 -0
- package/dist/vendor/core/image.d.ts +27 -0
- package/dist/vendor/core/image.js +265 -0
- package/dist/vendor/core/image.js.map +1 -0
- package/dist/vendor/core/index.d.ts +6 -0
- package/dist/vendor/core/index.js +6 -0
- package/dist/vendor/core/index.js.map +1 -0
- package/dist/vendor/core/layout.d.ts +22 -0
- package/dist/vendor/core/layout.js +276 -0
- package/dist/vendor/core/layout.js.map +1 -0
- package/dist/vendor/core/models.d.ts +138 -0
- package/dist/vendor/core/models.js +2 -0
- package/dist/vendor/core/models.js.map +1 -0
- package/dist/vendor/core/node-images.d.ts +2 -0
- package/dist/vendor/core/node-images.js +327 -0
- package/dist/vendor/core/node-images.js.map +1 -0
- package/dist/vendor/core/node.d.ts +31 -0
- package/dist/vendor/core/node.js +199 -0
- package/dist/vendor/core/node.js.map +1 -0
- package/dist/vendor/core/parser.d.ts +6 -0
- package/dist/vendor/core/parser.js +158 -0
- package/dist/vendor/core/parser.js.map +1 -0
- package/dist/vendor/core/preview.d.ts +6 -0
- package/dist/vendor/core/preview.js +325 -0
- package/dist/vendor/core/preview.js.map +1 -0
- package/dist/vendor/core/themes.d.ts +21 -0
- package/dist/vendor/core/themes.js +124 -0
- package/dist/vendor/core/themes.js.map +1 -0
- package/package.json +57 -0
- package/web-dist/assets/index-Br8RJhby.js +45 -0
- package/web-dist/assets/index-CwEw55IG.css +1 -0
- package/web-dist/index.html +13 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { Resvg } from "@resvg/resvg-js";
|
|
5
|
+
import satori from "satori";
|
|
6
|
+
import { analyzePageLayout } from "./layout.js";
|
|
7
|
+
import { resolvePageImagesForNode } from "./node-images.js";
|
|
8
|
+
import { parseMarkdownToPages } from "./parser.js";
|
|
9
|
+
import { XhsPageCard } from "./preview.js";
|
|
10
|
+
import { createRenderConfig } from "./themes.js";
|
|
11
|
+
const FONT_CANDIDATES = [
|
|
12
|
+
{
|
|
13
|
+
names: ["SimSun", "Songti SC", "Songti", "STSong"],
|
|
14
|
+
paths: ["/System/Library/Fonts/Supplemental/Songti.ttc"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
names: ["KaiTi", "Kaiti SC", "Kaiti", "Noto Sans Kaithi"],
|
|
18
|
+
paths: [
|
|
19
|
+
"/System/Library/Fonts/Supplemental/NotoSansKaithi-Regular.ttf",
|
|
20
|
+
"/System/Library/Fonts/Supplemental/Kailasa.ttc"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
names: ["SimHei", "Heiti SC", "STHeiti", "Hiragino Sans GB"],
|
|
25
|
+
paths: [
|
|
26
|
+
"/System/Library/Fonts/STHeiti Medium.ttc",
|
|
27
|
+
"/System/Library/Fonts/Hiragino Sans GB.ttc"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
names: ["PingFang SC", "Microsoft YaHei", "Helvetica Neue", "Helvetica", "Optima"],
|
|
32
|
+
paths: [
|
|
33
|
+
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
|
|
34
|
+
"/usr/share/fonts/opentype/noto/NotoSansSC-Regular.otf",
|
|
35
|
+
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
|
|
36
|
+
"/System/Library/Fonts/Hiragino Sans GB.ttc",
|
|
37
|
+
"/Library/Fonts/HelveticaNeue.ttc",
|
|
38
|
+
"/System/Library/Fonts/Helvetica.ttc",
|
|
39
|
+
"/Library/Fonts/Arial Unicode.ttf",
|
|
40
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
41
|
+
"/usr/share/fonts/truetype/liberation2/LiberationSans-Regular.ttf"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
names: ["Times New Roman", "Georgia", "serif", "sans-serif"],
|
|
46
|
+
paths: [
|
|
47
|
+
"/usr/share/fonts/opentype/noto/NotoSerifCJK-Regular.ttc",
|
|
48
|
+
"/System/Library/Fonts/Supplemental/Times New Roman.ttf",
|
|
49
|
+
"/System/Library/Fonts/Supplemental/Georgia.ttf",
|
|
50
|
+
"/System/Library/Fonts/Helvetica.ttc",
|
|
51
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf",
|
|
52
|
+
"/usr/share/fonts/truetype/liberation2/LiberationSerif-Regular.ttf",
|
|
53
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
async function loadFontData(fontPath) {
|
|
58
|
+
const fontBuffer = await readFile(fontPath);
|
|
59
|
+
return fontBuffer.buffer.slice(fontBuffer.byteOffset, fontBuffer.byteOffset + fontBuffer.byteLength);
|
|
60
|
+
}
|
|
61
|
+
async function isFile(filePath) {
|
|
62
|
+
try {
|
|
63
|
+
return (await stat(filePath)).isFile();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function parseRequestedFontNames(fontFamily) {
|
|
70
|
+
return fontFamily
|
|
71
|
+
.split(",")
|
|
72
|
+
.map((family) => family.trim().replace(/^['"]|['"]$/g, ""))
|
|
73
|
+
.filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
async function resolveFontPath(paths) {
|
|
76
|
+
for (const fontPath of paths) {
|
|
77
|
+
if (await isFile(fontPath)) {
|
|
78
|
+
return fontPath;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
async function loadFonts(fontFamily) {
|
|
84
|
+
const requestedNames = parseRequestedFontNames(fontFamily);
|
|
85
|
+
const loadedFonts = [];
|
|
86
|
+
const loadedPaths = new Map();
|
|
87
|
+
for (const candidate of FONT_CANDIDATES) {
|
|
88
|
+
const requested = candidate.names.some((name) => requestedNames.includes(name));
|
|
89
|
+
if (!requested && loadedFonts.length > 0) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const fontPath = await resolveFontPath(candidate.paths);
|
|
93
|
+
if (!fontPath) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
let data = loadedPaths.get(fontPath);
|
|
97
|
+
if (!data) {
|
|
98
|
+
data = await loadFontData(fontPath);
|
|
99
|
+
loadedPaths.set(fontPath, data);
|
|
100
|
+
}
|
|
101
|
+
for (const name of candidate.names) {
|
|
102
|
+
loadedFonts.push({
|
|
103
|
+
name,
|
|
104
|
+
data,
|
|
105
|
+
weight: 400,
|
|
106
|
+
style: "normal"
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (loadedFonts.length > 0) {
|
|
111
|
+
return loadedFonts;
|
|
112
|
+
}
|
|
113
|
+
throw new Error("No usable system font found for the requested font family.");
|
|
114
|
+
}
|
|
115
|
+
export async function renderPageToSvg(page, config) {
|
|
116
|
+
const fonts = await loadFonts(config.fontFamily);
|
|
117
|
+
return satori(React.createElement(XhsPageCard, { page, config }), {
|
|
118
|
+
width: config.width,
|
|
119
|
+
height: config.height,
|
|
120
|
+
fonts
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
export async function renderPageToPng(page, config) {
|
|
124
|
+
const svg = await renderPageToSvg(page, config);
|
|
125
|
+
const resvg = new Resvg(svg, {
|
|
126
|
+
fitTo: {
|
|
127
|
+
mode: "width",
|
|
128
|
+
value: config.width
|
|
129
|
+
},
|
|
130
|
+
background: "rgba(255,255,255,1)"
|
|
131
|
+
});
|
|
132
|
+
return resvg.render().asPng();
|
|
133
|
+
}
|
|
134
|
+
export async function prepareExportDocument(input) {
|
|
135
|
+
const config = createRenderConfig(input.renderConfig);
|
|
136
|
+
const parsed = parseMarkdownToPages(input.markdown, input.title === undefined ? {} : { documentTitle: input.title });
|
|
137
|
+
const pages = await resolvePageImagesForNode(parsed.pages, input.markdownFilePath);
|
|
138
|
+
const { source } = parsed;
|
|
139
|
+
const manifest = {
|
|
140
|
+
version: 1,
|
|
141
|
+
generatedAt: new Date().toISOString(),
|
|
142
|
+
sourceTitle: source.title,
|
|
143
|
+
renderConfig: {
|
|
144
|
+
width: config.width,
|
|
145
|
+
height: config.height,
|
|
146
|
+
fontFamily: config.fontFamily,
|
|
147
|
+
fontSize: config.fontSize,
|
|
148
|
+
layout: config.layout,
|
|
149
|
+
profile: config.profile,
|
|
150
|
+
themeId: config.theme.id
|
|
151
|
+
},
|
|
152
|
+
pages: pages.map((page) => ({
|
|
153
|
+
id: page.id,
|
|
154
|
+
index: page.index,
|
|
155
|
+
title: page.title,
|
|
156
|
+
sectionTitle: page.sectionTitle,
|
|
157
|
+
fileName: `page-${String(page.index + 1).padStart(2, "0")}.png`
|
|
158
|
+
}))
|
|
159
|
+
};
|
|
160
|
+
const layoutReport = analyzePageLayout(pages, config, source.title);
|
|
161
|
+
return {
|
|
162
|
+
source,
|
|
163
|
+
pages,
|
|
164
|
+
config,
|
|
165
|
+
manifest,
|
|
166
|
+
layoutReport
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
export async function buildExportBundle(input) {
|
|
170
|
+
const prepared = await prepareExportDocument(input);
|
|
171
|
+
const { pages, config, manifest, layoutReport } = prepared;
|
|
172
|
+
const bundlePages = [];
|
|
173
|
+
for (const page of pages) {
|
|
174
|
+
const fileName = manifest.pages[page.index]?.fileName ?? `page-${String(page.index + 1).padStart(2, "0")}.png`;
|
|
175
|
+
const png = await renderPageToPng(page, config);
|
|
176
|
+
bundlePages.push({ model: page, fileName, png });
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
manifest,
|
|
180
|
+
layoutReport,
|
|
181
|
+
pages: bundlePages
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
export async function writeExportBundle(input) {
|
|
185
|
+
const bundle = await buildExportBundle(input);
|
|
186
|
+
const outputDir = resolve(input.outputDir);
|
|
187
|
+
const pagesDir = join(outputDir, "pages");
|
|
188
|
+
await mkdir(pagesDir, { recursive: true });
|
|
189
|
+
await writeFile(join(outputDir, "manifest.json"), JSON.stringify(bundle.manifest, null, 2), "utf8");
|
|
190
|
+
await writeFile(join(outputDir, "layout-report.json"), JSON.stringify(bundle.layoutReport, null, 2), "utf8");
|
|
191
|
+
const models = bundle.pages.map((page) => page.model);
|
|
192
|
+
await writeFile(join(outputDir, "pages.json"), JSON.stringify(models, null, 2), "utf8");
|
|
193
|
+
await Promise.all(bundle.pages.map((page) => writeFile(join(pagesDir, page.fileName), Buffer.from(page.png))));
|
|
194
|
+
return bundle;
|
|
195
|
+
}
|
|
196
|
+
export async function ensureParentDir(filePath) {
|
|
197
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PageModel, ParseOptions, SourceDocument } from "./models.js";
|
|
2
|
+
export declare const PAGE_BREAK_MARKER = "<!-- xhs-page -->";
|
|
3
|
+
export declare function parseMarkdownToPages(markdown: string, options?: ParseOptions): {
|
|
4
|
+
source: SourceDocument;
|
|
5
|
+
pages: PageModel[];
|
|
6
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { toString } from "mdast-util-to-string";
|
|
2
|
+
import { unified } from "unified";
|
|
3
|
+
import remarkGfm from "remark-gfm";
|
|
4
|
+
import remarkParse from "remark-parse";
|
|
5
|
+
export const PAGE_BREAK_MARKER = "<!-- xhs-page -->";
|
|
6
|
+
const PAGE_BREAK_PATTERN = /^<!--\s*xhs-page\s*-->$/i;
|
|
7
|
+
function slugify(input) {
|
|
8
|
+
return input
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/[^a-z0-9\u4e00-\u9fa5]+/g, "-")
|
|
11
|
+
.replace(/^-+|-+$/g, "");
|
|
12
|
+
}
|
|
13
|
+
function createDocument(markdown, options) {
|
|
14
|
+
const title = options.documentTitle?.trim() || "Untitled Note";
|
|
15
|
+
return {
|
|
16
|
+
id: slugify(title) || "untitled-note",
|
|
17
|
+
title,
|
|
18
|
+
markdown
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function createPage(index, fallbackTitle) {
|
|
22
|
+
const safeTitle = fallbackTitle.trim() || `Page ${index + 1}`;
|
|
23
|
+
return {
|
|
24
|
+
id: `${index + 1}-${slugify(safeTitle) || "page"}`,
|
|
25
|
+
index,
|
|
26
|
+
title: safeTitle,
|
|
27
|
+
sectionTitle: safeTitle,
|
|
28
|
+
blocks: []
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function collectListItemText(item) {
|
|
32
|
+
return item.children.map((child) => toString(child)).join(" ").trim();
|
|
33
|
+
}
|
|
34
|
+
function paragraphHasOnlyImage(node) {
|
|
35
|
+
return node.children.length === 1 && node.children[0]?.type === "image";
|
|
36
|
+
}
|
|
37
|
+
function defaultPageTitle(sourceTitle, index) {
|
|
38
|
+
return index === 0 ? sourceTitle : `Page ${index + 1}`;
|
|
39
|
+
}
|
|
40
|
+
function isFallbackPageTitle(page, sourceTitle) {
|
|
41
|
+
return page.title === defaultPageTitle(sourceTitle, page.index);
|
|
42
|
+
}
|
|
43
|
+
function isPageBreakNode(node) {
|
|
44
|
+
return node.type === "html" && PAGE_BREAK_PATTERN.test(node.value.trim());
|
|
45
|
+
}
|
|
46
|
+
function blockFromNode(node) {
|
|
47
|
+
switch (node.type) {
|
|
48
|
+
case "paragraph": {
|
|
49
|
+
if (paragraphHasOnlyImage(node)) {
|
|
50
|
+
const image = node.children[0];
|
|
51
|
+
return {
|
|
52
|
+
type: "image",
|
|
53
|
+
alt: image.alt || "Image",
|
|
54
|
+
url: image.url
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const text = toString(node).trim();
|
|
58
|
+
return text ? { type: "paragraph", text } : null;
|
|
59
|
+
}
|
|
60
|
+
case "blockquote": {
|
|
61
|
+
const text = toString(node).trim();
|
|
62
|
+
return text ? { type: "quote", text } : null;
|
|
63
|
+
}
|
|
64
|
+
case "code":
|
|
65
|
+
return blockFromCodeNode(node.value.trim(), node.lang || undefined);
|
|
66
|
+
case "list":
|
|
67
|
+
return {
|
|
68
|
+
type: "list",
|
|
69
|
+
ordered: Boolean(node.ordered),
|
|
70
|
+
items: node.children.map(collectListItemText).filter(Boolean)
|
|
71
|
+
};
|
|
72
|
+
case "thematicBreak":
|
|
73
|
+
return {
|
|
74
|
+
type: "divider"
|
|
75
|
+
};
|
|
76
|
+
case "heading": {
|
|
77
|
+
const text = toString(node).trim();
|
|
78
|
+
return text ? { type: "subheading", text } : null;
|
|
79
|
+
}
|
|
80
|
+
case "image":
|
|
81
|
+
return {
|
|
82
|
+
type: "image",
|
|
83
|
+
alt: node.alt || "Image",
|
|
84
|
+
url: node.url
|
|
85
|
+
};
|
|
86
|
+
default: {
|
|
87
|
+
const text = "children" in node ? toString(node).trim() : "";
|
|
88
|
+
return text ? { type: "paragraph", text } : null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function blockFromCodeNode(text, language) {
|
|
93
|
+
if (!text) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return language
|
|
97
|
+
? {
|
|
98
|
+
type: "code",
|
|
99
|
+
text,
|
|
100
|
+
language
|
|
101
|
+
}
|
|
102
|
+
: {
|
|
103
|
+
type: "code",
|
|
104
|
+
text
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function pushPageIfUseful(pages, page) {
|
|
108
|
+
if (!page) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (page.blocks.length === 0 && page.title === `Page ${page.index + 1}`) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
pages.push(page);
|
|
115
|
+
}
|
|
116
|
+
export function parseMarkdownToPages(markdown, options = {}) {
|
|
117
|
+
const source = createDocument(markdown, options);
|
|
118
|
+
const root = unified().use(remarkParse).use(remarkGfm).parse(markdown);
|
|
119
|
+
const pages = [];
|
|
120
|
+
let currentPage = null;
|
|
121
|
+
const openPage = () => {
|
|
122
|
+
pushPageIfUseful(pages, currentPage);
|
|
123
|
+
currentPage = createPage(pages.length, defaultPageTitle(source.title, pages.length));
|
|
124
|
+
};
|
|
125
|
+
const ensurePage = () => {
|
|
126
|
+
if (!currentPage) {
|
|
127
|
+
currentPage = createPage(pages.length, defaultPageTitle(source.title, pages.length));
|
|
128
|
+
}
|
|
129
|
+
return currentPage;
|
|
130
|
+
};
|
|
131
|
+
for (const node of root.children) {
|
|
132
|
+
if (isPageBreakNode(node)) {
|
|
133
|
+
if (currentPage) {
|
|
134
|
+
openPage();
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const page = ensurePage();
|
|
139
|
+
if (node.type === "heading") {
|
|
140
|
+
const text = toString(node).trim();
|
|
141
|
+
if (text && page.blocks.length === 0 && isFallbackPageTitle(page, source.title)) {
|
|
142
|
+
page.title = text;
|
|
143
|
+
page.sectionTitle = text;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const block = blockFromNode(node);
|
|
148
|
+
if (block) {
|
|
149
|
+
page.blocks.push(block);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
pushPageIfUseful(pages, currentPage);
|
|
153
|
+
if (pages.length === 0) {
|
|
154
|
+
pages.push(createPage(0, source.title));
|
|
155
|
+
}
|
|
156
|
+
return { source, pages };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
|