@musnows/scriverse 0.4.4 → 0.4.5
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/app.js +10 -5
- package/dist/app.js.map +1 -1
- package/dist/public/app.js +107 -47
- package/dist/public/index.html +6 -4
- package/dist/public/relationship-graph.js +108 -26
- package/dist/public/styles.css +17 -7
- package/dist/store.js +61 -40
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +1 -1
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/public/styles.css
CHANGED
|
@@ -987,8 +987,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
987
987
|
.character-duplicate-pair section > small { color: var(--muted); }
|
|
988
988
|
.character-duplicate-pair section p { margin: 0; }
|
|
989
989
|
.character-duplicate-evidence { display: grid; gap: 8px; margin: 13px 0; padding: 0; list-style: none; }
|
|
990
|
-
.character-duplicate-evidence li { display: grid; gap: 5px; padding: 10px 12px; border-left: 2px solid var(--accent); background: var(--surface-soft); }
|
|
991
|
-
.character-duplicate-evidence q { color: var(--text); line-height: 1.
|
|
990
|
+
.character-duplicate-evidence li { display: grid; gap: 5px; padding: 10px 12px; border-left: 2px solid var(--accent); background: var(--surface-soft); font-size: 12px; }
|
|
991
|
+
.character-duplicate-evidence q { color: var(--text); font-size: 12px; line-height: 1.45; }
|
|
992
992
|
.character-duplicate-evidence small, .review-resolution-note { color: var(--muted); }
|
|
993
993
|
.character-duplicate-actions { flex-wrap: wrap; }
|
|
994
994
|
.card-actions { display: flex; gap: 6px; margin-top: 15px; }
|
|
@@ -1339,9 +1339,9 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1339
1339
|
.galaxy-node { --node-size: 12px; position: absolute; left: 0; top: 0; display: grid; grid-template-rows: var(--node-size) auto; justify-items: center; align-items: start; gap: 5px; padding: 8px; border: 0; background: transparent; color: #edf7ff; cursor: grab; touch-action: none; pointer-events: auto; transform-origin: center; opacity: var(--depth-opacity, 1); will-change: transform, opacity; }
|
|
1340
1340
|
.galaxy-node i { position: relative; isolation: isolate; width: var(--node-size); height: var(--node-size); border-radius: 50%; background: radial-gradient(circle at 32% 27%, var(--node-core, #fff) 0 7%, color-mix(in srgb, var(--node-color) 62%, #fff) 18%, var(--node-color) 52%, var(--node-rim, #07101f) 100%); box-shadow: inset -3px -4px 7px color-mix(in srgb, var(--node-rim, #07101f) 74%, transparent), 0 0 4px rgba(255,255,255,.82), 0 0 calc(7px + var(--node-glow) * 11px) var(--node-color), 0 0 calc(15px + var(--node-glow) * 25px) var(--node-atmosphere, color-mix(in srgb, var(--node-color) 72%, transparent)); filter: brightness(var(--node-brightness)); transition: filter .18s ease, box-shadow .18s ease; }
|
|
1341
1341
|
.galaxy-node i::before, .galaxy-node i::after { content: ""; position: absolute; pointer-events: none; }
|
|
1342
|
-
.galaxy-node i::before { z-index: -1; inset: -
|
|
1342
|
+
.galaxy-node i::before { z-index: -1; inset: -34%; border-radius: 50%; background: radial-gradient(circle, var(--node-atmosphere) 0, transparent 68%); opacity: .64; }
|
|
1343
1343
|
.galaxy-node[data-celestial-type="star"] i { background: radial-gradient(circle at 38% 34%, #fff 0 10%, var(--node-core) 22%, var(--node-color) 53%, var(--node-rim) 100%); box-shadow: 0 0 5px #fff, 0 0 calc(10px + var(--node-glow) * 15px) var(--node-color), 0 0 calc(24px + var(--node-glow) * 34px) var(--node-atmosphere); }
|
|
1344
|
-
.galaxy-node[data-celestial-type="star"] i::before { inset: -
|
|
1344
|
+
.galaxy-node[data-celestial-type="star"] i::before { inset: -48%; opacity: .92; background: radial-gradient(circle, var(--node-atmosphere) 0 12%, transparent 66%); }
|
|
1345
1345
|
.galaxy-node[data-celestial-type="gas-giant"] i { background: linear-gradient(168deg, transparent 0 17%, color-mix(in srgb, var(--node-core) 78%, transparent) 18% 25%, transparent 26% 40%, color-mix(in srgb, var(--node-rim) 64%, transparent) 41% 50%, transparent 51% 68%, color-mix(in srgb, var(--node-core) 54%, transparent) 69% 75%, transparent 76%), radial-gradient(circle at 34% 28%, var(--node-core) 0 7%, var(--node-color) 42%, var(--node-rim) 100%); }
|
|
1346
1346
|
.galaxy-node[data-celestial-type="ringed"] i::after { z-index: 2; left: 50%; top: 50%; width: 168%; height: 48%; border: 1px solid var(--node-ring); border-left-color: color-mix(in srgb, var(--node-ring) 28%, transparent); border-right-color: color-mix(in srgb, var(--node-ring) 88%, #fff); border-radius: 50%; box-shadow: 0 0 3px var(--node-atmosphere); transform: translate(-50%, -50%) rotate(-19deg); }
|
|
1347
1347
|
.galaxy-node[data-celestial-type="ocean"] i { background: radial-gradient(ellipse at 67% 63%, color-mix(in srgb, var(--node-core) 48%, transparent) 0 10%, transparent 12%), radial-gradient(circle at 28% 24%, var(--node-core) 0 6%, var(--node-color) 38%, color-mix(in srgb, var(--node-color) 58%, #0b2f62) 72%, var(--node-rim) 100%); }
|
|
@@ -1701,6 +1701,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1701
1701
|
.entity-editor-header, .character-editor-header { display: grid; grid-template-columns: minmax(160px, 1fr) minmax(0, 2fr) minmax(160px, 1fr); align-items: center; gap: 24px; min-height: 78px; padding: 14px clamp(18px, 3vw, 44px); border-bottom: 1px solid var(--line); background: var(--panel); }
|
|
1702
1702
|
.entity-editor-heading { min-width: 0; text-align: center; }
|
|
1703
1703
|
.entity-editor-heading h1 { overflow: hidden; margin: 2px 0 0; font-size: 24px; font-weight: 600; text-overflow: ellipsis; white-space: nowrap; }
|
|
1704
|
+
.entity-editor-readonly-badge { display: inline-block; width: fit-content; margin: 0 auto; padding: 3px 7px; border: 1px solid color-mix(in srgb, var(--muted) 55%, var(--line)); border-radius: 999px; color: var(--muted); font-size: 10px; line-height: 1.2; }
|
|
1705
|
+
.character-editor-title-row .entity-editor-readonly-badge { margin-left: 6px; vertical-align: middle; }
|
|
1704
1706
|
.entity-editor-header > .primary-button { justify-self: end; min-width: 112px; }
|
|
1705
1707
|
.entity-editor-back { justify-self: start; min-height: 36px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 4px; background: transparent; color: var(--muted); font-size: 11px; }
|
|
1706
1708
|
.entity-editor-back::before { content: "←"; margin-right: 7px; }
|
|
@@ -1731,8 +1733,13 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1731
1733
|
.vditor-editor-host.vditor { height: 100% !important; min-height: 0; overflow: hidden; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); color: var(--ink); }
|
|
1732
1734
|
.vditor-editor-host.vditor:not(.vditor--dark) { --border-color: var(--line); --panel-background-color: var(--surface); --toolbar-background-color: var(--surface-soft); --toolbar-icon-color: var(--muted); --toolbar-icon-hover-color: var(--accent-dark); --textarea-background-color: var(--surface); --textarea-text-color: var(--ink); --heading-border-color: var(--line); --blockquote-color: var(--muted); }
|
|
1733
1735
|
.vditor-editor-host.vditor--dark { --border-color: var(--line); --panel-background-color: var(--surface); --toolbar-background-color: var(--surface-soft); --toolbar-icon-color: var(--muted); --toolbar-icon-hover-color: var(--accent); --textarea-background-color: var(--surface); --textarea-text-color: var(--ink); --heading-border-color: var(--line); --blockquote-color: var(--muted); }
|
|
1734
|
-
.vditor-editor-host .vditor-toolbar { flex: 0 0 auto; }
|
|
1735
|
-
.vditor-editor-host .markdown-word-count { display: inline-flex; align-items: center; min-height: 28px; margin-left:
|
|
1736
|
+
.vditor-editor-host .vditor-toolbar { display: flex; align-items: center; flex: 0 0 auto; }
|
|
1737
|
+
.vditor-editor-host .markdown-word-count { display: inline-flex; align-items: center; align-self: center; min-height: 28px; margin-left: 24px; padding: 0 10px; color: var(--muted); font: 10px/1 var(--font-latin), var(--font-cjk), sans-serif; white-space: nowrap; }
|
|
1738
|
+
.vditor-editor-host .vditor-content { position: relative; }
|
|
1739
|
+
.vditor-editor-host .vditor-line-numbers { display: none; position: absolute; z-index: 1; inset: 0 auto 0 0; width: 42px; padding: 16px 8px 16px 0; overflow: hidden; border-right: 1px solid var(--line); background: color-mix(in srgb, var(--surface-soft) 88%, transparent); color: var(--muted); font: 12px/1.75 var(--font-latin), monospace; text-align: right; user-select: none; pointer-events: none; }
|
|
1740
|
+
.vditor-editor-host.vditor.show-line-numbers .vditor-line-numbers { display: grid; align-content: start; }
|
|
1741
|
+
.vditor-editor-host.vditor.show-line-numbers .vditor-ir, .vditor-editor-host.vditor.show-line-numbers .vditor-wysiwyg, .vditor-editor-host.vditor.show-line-numbers .vditor-sv textarea { padding-left: 42px; }
|
|
1742
|
+
.vditor-editor-host .vditor-line-number-button[aria-pressed="true"] { color: var(--accent-dark); background: color-mix(in srgb, var(--accent) 16%, transparent); }
|
|
1736
1743
|
.vditor-editor-host .vditor-content { min-height: 0; }
|
|
1737
1744
|
.vditor-editor-host .vditor-reset { color: var(--ink); font-family: var(--font-cjk), var(--font-latin), sans-serif; }
|
|
1738
1745
|
.vditor-editor-host .vditor-ir, .vditor-editor-host .vditor-sv, .vditor-editor-host .vditor-wysiwyg { background: var(--surface); color: var(--ink); }
|
|
@@ -1837,11 +1844,14 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1837
1844
|
.character-section-editor-header > div { grid-column: 1; grid-row: 1; justify-self: center; text-align: center; }
|
|
1838
1845
|
.character-section-editor-header .entity-editor-back { grid-column: 1; grid-row: 1; z-index: 1; }
|
|
1839
1846
|
.character-section-editor-header h2 { margin: 3px 0 0; font-size: 22px; font-weight: 600; }
|
|
1847
|
+
.character-section-editor-title-input { width: min(100%, 520px); margin: 3px auto 0; padding: 0 0 4px; border: 0; border-bottom: 1px solid transparent; border-radius: 0; background: transparent; color: var(--ink); font-size: 22px; font-weight: 600; line-height: 1.2; text-align: center; }
|
|
1848
|
+
.character-section-editor-title-input::placeholder { color: var(--ink); opacity: .92; }
|
|
1849
|
+
.character-section-editor-title-input:focus { border-color: var(--accent); box-shadow: none; }
|
|
1840
1850
|
.character-markdown-editor { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 12px; min-height: 0; padding: 16px 22px 18px; overflow: hidden; background: var(--surface-soft); }
|
|
1841
1851
|
.character-markdown-editor > .vditor-editor-host { width: 100%; max-width: 960px; justify-self: center; }
|
|
1842
1852
|
.character-markdown-editor > .vditor-editor-host.vditor { border-color: color-mix(in srgb, var(--accent) 22%, var(--line)); box-shadow: 0 12px 34px color-mix(in srgb, var(--ink) 12%, transparent); transition: border-color .16s ease, box-shadow .16s ease; }
|
|
1843
1853
|
.character-markdown-editor > .vditor-editor-host.vditor:focus-within { border-color: color-mix(in srgb, var(--accent) 62%, var(--line)); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 15%, transparent), 0 16px 42px color-mix(in srgb, var(--ink) 16%, transparent); }
|
|
1844
|
-
.character-markdown-editor-meta { display: grid; grid-template-columns: minmax(
|
|
1854
|
+
.character-markdown-editor-meta { display: grid; grid-template-columns: minmax(160px, .55fr) minmax(280px, 1.45fr); gap: 12px; }
|
|
1845
1855
|
.character-markdown-editor label { display: grid; gap: 6px; color: var(--muted); font-size: 10px; }
|
|
1846
1856
|
.character-markdown-editor input, .character-markdown-editor select, .character-markdown-editor textarea { width: 100%; padding: 9px 10px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); color: var(--ink); font-size: 12px; }
|
|
1847
1857
|
.character-markdown-summary-field textarea { min-height: 42px; height: 42px; resize: vertical; }
|
package/dist/store.js
CHANGED
|
@@ -1702,15 +1702,15 @@ export class Store {
|
|
|
1702
1702
|
});
|
|
1703
1703
|
return this.getSetting(settingId);
|
|
1704
1704
|
}
|
|
1705
|
-
listSettings(workId) {
|
|
1705
|
+
listSettings(workId, includeContent = true) {
|
|
1706
1706
|
this.getWork(workId);
|
|
1707
|
-
return this.db.all("SELECT * FROM settings WHERE work_id = ? ORDER BY locked DESC, category, title", workId).map((row) => this.mapSetting(row));
|
|
1707
|
+
return this.db.all("SELECT * FROM settings WHERE work_id = ? ORDER BY locked DESC, category, title", workId).map((row) => this.mapSetting(row, includeContent));
|
|
1708
1708
|
}
|
|
1709
|
-
listSettingsPage(workId, pagination) {
|
|
1709
|
+
listSettingsPage(workId, pagination, includeContent = true) {
|
|
1710
1710
|
this.getWork(workId);
|
|
1711
1711
|
const page = paginationSql(pagination);
|
|
1712
1712
|
const rows = this.db.all(`SELECT * FROM settings WHERE work_id = ? ORDER BY locked DESC, category, title${page.sql}`, workId, ...page.params);
|
|
1713
|
-
return paginated(rows.map((row) => this.mapSetting(row)), pagination);
|
|
1713
|
+
return paginated(rows.map((row) => this.mapSetting(row, includeContent)), pagination);
|
|
1714
1714
|
}
|
|
1715
1715
|
getSetting(settingId) {
|
|
1716
1716
|
const row = this.db.get("SELECT * FROM settings WHERE id = ?", settingId);
|
|
@@ -1741,13 +1741,14 @@ export class Store {
|
|
|
1741
1741
|
this.audit(String(current.workId), "setting.deleted", "setting", settingId);
|
|
1742
1742
|
});
|
|
1743
1743
|
}
|
|
1744
|
-
mapSetting(row) {
|
|
1744
|
+
mapSetting(row, includeContent = true) {
|
|
1745
|
+
const content = requiredString(row, "content");
|
|
1745
1746
|
return {
|
|
1746
1747
|
id: requiredString(row, "id"),
|
|
1747
1748
|
workId: requiredString(row, "work_id"),
|
|
1748
1749
|
title: requiredString(row, "title"),
|
|
1749
1750
|
category: requiredString(row, "category"),
|
|
1750
|
-
content:
|
|
1751
|
+
...(includeContent ? { content } : { contentPreview: content.replace(/\s+/gu, " ").trim().slice(0, 320) }),
|
|
1751
1752
|
tags: json(requiredString(row, "tags_json"), []),
|
|
1752
1753
|
status: requiredString(row, "status"),
|
|
1753
1754
|
locked: booleanValue(row, "locked"),
|
|
@@ -1788,21 +1789,21 @@ export class Store {
|
|
|
1788
1789
|
});
|
|
1789
1790
|
return this.getRace(raceId);
|
|
1790
1791
|
}
|
|
1791
|
-
listRaces(workId) {
|
|
1792
|
+
listRaces(workId, includeMarkdown = true) {
|
|
1792
1793
|
this.getWork(workId);
|
|
1793
|
-
return this.db.all("SELECT * FROM races WHERE work_id = ? ORDER BY name", workId).map((row) => this.mapRace(row));
|
|
1794
|
+
return this.db.all("SELECT * FROM races WHERE work_id = ? ORDER BY name", workId).map((row) => this.mapRace(row, includeMarkdown));
|
|
1794
1795
|
}
|
|
1795
|
-
listRacesPage(workId, pagination) {
|
|
1796
|
+
listRacesPage(workId, pagination, includeMarkdown = true) {
|
|
1796
1797
|
this.getWork(workId);
|
|
1797
1798
|
const page = paginationSql(pagination);
|
|
1798
1799
|
const rows = this.db.all(`SELECT * FROM races WHERE work_id = ? ORDER BY name${page.sql}`, workId, ...page.params);
|
|
1799
|
-
return paginated(rows.map((row) => this.mapRace(row)), pagination);
|
|
1800
|
+
return paginated(rows.map((row) => this.mapRace(row, includeMarkdown)), pagination);
|
|
1800
1801
|
}
|
|
1801
|
-
getRace(raceId) {
|
|
1802
|
+
getRace(raceId, includeMarkdown = true) {
|
|
1802
1803
|
const row = this.db.get("SELECT * FROM races WHERE id = ?", raceId);
|
|
1803
1804
|
if (!row)
|
|
1804
1805
|
throw notFound("种族");
|
|
1805
|
-
return this.mapRace(row);
|
|
1806
|
+
return this.mapRace(row, includeMarkdown);
|
|
1806
1807
|
}
|
|
1807
1808
|
updateRace(raceId, input, source = "manual", sourceRef = null, changeNote = "", expectedVersionNo) {
|
|
1808
1809
|
const current = this.getRace(raceId);
|
|
@@ -1908,9 +1909,9 @@ export class Store {
|
|
|
1908
1909
|
const row = this.db.get("SELECT id FROM races WHERE work_id = ? AND normalized_name = ?", workId, normalizedName);
|
|
1909
1910
|
return row ? requiredString(row, "id") : null;
|
|
1910
1911
|
}
|
|
1911
|
-
mapRace(row) {
|
|
1912
|
+
mapRace(row, includeMarkdown = true) {
|
|
1912
1913
|
const raceId = requiredString(row, "id");
|
|
1913
|
-
const lineage = this.raceLineage(raceId);
|
|
1914
|
+
const lineage = includeMarkdown ? this.raceLineage(raceId) : this.raceLineageNames(raceId);
|
|
1914
1915
|
const settingsSections = knowledgeSectionsFromStored(row.settings_sections_json, json(requiredString(row, "settings_json"), []));
|
|
1915
1916
|
const settings = settingsFromKnowledgeSections(settingsSections);
|
|
1916
1917
|
const members = this.db.all("SELECT id, name FROM characters WHERE race_id = ? ORDER BY name", requiredString(row, "id")).map((member) => ({
|
|
@@ -1923,19 +1924,21 @@ export class Store {
|
|
|
1923
1924
|
parentRaceId: optionalString(row, "parent_race_id"),
|
|
1924
1925
|
name: requiredString(row, "name"),
|
|
1925
1926
|
description: requiredString(row, "description"),
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1927
|
+
...(includeMarkdown
|
|
1928
|
+
? { settings, settingsMarkdown: settingsMarkdownFromList(settings), settingsSections }
|
|
1929
|
+
: { settings: [], settingsCount: settingsSections.length }),
|
|
1929
1930
|
lineage: lineage.map((item) => ({ id: item.id, name: item.name })),
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1931
|
+
...(includeMarkdown
|
|
1932
|
+
? { effectiveSettings: lineage.flatMap((item, index) => item.settingsSections.map((section) => ({
|
|
1933
|
+
title: section.title,
|
|
1934
|
+
summary: section.summary,
|
|
1935
|
+
sortOrder: section.sortOrder,
|
|
1936
|
+
value: section.contentMarkdown,
|
|
1937
|
+
sourceRaceId: item.id,
|
|
1938
|
+
sourceRaceName: item.name,
|
|
1939
|
+
inherited: index < lineage.length - 1
|
|
1940
|
+
}))) }
|
|
1941
|
+
: {}),
|
|
1939
1942
|
memberIds: members.map((member) => member.characterId),
|
|
1940
1943
|
members,
|
|
1941
1944
|
versionNo: this.currentEntityVersionNo("race", requiredString(row, "id")),
|
|
@@ -1995,6 +1998,22 @@ export class Store {
|
|
|
1995
1998
|
}
|
|
1996
1999
|
return lineage.reverse();
|
|
1997
2000
|
}
|
|
2001
|
+
raceLineageNames(raceId) {
|
|
2002
|
+
const lineage = [];
|
|
2003
|
+
const seen = new Set();
|
|
2004
|
+
let currentId = raceId;
|
|
2005
|
+
while (currentId) {
|
|
2006
|
+
if (seen.has(currentId))
|
|
2007
|
+
throw new AppError(500, "RACE_HIERARCHY_INVALID", "种族层级存在循环");
|
|
2008
|
+
seen.add(currentId);
|
|
2009
|
+
const row = this.db.get("SELECT id, name, parent_race_id FROM races WHERE id = ?", currentId);
|
|
2010
|
+
if (!row)
|
|
2011
|
+
throw new AppError(500, "RACE_HIERARCHY_INVALID", "种族层级引用了不存在的父种族");
|
|
2012
|
+
lineage.push({ id: requiredString(row, "id"), name: requiredString(row, "name") });
|
|
2013
|
+
currentId = optionalString(row, "parent_race_id");
|
|
2014
|
+
}
|
|
2015
|
+
return lineage.reverse();
|
|
2016
|
+
}
|
|
1998
2017
|
replaceRaceMembers(raceId, raceName, memberIds) {
|
|
1999
2018
|
const timestamp = now();
|
|
2000
2019
|
this.db.run("UPDATE characters SET race_id = NULL, species = '', updated_at = ? WHERE race_id = ?", timestamp, raceId);
|
|
@@ -2029,15 +2048,15 @@ export class Store {
|
|
|
2029
2048
|
});
|
|
2030
2049
|
return this.getOrganization(organizationId);
|
|
2031
2050
|
}
|
|
2032
|
-
listOrganizations(workId) {
|
|
2051
|
+
listOrganizations(workId, includeMarkdown = true) {
|
|
2033
2052
|
this.getWork(workId);
|
|
2034
|
-
return this.db.all("SELECT * FROM organizations WHERE work_id = ? ORDER BY name", workId).map((row) => this.mapOrganization(row));
|
|
2053
|
+
return this.db.all("SELECT * FROM organizations WHERE work_id = ? ORDER BY name", workId).map((row) => this.mapOrganization(row, includeMarkdown));
|
|
2035
2054
|
}
|
|
2036
|
-
listOrganizationsPage(workId, pagination) {
|
|
2055
|
+
listOrganizationsPage(workId, pagination, includeMarkdown = true) {
|
|
2037
2056
|
this.getWork(workId);
|
|
2038
2057
|
const page = paginationSql(pagination);
|
|
2039
2058
|
const rows = this.db.all(`SELECT * FROM organizations WHERE work_id = ? ORDER BY name${page.sql}`, workId, ...page.params);
|
|
2040
|
-
return paginated(rows.map((row) => this.mapOrganization(row)), pagination);
|
|
2059
|
+
return paginated(rows.map((row) => this.mapOrganization(row, includeMarkdown)), pagination);
|
|
2041
2060
|
}
|
|
2042
2061
|
getOrganization(organizationId) {
|
|
2043
2062
|
const row = this.db.get("SELECT * FROM organizations WHERE id = ?", organizationId);
|
|
@@ -2124,7 +2143,7 @@ export class Store {
|
|
|
2124
2143
|
});
|
|
2125
2144
|
return { mergeId, target: this.getOrganization(targetOrganizationId), source };
|
|
2126
2145
|
}
|
|
2127
|
-
mapOrganization(row) {
|
|
2146
|
+
mapOrganization(row, includeMarkdown = true) {
|
|
2128
2147
|
const settingsSections = knowledgeSectionsFromStored(row.settings_sections_json, json(requiredString(row, "settings_json"), []));
|
|
2129
2148
|
const settings = settingsFromKnowledgeSections(settingsSections);
|
|
2130
2149
|
const members = this.db.all(`SELECT c.id, c.name, m.role, m.note
|
|
@@ -2141,9 +2160,9 @@ export class Store {
|
|
|
2141
2160
|
workId: requiredString(row, "work_id"),
|
|
2142
2161
|
name: requiredString(row, "name"),
|
|
2143
2162
|
description: requiredString(row, "description"),
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2163
|
+
...(includeMarkdown
|
|
2164
|
+
? { settings, settingsMarkdown: settingsMarkdownFromList(settings), settingsSections }
|
|
2165
|
+
: { settings: [], settingsCount: settingsSections.length }),
|
|
2147
2166
|
memberIds: members.map((member) => member.characterId),
|
|
2148
2167
|
members,
|
|
2149
2168
|
versionNo: this.currentEntityVersionNo("organization", requiredString(row, "id")),
|
|
@@ -2256,16 +2275,16 @@ export class Store {
|
|
|
2256
2275
|
});
|
|
2257
2276
|
return this.getCharacter(characterId);
|
|
2258
2277
|
}
|
|
2259
|
-
listCharacters(workId, includeProfileSections = false, includeMerged = false) {
|
|
2278
|
+
listCharacters(workId, includeProfileSections = false, includeMerged = false, includeRaceMarkdown = true) {
|
|
2260
2279
|
this.getWork(workId);
|
|
2261
2280
|
return this.db.all(`SELECT * FROM characters WHERE work_id = ?${includeMerged ? "" : " AND merged_into_character_id IS NULL"} ORDER BY name`, workId)
|
|
2262
|
-
.map((row) => this.mapCharacter(row, includeProfileSections));
|
|
2281
|
+
.map((row) => this.mapCharacter(row, includeProfileSections, includeRaceMarkdown));
|
|
2263
2282
|
}
|
|
2264
|
-
listCharactersPage(workId, pagination, includeProfileSections = false, includeMerged = false) {
|
|
2283
|
+
listCharactersPage(workId, pagination, includeProfileSections = false, includeMerged = false, includeRaceMarkdown = true) {
|
|
2265
2284
|
this.getWork(workId);
|
|
2266
2285
|
const page = paginationSql(pagination);
|
|
2267
2286
|
const rows = this.db.all(`SELECT * FROM characters WHERE work_id = ?${includeMerged ? "" : " AND merged_into_character_id IS NULL"} ORDER BY name${page.sql}`, workId, ...page.params);
|
|
2268
|
-
return paginated(rows.map((row) => this.mapCharacter(row, includeProfileSections)), pagination);
|
|
2287
|
+
return paginated(rows.map((row) => this.mapCharacter(row, includeProfileSections, includeRaceMarkdown)), pagination);
|
|
2269
2288
|
}
|
|
2270
2289
|
mapCharacterProfileSection(row) {
|
|
2271
2290
|
return {
|
|
@@ -2723,7 +2742,7 @@ export class Store {
|
|
|
2723
2742
|
this.audit(workId, "character.deleted", "character", characterId, { versionNo });
|
|
2724
2743
|
});
|
|
2725
2744
|
}
|
|
2726
|
-
mapCharacter(row, includeProfileSections = true) {
|
|
2745
|
+
mapCharacter(row, includeProfileSections = true, includeRaceMarkdown = true) {
|
|
2727
2746
|
const indexedAliases = this.db.all("SELECT display_name FROM character_names WHERE character_id = ? AND kind = 'alias' ORDER BY sort_order", requiredString(row, "id")).map((item) => requiredString(item, "display_name"));
|
|
2728
2747
|
const organizations = this.db.all(`SELECT o.id, o.name, m.role, m.note
|
|
2729
2748
|
FROM character_organization_memberships m
|
|
@@ -2735,9 +2754,11 @@ export class Store {
|
|
|
2735
2754
|
note: requiredString(item, "note")
|
|
2736
2755
|
}));
|
|
2737
2756
|
const raceId = optionalString(row, "race_id");
|
|
2738
|
-
const race = raceId ? this.getRace(raceId) : undefined;
|
|
2757
|
+
const race = raceId ? this.getRace(raceId, includeRaceMarkdown) : undefined;
|
|
2739
2758
|
const species = race ? String(race.name) : requiredString(row, "species");
|
|
2740
2759
|
const profile = json(requiredString(row, "profile_json"), {});
|
|
2760
|
+
if (!includeProfileSections)
|
|
2761
|
+
delete profile.sections;
|
|
2741
2762
|
const characterId = requiredString(row, "id");
|
|
2742
2763
|
const profileSectionCount = Number(this.db.get("SELECT COUNT(*) AS count FROM character_profile_sections WHERE character_id = ?", characterId)?.count ?? 0);
|
|
2743
2764
|
const markdownSections = includeProfileSections
|