refactor: publish feature APIs through TTVC
This commit is contained in:
parent
e2e20fa89f
commit
ed3b2d42cd
@ -8,6 +8,8 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- **Namespace migration surface.** Extracted Rehearser and Audiobook modules now publish parse, stage, voice-picker,
|
||||||
|
and persistence APIs through `window.TTVC` while retaining legacy globals for the ongoing migration.
|
||||||
- **CI frontend gate.** The manifest-driven JavaScript syntax and top-level declaration collision check now runs in the
|
- **CI frontend gate.** The manifest-driven JavaScript syntax and top-level declaration collision check now runs in the
|
||||||
SonarQube quality workflow, alongside Python compilation, regressions, and the production bundle build.
|
SonarQube quality workflow, alongside Python compilation, regressions, and the production bundle build.
|
||||||
- **Structured request correlation.** API and MCP requests now receive a bounded `X-Request-ID` and emit sanitized
|
- **Structured request correlation.** API and MCP requests now receive a bounded `X-Request-ID` and emit sanitized
|
||||||
|
|||||||
1
TODO.md
1
TODO.md
@ -93,6 +93,7 @@ architecture change: the larger Audiobook/Rehearser/style split.
|
|||||||
duration logs; route-specific logs retain provider/job context without request bodies.
|
duration logs; route-specific logs retain provider/job context without request bodies.
|
||||||
- [x] **L — Add linting and duplicate-function checks.** The manifest-driven frontend syntax/declaration gate now runs
|
- [x] **L — Add linting and duplicate-function checks.** The manifest-driven frontend syntax/declaration gate now runs
|
||||||
locally and in the SonarQube quality workflow alongside the existing Python and bundle checks.
|
locally and in the SonarQube quality workflow alongside the existing Python and bundle checks.
|
||||||
|
- [x] Expose extracted Rehearser and Audiobook parser APIs through the `window.TTVC` namespace bridge.
|
||||||
|
|
||||||
### P2 — after behavior and safety stabilize
|
### P2 — after behavior and safety stabilize
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
<meta name="color-scheme" content="light dark">
|
<meta name="color-scheme" content="light dark">
|
||||||
<meta name="theme-color" content="#2563EB">
|
<meta name="theme-color" content="#2563EB">
|
||||||
<meta name="app-version" content="1.24.29">
|
<meta name="app-version" content="1.24.30">
|
||||||
<link rel="manifest" href="/manifest.webmanifest">
|
<link rel="manifest" href="/manifest.webmanifest">
|
||||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||||
<link rel="apple-touch-icon" href="/static/icon.svg">
|
<link rel="apple-touch-icon" href="/static/icon.svg">
|
||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||||
<link rel="stylesheet" href="/static/style.css?v=1.24.29">
|
<link rel="stylesheet" href="/static/style.css?v=1.24.30">
|
||||||
|
|
||||||
|
|
||||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||||
@ -392,7 +392,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||||
<script src="/static/loader.js?v=1.24.29"></script>
|
<script src="/static/loader.js?v=1.24.30"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -23,3 +23,7 @@ const AB_PERSON_NOUNS = new Set(['Mann','Frau','Junge','Mädchen','Alte','Alter'
|
|||||||
'Bauer','Priester','Priesterin','Nachbar','Nachbarin','Sklave','Sklavin','Verweser','Inquisitor','General','König','Königin',
|
'Bauer','Priester','Priesterin','Nachbar','Nachbarin','Sklave','Sklavin','Verweser','Inquisitor','General','König','Königin',
|
||||||
'Prinz','Prinzessin','Fürst','Fürstin','Baron','Baronin','Bote','Diener','Dienerin','Knabe','Kind','Reiter','Reiterin',
|
'Prinz','Prinzessin','Fürst','Fürstin','Baron','Baronin','Bote','Diener','Dienerin','Knabe','Kind','Reiter','Reiterin',
|
||||||
'Bogenschütze','Schmied','Schmiedin','Heiler','Heilerin','Gelehrte','Gelehrter','Kapitän','Anführer','Anführerin']);
|
'Bogenschütze','Schmied','Schmiedin','Heiler','Heilerin','Gelehrte','Gelehrter','Kapitän','Anführer','Anführerin']);
|
||||||
|
|
||||||
|
window.TTVC = window.TTVC || {};
|
||||||
|
window.TTVC.audiobook = window.TTVC.audiobook || {};
|
||||||
|
window.TTVC.audiobook.parse = { audiobookHasDialogue, audiobookDehyphenate };
|
||||||
|
|||||||
@ -57,3 +57,6 @@ function _rehIdbGetAll() {
|
|||||||
} catch (e) { console.warn('[rehearser] migration skipped:', e); }
|
} catch (e) { console.warn('[rehearser] migration skipped:', e); }
|
||||||
})();
|
})();
|
||||||
window.rehDbGetById = rehDbGetById;
|
window.rehDbGetById = rehDbGetById;
|
||||||
|
window.TTVC = window.TTVC || {};
|
||||||
|
window.TTVC.rehearser = window.TTVC.rehearser || {};
|
||||||
|
window.TTVC.rehearser.library = { rehDbGetAll, rehDbGetById, rehDbPut, rehDbDelete };
|
||||||
|
|||||||
@ -192,3 +192,6 @@ function detectCharacters(lines) {
|
|||||||
return cast;
|
return cast;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.TTVC = window.TTVC || {};
|
||||||
|
window.TTVC.rehearser = window.TTVC.rehearser || {};
|
||||||
|
window.TTVC.rehearser.parse = { parseScript, detectCharacters };
|
||||||
|
|||||||
@ -99,3 +99,7 @@ function renderCastStrip() {
|
|||||||
$('reh-font-inc')?.addEventListener('click', () => rehStageFontStep(0.1));
|
$('reh-font-inc')?.addEventListener('click', () => rehStageFontStep(0.1));
|
||||||
$('reh-font-dec')?.addEventListener('click', () => rehStageFontStep(-0.1));
|
$('reh-font-dec')?.addEventListener('click', () => rehStageFontStep(-0.1));
|
||||||
$('reh-cast-toggle')?.addEventListener('click', rehToggleCast);
|
$('reh-cast-toggle')?.addEventListener('click', rehToggleCast);
|
||||||
|
|
||||||
|
window.TTVC = window.TTVC || {};
|
||||||
|
window.TTVC.rehearser = window.TTVC.rehearser || {};
|
||||||
|
window.TTVC.rehearser.stage = { renderCastStrip, rehApplyStageFont, rehApplyCastCollapsed };
|
||||||
|
|||||||
@ -71,3 +71,7 @@ function castOnlinePanelHtml(sp, c) {
|
|||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.TTVC = window.TTVC || {};
|
||||||
|
window.TTVC.rehearser = window.TTVC.rehearser || {};
|
||||||
|
window.TTVC.rehearser.voicePicker = { castOnlinePanelHtml, preview: _rehAudition, stopPreview: _rehStopAudition };
|
||||||
|
|||||||
@ -31,6 +31,11 @@ test('parses a screenplay and builds the cast', async ({ page }) => {
|
|||||||
await page.waitForSelector('#app-skeleton', { state: 'detached', timeout: 15_000 });
|
await page.waitForSelector('#app-skeleton', { state: 'detached', timeout: 15_000 });
|
||||||
await navTo(page, 's-rehearser');
|
await navTo(page, 's-rehearser');
|
||||||
await page.waitForFunction(() => typeof window.navRehearserPhase === 'function', null, { timeout: 15_000 });
|
await page.waitForFunction(() => typeof window.navRehearserPhase === 'function', null, { timeout: 15_000 });
|
||||||
|
await expect.poll(() => page.evaluate(() => Boolean(
|
||||||
|
window.TTVC?.rehearser?.parse?.parseScript &&
|
||||||
|
window.TTVC?.rehearser?.stage?.renderCastStrip &&
|
||||||
|
window.TTVC?.rehearser?.voicePicker?.castOnlinePanelHtml
|
||||||
|
))).toBe(true);
|
||||||
await page.evaluate(() => window.navRehearserPhase(1));
|
await page.evaluate(() => window.navRehearserPhase(1));
|
||||||
|
|
||||||
// Go to the Cast tab area: paste a script and parse
|
// Go to the Cast tab area: paste a script and parse
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user