Show source evidence in character sheets

This commit is contained in:
mARTin-B78 2026-07-09 20:36:17 +02:00
parent ab58ef2e43
commit f6e5449eb6
6 changed files with 1803 additions and 18 deletions

View File

@ -9,6 +9,16 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
---
## [1.14.24] — 2026-07-09
### Fixed
- **Character sheet sources are visible again and appear before the prompt boxes** — the evidence section now renders any source metadata we have, instead of hiding everything that lacks a long quote.
## [1.14.23] — 2026-07-09
### Changed
- **The character-sheet header is less cluttered** — aliases now live in the identity block instead of being duplicated as header chips.
## [1.14.22] — 2026-07-09
### Fixed
@ -1662,7 +1672,9 @@ Initial feature-complete release.
---
[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.22...HEAD
[Unreleased]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.24...HEAD
[1.14.24]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.23...v1.14.24
[1.14.23]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.22...v1.14.23
[1.14.22]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.21...v1.14.22
[1.14.21]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.20...v1.14.21
[1.14.20]: https://github.com/mARTin-B78/tts-voice-creator-clone-and-design-2/compare/v1.14.19...v1.14.20

View File

@ -1 +1 @@
1.14.22
1.14.24

1737
static/dist/main.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@
<meta name="format-detection" content="telephone=no">
<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#2563EB">
<meta name="app-version" content="1.14.22">
<meta name="app-version" content="1.14.24">
<link rel="manifest" href="/manifest.webmanifest">
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/static/icon.svg">
@ -27,7 +27,7 @@
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
<link rel="stylesheet" href="/static/style.css?v=1.14.22">
<link rel="stylesheet" href="/static/style.css?v=1.14.24">
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
@ -365,7 +365,7 @@ window.toggleNavTree = function(treeId, chevronId) {
</script>
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
<script src="/static/loader.js?v=1.14.22"></script>
<script src="/static/loader.js?v=1.14.24"></script>
</body>
</html>

View File

@ -1065,6 +1065,12 @@ function csField(label, value, sheet, field) {
return `<div class="cs-row"><dt>${label}</dt><dd>${escHtml(String(value))}${badge ? ` ${badge}` : ''}</dd></div>`;
}
function csIdentityCell(label, value, sheet, field) {
if (!value) return '';
const badge = sheet && field ? csSourceBadgeHtml(sheet, field) : '';
return `<div class="cs-id-cell"><dt>${label}</dt><dd>${escHtml(String(value))}${badge ? ` ${badge}` : ''}</dd></div>`;
}
function csPromptBox(label, value, sheetKey) {
const text = _csStr(value);
const has = !!text.trim();
@ -1103,7 +1109,6 @@ function csIdentityTagList(s) {
if (tags.some(t => t.key === key)) return;
tags.push({ label, text, key });
};
(String(s.aliases || '').split(',') || []).map(x => x.trim()).filter(Boolean).forEach(v => add('also known as', v));
if (s.full_name && String(s.full_name).trim() && String(s.full_name).trim() !== String(s.name || '').trim()) add('full name', s.full_name);
const firstLast = [s.first_name, s.last_name].filter(Boolean).join(' ').trim();
if (firstLast && firstLast !== String(s.full_name || '').trim() && firstLast !== String(s.name || '').trim()) add('first / last', firstLast);
@ -1114,23 +1119,23 @@ function csCardHtml(s) {
const inv = (s.inventory || []).filter(Boolean);
const fullName = String(s.full_name || '').trim();
const metaTags = csIdentityTagList(s);
const identityHtml = [
csField('Name', s.name || fullName, s, 'name'),
csField('Full Name', fullName && fullName.toLowerCase() !== String(s.name || '').toLowerCase() ? fullName : '', s, 'full_name'),
csField('First Name', s.first_name, s, 'first_name'),
csField('Last Name', s.last_name, s, 'last_name'),
csField('Also Known As', s.aliases, s, 'aliases'),
csField('Gender', s.gender, s, 'gender'),
csField('Title', s.title, s, 'title'),
csField('Occupation', s.profession, s, 'profession'),
].join('');
const identityHtml = `<div class="cs-identity-grid">
${csIdentityCell('Name', s.name || fullName, s, 'name')}
${csIdentityCell('First Name', s.first_name, s, 'first_name')}
${csIdentityCell('Last Name', s.last_name, s, 'last_name')}
${csIdentityCell('Full Name', fullName && fullName.toLowerCase() !== String(s.name || '').toLowerCase() ? fullName : '', s, 'full_name')}
${csIdentityCell('Gender', s.gender, s, 'gender')}
${csIdentityCell('Title', s.title, s, 'title')}
${csIdentityCell('Occupation', s.profession, s, 'profession')}
${csIdentityCell('Also Known As', s.aliases, s, 'aliases')}
</div>`;
const invHtml = inv.length
? `<div class="cs-row"><dt>Signature Items</dt><dd><ul>${inv.map(i => `<li>${escHtml(i)}</li>`).join('')}</ul></dd></div>`
: '';
const attrs = (s.attribute_high || s.attribute_low)
? `<div class="cs-row"><dt>Core Attributes</dt><dd>▲ ${escHtml(s.attribute_high || '—')} &nbsp;·&nbsp; ▼ ${escHtml(s.attribute_low || '—')}</dd></div>`
: '';
const sources = (s.sources || []).filter(x => x && (x.quote || x.page != null));
const sources = (s.sources || []).filter(x => x && (x.quote || x.page != null || x.line_hint));
const srcHtml = sources.length
? `<div class="cs-sources"><div class="cs-sources-title"><span class="mdi mdi-book-open-page-variant-outline"></span> Sources / Evidence</div><div class="cs-source-list">${
sources.map((x, i) =>
@ -1185,8 +1190,8 @@ function csCardHtml(s) {
${csField('Conflict Style', s.conflict_style, s, 'conflict_style')}
${csField('Win Condition', s.win_condition, s, 'win_condition')}
</dl>
${promptHtml}
${srcHtml}
${promptHtml}
</div>`;
}

View File

@ -6081,6 +6081,37 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami
}
.cs-progress-badge { font-size: 9px; text-transform: uppercase; color: var(--subtext); font-weight: 800; }
.cs-fields { margin: 0; display: grid; grid-template-columns: 1fr; gap: 6px; }
.cs-identity-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
gap: 6px;
margin-bottom: 4px;
}
.cs-id-cell {
display: flex;
flex-direction: column;
gap: 3px;
padding: 8px 10px;
font-size: 12px;
border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
border-radius: 8px;
background: color-mix(in srgb, var(--surface) 78%, transparent);
}
.cs-id-cell dt {
font-weight: 800;
color: var(--subtext);
text-transform: uppercase;
font-size: 9.5px;
letter-spacing: .04em;
display: flex;
align-items: center;
gap: 5px;
}
.cs-id-cell dd {
margin: 0;
color: var(--text);
line-height: 1.35;
}
.cs-row { display: grid; grid-template-columns: 136px 1fr; gap: 10px; font-size: 12.5px; padding: 6px 8px; border: 1px solid color-mix(in srgb, var(--border) 55%, transparent); border-radius: 6px; background: color-mix(in srgb, var(--surface) 72%, transparent); }
.cs-row dt { font-weight: 800; color: var(--subtext); text-transform: uppercase; font-size: 10px; letter-spacing: .04em; display:flex; align-items:center; gap:5px; }
.cs-row dd { margin: 0; color: var(--text); line-height: 1.45; }