@akairos/typeset-studio 0.2.0 → 0.2.1
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/dist/lib/adapter.js +343 -310
- package/dist/lib/index.js +343 -310
- package/package.json +1 -1
- package/src/adapter.ts +1 -1
- package/src/server/routes/templates.ts +50 -11
package/package.json
CHANGED
package/src/adapter.ts
CHANGED
|
@@ -192,7 +192,7 @@ async function renderRemoteBatch(
|
|
|
192
192
|
|
|
193
193
|
export const typesetStudioAdapter: ImageRenderPlugin = {
|
|
194
194
|
name: "typeset-studio",
|
|
195
|
-
version: "0.2.
|
|
195
|
+
version: "0.2.1",
|
|
196
196
|
|
|
197
197
|
async doctor(): Promise<PipelinePluginDoctorCheck[]> {
|
|
198
198
|
const checks: PipelinePluginDoctorCheck[] = [];
|
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
2
|
+
import { dirname, join, resolve } from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
3
4
|
import { Hono } from "hono";
|
|
4
5
|
import { getDefaultConfig } from "../../core/engine";
|
|
5
6
|
import { TemplateSlot, TypesetConfig } from "../../core/types";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
export function resolveDataDir(): string {
|
|
9
|
+
if (process.env.TYPESET_DATA_DIR) {
|
|
10
|
+
return process.env.TYPESET_DATA_DIR;
|
|
11
|
+
}
|
|
12
|
+
const currentDir = typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const candidateLib = resolve(currentDir, "../../data");
|
|
14
|
+
if (existsSync(candidateLib)) return candidateLib;
|
|
15
|
+
const candidateSrc = resolve(currentDir, "../../../data");
|
|
16
|
+
if (existsSync(candidateSrc)) return candidateSrc;
|
|
17
|
+
const candidateCwd = resolve(process.cwd(), "data");
|
|
18
|
+
if (existsSync(candidateCwd)) return candidateCwd;
|
|
19
|
+
return candidateLib;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const TEMPLATES_DIR = join(resolveDataDir(), "templates");
|
|
8
23
|
|
|
9
24
|
function ensureTemplatesDir(): void {
|
|
10
25
|
if (!existsSync(TEMPLATES_DIR)) {
|
|
11
|
-
|
|
26
|
+
try {
|
|
27
|
+
mkdirSync(TEMPLATES_DIR, { recursive: true });
|
|
28
|
+
} catch {
|
|
29
|
+
// Ignore write errors in read-only environments
|
|
30
|
+
}
|
|
12
31
|
}
|
|
13
32
|
seedDefaultTemplates();
|
|
14
33
|
}
|
|
15
34
|
|
|
16
|
-
|
|
17
|
-
const presets: TypesetConfig[] = [
|
|
35
|
+
export const BUILTIN_PRESETS: TypesetConfig[] = [
|
|
18
36
|
{
|
|
19
37
|
...getDefaultConfig("wechat-cover-2.35"),
|
|
20
38
|
id: "tpl_wechat_cover_minimal",
|
|
@@ -325,13 +343,21 @@ function seedDefaultTemplates(): void {
|
|
|
325
343
|
},
|
|
326
344
|
];
|
|
327
345
|
|
|
328
|
-
|
|
346
|
+
function seedDefaultTemplates(): void {
|
|
347
|
+
if (!existsSync(TEMPLATES_DIR)) return;
|
|
348
|
+
for (const preset of BUILTIN_PRESETS) {
|
|
329
349
|
const filePath = join(TEMPLATES_DIR, `${preset.id}.json`);
|
|
330
|
-
|
|
350
|
+
if (!existsSync(filePath)) {
|
|
351
|
+
try {
|
|
352
|
+
writeFileSync(filePath, JSON.stringify(preset, null, 2), "utf-8");
|
|
353
|
+
} catch {
|
|
354
|
+
// Ignore write failures in package directories
|
|
355
|
+
}
|
|
356
|
+
}
|
|
331
357
|
}
|
|
332
358
|
}
|
|
333
359
|
|
|
334
|
-
const DEFAULT_SETTINGS_PATH = join(
|
|
360
|
+
const DEFAULT_SETTINGS_PATH = join(resolveDataDir(), "default-template.json");
|
|
335
361
|
|
|
336
362
|
export const BUILTIN_SLOT_DEFAULTS: Record<TemplateSlot, string> = {
|
|
337
363
|
article_cover: "tpl_wechat_cover_minimal",
|
|
@@ -411,7 +437,21 @@ export function setDefaultTemplateId(id: string): void {
|
|
|
411
437
|
}
|
|
412
438
|
|
|
413
439
|
export function findTemplateByKeyOrName(key: string): TypesetConfig | null {
|
|
414
|
-
|
|
440
|
+
const lowerKey = key.trim().toLowerCase();
|
|
441
|
+
|
|
442
|
+
// 1. Direct match in built-in memory presets
|
|
443
|
+
const builtin = BUILTIN_PRESETS.find(
|
|
444
|
+
(p) => p.id?.toLowerCase() === lowerKey || p.name.toLowerCase() === lowerKey,
|
|
445
|
+
);
|
|
446
|
+
if (builtin) return builtin;
|
|
447
|
+
|
|
448
|
+
// 2. Partial match in built-in memory presets
|
|
449
|
+
const builtinPartial = BUILTIN_PRESETS.find((p) => p.name.toLowerCase().includes(lowerKey));
|
|
450
|
+
if (builtinPartial) return builtinPartial;
|
|
451
|
+
|
|
452
|
+
// 3. Scan disk if templates directory exists
|
|
453
|
+
if (!existsSync(TEMPLATES_DIR)) return null;
|
|
454
|
+
|
|
415
455
|
const directPath = join(TEMPLATES_DIR, `${key}.json`);
|
|
416
456
|
if (existsSync(directPath)) {
|
|
417
457
|
try {
|
|
@@ -421,9 +461,8 @@ export function findTemplateByKeyOrName(key: string): TypesetConfig | null {
|
|
|
421
461
|
}
|
|
422
462
|
}
|
|
423
463
|
|
|
424
|
-
// Scan all templates
|
|
464
|
+
// Scan all templates on disk
|
|
425
465
|
const files = readdirSync(TEMPLATES_DIR).filter((f) => f.endsWith(".json"));
|
|
426
|
-
const lowerKey = key.trim().toLowerCase();
|
|
427
466
|
|
|
428
467
|
for (const file of files) {
|
|
429
468
|
try {
|