scribe-cms 0.0.5 → 0.0.7
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/cli/index.cjs +185 -150
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +184 -149
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/translate-progress.d.ts.map +1 -1
- package/dist/index.cjs +114 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +114 -86
- package/dist/index.js.map +1 -1
- package/dist/runtime.cjs +23 -18
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +23 -18
- package/dist/runtime.js.map +1 -1
- package/dist/src/core/localized-slug.d.ts +8 -0
- package/dist/src/core/localized-slug.d.ts.map +1 -0
- package/dist/src/history/record-snapshot.d.ts +11 -0
- package/dist/src/history/record-snapshot.d.ts.map +1 -0
- package/dist/src/storage/sqlite.d.ts.map +1 -1
- package/dist/src/storage/translations.d.ts +14 -21
- package/dist/src/storage/translations.d.ts.map +1 -1
- package/dist/src/translate/page-translator.d.ts +5 -0
- package/dist/src/translate/page-translator.d.ts.map +1 -1
- package/dist/src/translate/prompts/translation-prompt.d.ts.map +1 -1
- package/dist/src/translate/resolve-translate-config.d.ts.map +1 -1
- package/dist/src/validate/validate-slug-suffix.d.ts.map +1 -1
- package/dist/studio/server.cjs +51 -64
- package/dist/studio/server.cjs.map +1 -1
- package/dist/studio/server.d.ts.map +1 -1
- package/dist/studio/server.js +51 -64
- package/dist/studio/server.js.map +1 -1
- package/package.json +2 -1
- package/dist/src/history/record-revision.d.ts +0 -14
- package/dist/src/history/record-revision.d.ts.map +0 -1
package/dist/studio/server.js
CHANGED
|
@@ -333,7 +333,7 @@ function mergeBuiltinsIntoFrontmatter(frontmatter, doc, type, defaultLocale) {
|
|
|
333
333
|
out.canonicalPath = resolveCanonicalPathname(type, doc, defaultLocale);
|
|
334
334
|
return out;
|
|
335
335
|
}
|
|
336
|
-
var SCHEMA_VERSION =
|
|
336
|
+
var SCHEMA_VERSION = 4;
|
|
337
337
|
var MIGRATIONS = [
|
|
338
338
|
`CREATE TABLE IF NOT EXISTS meta (
|
|
339
339
|
key TEXT PRIMARY KEY,
|
|
@@ -353,20 +353,6 @@ var MIGRATIONS = [
|
|
|
353
353
|
)`,
|
|
354
354
|
`CREATE INDEX IF NOT EXISTS idx_translations_type_locale
|
|
355
355
|
ON translations(content_type, locale)`,
|
|
356
|
-
`CREATE TABLE IF NOT EXISTS revisions (
|
|
357
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
358
|
-
content_type TEXT NOT NULL,
|
|
359
|
-
en_slug TEXT NOT NULL,
|
|
360
|
-
locale TEXT,
|
|
361
|
-
revision_kind TEXT NOT NULL,
|
|
362
|
-
en_hash TEXT NOT NULL,
|
|
363
|
-
body_hash TEXT NOT NULL,
|
|
364
|
-
created_at TEXT NOT NULL,
|
|
365
|
-
model TEXT,
|
|
366
|
-
body_preview TEXT
|
|
367
|
-
)`,
|
|
368
|
-
`CREATE INDEX IF NOT EXISTS idx_revisions_lookup
|
|
369
|
-
ON revisions(content_type, en_slug, locale, created_at DESC)`,
|
|
370
356
|
`CREATE TABLE IF NOT EXISTS slug_aliases (
|
|
371
357
|
content_type TEXT NOT NULL,
|
|
372
358
|
canonical_en_slug TEXT NOT NULL,
|
|
@@ -383,7 +369,19 @@ var MIGRATIONS = [
|
|
|
383
369
|
locale_slug TEXT NOT NULL,
|
|
384
370
|
captured_at TEXT NOT NULL,
|
|
385
371
|
PRIMARY KEY (content_type, alias_en_slug, locale)
|
|
386
|
-
)
|
|
372
|
+
)`,
|
|
373
|
+
`CREATE TABLE IF NOT EXISTS en_snapshots (
|
|
374
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
375
|
+
content_type TEXT NOT NULL,
|
|
376
|
+
en_slug TEXT NOT NULL,
|
|
377
|
+
en_hash TEXT NOT NULL,
|
|
378
|
+
frontmatter_json TEXT NOT NULL,
|
|
379
|
+
body TEXT NOT NULL,
|
|
380
|
+
created_at TEXT NOT NULL,
|
|
381
|
+
UNIQUE (content_type, en_slug, en_hash)
|
|
382
|
+
)`,
|
|
383
|
+
`CREATE INDEX IF NOT EXISTS idx_en_snapshots_lookup
|
|
384
|
+
ON en_snapshots(content_type, en_slug, created_at DESC)`
|
|
387
385
|
];
|
|
388
386
|
function resolveStorePath(config) {
|
|
389
387
|
return config.storePath;
|
|
@@ -405,12 +403,19 @@ function addColumnIfMissing(db, table, column, ddlType) {
|
|
|
405
403
|
db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${ddlType}`);
|
|
406
404
|
}
|
|
407
405
|
}
|
|
406
|
+
function readSchemaVersion(db) {
|
|
407
|
+
const row = db.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get();
|
|
408
|
+
return row ? Number.parseInt(row.value, 10) || 0 : 0;
|
|
409
|
+
}
|
|
408
410
|
function migrate(db) {
|
|
411
|
+
const previousVersion = readSchemaVersion(db);
|
|
409
412
|
for (const sql of MIGRATIONS) {
|
|
410
413
|
db.exec(sql);
|
|
411
414
|
}
|
|
412
|
-
|
|
413
|
-
|
|
415
|
+
if (previousVersion < 4) {
|
|
416
|
+
db.exec(`DROP TABLE IF EXISTS revisions`);
|
|
417
|
+
}
|
|
418
|
+
addColumnIfMissing(db, "translations", "snapshot_id", "INTEGER");
|
|
414
419
|
db.prepare(
|
|
415
420
|
`INSERT INTO meta(key, value) VALUES('schema_version', ?)
|
|
416
421
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
@@ -418,6 +423,9 @@ function migrate(db) {
|
|
|
418
423
|
}
|
|
419
424
|
|
|
420
425
|
// src/storage/translations.ts
|
|
426
|
+
function getEnSnapshot(db, snapshotId) {
|
|
427
|
+
return db.prepare(`SELECT * FROM en_snapshots WHERE id = ?`).get(snapshotId);
|
|
428
|
+
}
|
|
421
429
|
function getTranslation(db, contentType, enSlug, locale) {
|
|
422
430
|
return db.prepare(
|
|
423
431
|
`SELECT * FROM translations WHERE content_type = ? AND en_slug = ? AND locale = ?`
|
|
@@ -426,20 +434,6 @@ function getTranslation(db, contentType, enSlug, locale) {
|
|
|
426
434
|
function listTranslationsForLocale(db, contentType, locale) {
|
|
427
435
|
return db.prepare(`SELECT * FROM translations WHERE content_type = ? AND locale = ? ORDER BY en_slug`).all(contentType, locale);
|
|
428
436
|
}
|
|
429
|
-
function listRevisions(db, contentType, enSlug, locale) {
|
|
430
|
-
if (locale) {
|
|
431
|
-
return db.prepare(
|
|
432
|
-
`SELECT * FROM revisions
|
|
433
|
-
WHERE content_type = ? AND en_slug = ? AND locale = ?
|
|
434
|
-
ORDER BY created_at DESC, id DESC`
|
|
435
|
-
).all(contentType, enSlug, locale);
|
|
436
|
-
}
|
|
437
|
-
return db.prepare(
|
|
438
|
-
`SELECT * FROM revisions
|
|
439
|
-
WHERE content_type = ? AND en_slug = ?
|
|
440
|
-
ORDER BY created_at DESC, id DESC`
|
|
441
|
-
).all(contentType, enSlug);
|
|
442
|
-
}
|
|
443
437
|
|
|
444
438
|
// src/loader/normalize-en.ts
|
|
445
439
|
function normalizeEnFrontmatter(data) {
|
|
@@ -672,38 +666,31 @@ function renderFrontmatterTable(frontmatter, schema) {
|
|
|
672
666
|
<tbody>${rows || `<tr><td colspan="2" class="dim">\u2014</td></tr>`}</tbody>
|
|
673
667
|
</table>`;
|
|
674
668
|
}
|
|
675
|
-
function
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
frontmatter = {};
|
|
682
|
-
}
|
|
683
|
-
const fmRows = flattenFrontmatter(frontmatter).map(
|
|
684
|
-
(row) => `<tr><td class="k">${escapeHtml(row.key)}</td><td class="v">${escapeHtml(row.value)}</td></tr>`
|
|
685
|
-
).join("");
|
|
686
|
-
return `<table class="kv"><tbody>${fmRows}</tbody></table>
|
|
687
|
-
<pre class="code">${escapeHtml(revision.body)}</pre>`;
|
|
669
|
+
function renderEnSnapshotPreview(snapshot) {
|
|
670
|
+
let frontmatter = {};
|
|
671
|
+
try {
|
|
672
|
+
frontmatter = JSON.parse(snapshot.frontmatter_json);
|
|
673
|
+
} catch {
|
|
674
|
+
frontmatter = {};
|
|
688
675
|
}
|
|
689
|
-
|
|
676
|
+
const fmRows = flattenFrontmatter(frontmatter).map(
|
|
677
|
+
(row) => `<tr><td class="k">${escapeHtml(row.key)}</td><td class="v">${escapeHtml(row.value)}</td></tr>`
|
|
678
|
+
).join("");
|
|
679
|
+
return `<table class="kv"><tbody>${fmRows}</tbody></table>
|
|
680
|
+
<pre class="code">${escapeHtml(snapshot.body)}</pre>`;
|
|
690
681
|
}
|
|
691
|
-
function
|
|
692
|
-
if (
|
|
693
|
-
return `<p class="dim">No
|
|
682
|
+
function renderTranslationSnapshotPanel(snapshot, currentEnHash) {
|
|
683
|
+
if (!snapshot) {
|
|
684
|
+
return `<p class="dim">No EN snapshot linked to this translation.</p>`;
|
|
694
685
|
}
|
|
695
|
-
const
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
).join("");
|
|
704
|
-
return `<table class="data"><thead><tr>
|
|
705
|
-
<th>When</th><th>Kind</th><th>Model</th><th>Hash</th><th></th>
|
|
706
|
-
</tr></thead><tbody>${items}</tbody></table>`;
|
|
686
|
+
const staleNote = currentEnHash && currentEnHash !== snapshot.en_hash ? `<p class="dim">Current EN hash differs from snapshot (${escapeHtml(currentEnHash.slice(0, 12))} vs ${escapeHtml(snapshot.en_hash.slice(0, 12))}).</p>` : "";
|
|
687
|
+
return `<dl class="meta">
|
|
688
|
+
<dt>snapshot</dt><dd>#${snapshot.id}</dd>
|
|
689
|
+
<dt>captured</dt><dd>${escapeHtml(snapshot.created_at.slice(0, 19))}</dd>
|
|
690
|
+
<dt>en_hash</dt><dd class="mono">${escapeHtml(snapshot.en_hash.slice(0, 12))}</dd>
|
|
691
|
+
</dl>
|
|
692
|
+
${staleNote}
|
|
693
|
+
<details><summary>EN source at translation time</summary>${renderEnSnapshotPreview(snapshot)}</details>`;
|
|
707
694
|
}
|
|
708
695
|
function renderLayout(title, body, project, options = {}) {
|
|
709
696
|
const typeLinks = project.listTypes().map((type) => {
|
|
@@ -1014,10 +1001,10 @@ async function startStudio(project, options = {}) {
|
|
|
1014
1001
|
<dt>slug</dt><dd>${escapeHtml(translation.slug)}</dd>
|
|
1015
1002
|
<dt>en_hash</dt><dd>${escapeHtml(currentEnHash?.slice(0, 12) ?? "\u2014")} / ${escapeHtml(storedEnHash?.slice(0, 12) ?? "\u2014")}</dd>
|
|
1016
1003
|
</dl>`;
|
|
1017
|
-
const
|
|
1004
|
+
const snapshot = translation.snapshot_id != null ? getEnSnapshot(db, translation.snapshot_id) : void 0;
|
|
1018
1005
|
historyPanel = `<div class="section">
|
|
1019
|
-
<div class="section-head">
|
|
1020
|
-
<div class="section-body">${
|
|
1006
|
+
<div class="section-head">EN snapshot</div>
|
|
1007
|
+
<div class="section-body">${renderTranslationSnapshotPanel(snapshot, currentEnHash)}</div>
|
|
1021
1008
|
</div>`;
|
|
1022
1009
|
} else {
|
|
1023
1010
|
contentPanel = `<p class="dim" style="padding:12px">No translation for ${escapeHtml(locale)}.</p>`;
|