locusing 0.1.2
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 +147 -0
- package/dist/chunk-3XW6GBD6.mjs +445 -0
- package/dist/chunk-HNU2F3GX.mjs +586 -0
- package/dist/chunk-TQQRYA5H.mjs +58 -0
- package/dist/chunk-Y4M467JV.mjs +607 -0
- package/dist/diagram-Djxa_kGR.d.mts +1945 -0
- package/dist/diagram-Djxa_kGR.d.ts +1945 -0
- package/dist/export.d.mts +194 -0
- package/dist/export.d.ts +194 -0
- package/dist/export.js +528 -0
- package/dist/export.mjs +305 -0
- package/dist/index.d.mts +6883 -0
- package/dist/index.d.ts +6883 -0
- package/dist/index.global.js +79540 -0
- package/dist/index.js +15785 -0
- package/dist/index.mjs +14350 -0
- package/dist/transform-4WYIJSLH.mjs +23 -0
- package/dist/transform-7YKZIQ3I.mjs +22 -0
- package/package.json +117 -0
package/dist/export.mjs
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import {
|
|
2
|
+
init_render_svg,
|
|
3
|
+
toSVGString
|
|
4
|
+
} from "./chunk-3XW6GBD6.mjs";
|
|
5
|
+
import {
|
|
6
|
+
__objRest,
|
|
7
|
+
__spreadProps,
|
|
8
|
+
__spreadValues
|
|
9
|
+
} from "./chunk-TQQRYA5H.mjs";
|
|
10
|
+
|
|
11
|
+
// src/export/playwright-exporter.ts
|
|
12
|
+
init_render_svg();
|
|
13
|
+
|
|
14
|
+
// src/export/html-template.ts
|
|
15
|
+
var KATEX_CSS_URL = "https://cdn.jsdelivr.net/npm/katex@0.16.27/dist/katex.min.css";
|
|
16
|
+
function generateExportHTML(svgContent, options) {
|
|
17
|
+
const {
|
|
18
|
+
width = 1920,
|
|
19
|
+
height = 1080,
|
|
20
|
+
background = "transparent"
|
|
21
|
+
} = options;
|
|
22
|
+
return `<!DOCTYPE html>
|
|
23
|
+
<html>
|
|
24
|
+
<head>
|
|
25
|
+
<meta charset="UTF-8">
|
|
26
|
+
<meta name="viewport" content="width=${width}, height=${height}">
|
|
27
|
+
<link rel="stylesheet" href="${KATEX_CSS_URL}" crossorigin="anonymous">
|
|
28
|
+
<style>
|
|
29
|
+
* {
|
|
30
|
+
margin: 0;
|
|
31
|
+
padding: 0;
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
}
|
|
34
|
+
html, body {
|
|
35
|
+
width: ${width}px;
|
|
36
|
+
height: ${height}px;
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
}
|
|
39
|
+
body {
|
|
40
|
+
background: ${background};
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
}
|
|
45
|
+
svg {
|
|
46
|
+
width: 100%;
|
|
47
|
+
height: 100%;
|
|
48
|
+
display: block;
|
|
49
|
+
}
|
|
50
|
+
/* KaTeX \u5728 SVG foreignObject \u4E2D\u7684\u6837\u5F0F\u4FEE\u6B63 */
|
|
51
|
+
.katex {
|
|
52
|
+
font-size: inherit;
|
|
53
|
+
line-height: 1;
|
|
54
|
+
}
|
|
55
|
+
.katex-html {
|
|
56
|
+
white-space: nowrap;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
<body>
|
|
61
|
+
${svgContent}
|
|
62
|
+
</body>
|
|
63
|
+
</html>`;
|
|
64
|
+
}
|
|
65
|
+
function generateExportHTMLWithInlineCSS(katexCSS, svgContent, options) {
|
|
66
|
+
const {
|
|
67
|
+
width = 1920,
|
|
68
|
+
height = 1080,
|
|
69
|
+
background = "transparent"
|
|
70
|
+
} = options;
|
|
71
|
+
return `<!DOCTYPE html>
|
|
72
|
+
<html>
|
|
73
|
+
<head>
|
|
74
|
+
<meta charset="UTF-8">
|
|
75
|
+
<meta name="viewport" content="width=${width}, height=${height}">
|
|
76
|
+
<style>
|
|
77
|
+
${katexCSS}
|
|
78
|
+
</style>
|
|
79
|
+
<style>
|
|
80
|
+
* {
|
|
81
|
+
margin: 0;
|
|
82
|
+
padding: 0;
|
|
83
|
+
box-sizing: border-box;
|
|
84
|
+
}
|
|
85
|
+
html, body {
|
|
86
|
+
width: ${width}px;
|
|
87
|
+
height: ${height}px;
|
|
88
|
+
overflow: hidden;
|
|
89
|
+
}
|
|
90
|
+
body {
|
|
91
|
+
background: ${background};
|
|
92
|
+
display: flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
}
|
|
96
|
+
svg {
|
|
97
|
+
width: 100%;
|
|
98
|
+
height: 100%;
|
|
99
|
+
display: block;
|
|
100
|
+
}
|
|
101
|
+
.katex {
|
|
102
|
+
font-size: inherit;
|
|
103
|
+
line-height: 1;
|
|
104
|
+
}
|
|
105
|
+
.katex-html {
|
|
106
|
+
white-space: nowrap;
|
|
107
|
+
}
|
|
108
|
+
</style>
|
|
109
|
+
</head>
|
|
110
|
+
<body>
|
|
111
|
+
${svgContent}
|
|
112
|
+
</body>
|
|
113
|
+
</html>`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/export/playwright-exporter.ts
|
|
117
|
+
var PlaywrightExporter = class {
|
|
118
|
+
constructor(options = {}) {
|
|
119
|
+
this.browser = null;
|
|
120
|
+
this.page = null;
|
|
121
|
+
var _a, _b;
|
|
122
|
+
this.options = {
|
|
123
|
+
headless: (_a = options.headless) != null ? _a : true,
|
|
124
|
+
browser: (_b = options.browser) != null ? _b : "chromium"
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 启动浏览器
|
|
129
|
+
*
|
|
130
|
+
* @throws 如果 Playwright 未安装
|
|
131
|
+
*/
|
|
132
|
+
async launch() {
|
|
133
|
+
if (this.browser) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
let playwright;
|
|
137
|
+
try {
|
|
138
|
+
playwright = await import("playwright");
|
|
139
|
+
} catch (e) {
|
|
140
|
+
throw new Error(
|
|
141
|
+
"Playwright is not installed. Please install it with: pnpm add -D playwright"
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
const browserType = playwright[this.options.browser];
|
|
145
|
+
if (!browserType) {
|
|
146
|
+
throw new Error(`Unknown browser type: ${this.options.browser}`);
|
|
147
|
+
}
|
|
148
|
+
this.browser = await browserType.launch({
|
|
149
|
+
headless: this.options.headless
|
|
150
|
+
});
|
|
151
|
+
this.page = await this.browser.newPage();
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 关闭浏览器
|
|
155
|
+
*/
|
|
156
|
+
async close() {
|
|
157
|
+
if (this.page) {
|
|
158
|
+
await this.page.close();
|
|
159
|
+
this.page = null;
|
|
160
|
+
}
|
|
161
|
+
if (this.browser) {
|
|
162
|
+
await this.browser.close();
|
|
163
|
+
this.browser = null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* 获取页面实例,确保已启动
|
|
168
|
+
*/
|
|
169
|
+
getPage() {
|
|
170
|
+
if (!this.browser || !this.page) {
|
|
171
|
+
throw new Error("Browser not launched. Call launch() first.");
|
|
172
|
+
}
|
|
173
|
+
return this.page;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 导出 Diagram 为图片
|
|
177
|
+
*
|
|
178
|
+
* @param diagram - 要导出的 Diagram
|
|
179
|
+
* @param options - 导出选项
|
|
180
|
+
* @returns 导出结果
|
|
181
|
+
*/
|
|
182
|
+
async exportDiagram(diagram, options = {}) {
|
|
183
|
+
const {
|
|
184
|
+
width = 1920,
|
|
185
|
+
height = 1080,
|
|
186
|
+
frame = true
|
|
187
|
+
} = options;
|
|
188
|
+
const svgString = toSVGString(diagram, {
|
|
189
|
+
width,
|
|
190
|
+
height,
|
|
191
|
+
frame,
|
|
192
|
+
background: "transparent"
|
|
193
|
+
// HTML 背景会处理
|
|
194
|
+
});
|
|
195
|
+
return this.exportSVGString(svgString, options);
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* 导出 Scene 为图片(静态帧)
|
|
199
|
+
*
|
|
200
|
+
* @param SceneClass - Scene 类
|
|
201
|
+
* @param options - 导出选项
|
|
202
|
+
* @returns 导出结果
|
|
203
|
+
*/
|
|
204
|
+
async exportScene(SceneClass, options = {}) {
|
|
205
|
+
const _a = options, { frameTime: _frameTime = 0 } = _a, exportOptions = __objRest(_a, ["frameTime"]);
|
|
206
|
+
const scene = new SceneClass();
|
|
207
|
+
if (typeof scene.construct === "function") {
|
|
208
|
+
if (typeof scene.toSVGString === "function") {
|
|
209
|
+
const svgString = scene.toSVGString();
|
|
210
|
+
return this.exportSVGString(svgString, exportOptions);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
throw new Error(
|
|
214
|
+
"Scene export requires the Scene to have a toSVGString() method. For animated scenes, use browser-based export."
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* 导出 SVG 字符串为图片
|
|
219
|
+
*
|
|
220
|
+
* @param svgString - SVG 字符串
|
|
221
|
+
* @param options - 导出选项
|
|
222
|
+
* @returns 导出结果
|
|
223
|
+
*/
|
|
224
|
+
async exportSVGString(svgString, options = {}) {
|
|
225
|
+
const page = this.getPage();
|
|
226
|
+
const {
|
|
227
|
+
format = "png",
|
|
228
|
+
quality = 90,
|
|
229
|
+
deviceScaleFactor = 2,
|
|
230
|
+
width = 1920,
|
|
231
|
+
height = 1080,
|
|
232
|
+
background = "transparent",
|
|
233
|
+
waitForFonts = true,
|
|
234
|
+
renderDelay = 100
|
|
235
|
+
} = options;
|
|
236
|
+
await page.setViewportSize({
|
|
237
|
+
width,
|
|
238
|
+
height
|
|
239
|
+
});
|
|
240
|
+
await page.emulateMedia({ colorScheme: "light" });
|
|
241
|
+
const html = generateExportHTML(svgString, { width, height, background });
|
|
242
|
+
await page.setContent(html, {
|
|
243
|
+
waitUntil: "networkidle"
|
|
244
|
+
});
|
|
245
|
+
if (waitForFonts) {
|
|
246
|
+
await page.waitForFunction(
|
|
247
|
+
() => document.fonts.ready.then(() => true),
|
|
248
|
+
{ timeout: 1e4 }
|
|
249
|
+
).catch(() => {
|
|
250
|
+
console.warn("Font loading timeout, continuing with available fonts");
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
if (renderDelay > 0) {
|
|
254
|
+
await page.waitForTimeout(renderDelay);
|
|
255
|
+
}
|
|
256
|
+
const buffer = await page.screenshot({
|
|
257
|
+
type: format,
|
|
258
|
+
quality: format !== "png" ? quality : void 0,
|
|
259
|
+
fullPage: false,
|
|
260
|
+
omitBackground: background === "transparent",
|
|
261
|
+
scale: "device"
|
|
262
|
+
});
|
|
263
|
+
const actualWidth = width * deviceScaleFactor;
|
|
264
|
+
const actualHeight = height * deviceScaleFactor;
|
|
265
|
+
return {
|
|
266
|
+
buffer: Buffer.from(buffer),
|
|
267
|
+
mimeType: `image/${format}`,
|
|
268
|
+
width: actualWidth,
|
|
269
|
+
height: actualHeight
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
async function exportToPNG(diagram, outputPath, options = {}) {
|
|
274
|
+
const fs = await import("fs/promises");
|
|
275
|
+
const exporter = new PlaywrightExporter();
|
|
276
|
+
try {
|
|
277
|
+
await exporter.launch();
|
|
278
|
+
const result = await exporter.exportDiagram(diagram, __spreadProps(__spreadValues({}, options), {
|
|
279
|
+
format: "png"
|
|
280
|
+
}));
|
|
281
|
+
await fs.writeFile(outputPath, result.buffer);
|
|
282
|
+
} finally {
|
|
283
|
+
await exporter.close();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
async function exportSVGToPNG(svgString, outputPath, options = {}) {
|
|
287
|
+
const fs = await import("fs/promises");
|
|
288
|
+
const exporter = new PlaywrightExporter();
|
|
289
|
+
try {
|
|
290
|
+
await exporter.launch();
|
|
291
|
+
const result = await exporter.exportSVGString(svgString, __spreadProps(__spreadValues({}, options), {
|
|
292
|
+
format: "png"
|
|
293
|
+
}));
|
|
294
|
+
await fs.writeFile(outputPath, result.buffer);
|
|
295
|
+
} finally {
|
|
296
|
+
await exporter.close();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
export {
|
|
300
|
+
PlaywrightExporter,
|
|
301
|
+
exportSVGToPNG,
|
|
302
|
+
exportToPNG,
|
|
303
|
+
generateExportHTML,
|
|
304
|
+
generateExportHTMLWithInlineCSS
|
|
305
|
+
};
|