Split everything up into dynamically loaded modules.
This commit is contained in:
+188
-88
@@ -1,93 +1,193 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<!-- meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'blob'; style-src 'self' 'unsafe-inline'" -->
|
||||
<title>ai-fiction Book Runtime (Modular Version)</title>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<p id="versions">We are using Node.js <span id="node-version"></span>,
|
||||
Chromium <span id="chrome-version"></span>,
|
||||
and Electron <span id="electron-version"></span>.</p>
|
||||
<div id="book">
|
||||
<div id="page_left">
|
||||
<div class="header">
|
||||
<h2 class="byline l10n-by">powered by Generative AI</h2>
|
||||
<h1 class="title">AI Interactive Fiction</h1>
|
||||
<h3 class="subtitle">An open-world text adventure</h3>
|
||||
<div class="separator"><double>❦</double></div>
|
||||
</div>
|
||||
<div id="controls" class="buttons">
|
||||
<a class="l10n-speech" id="speech" title="Toggle text to speech" disabled="disabled">speech</a>
|
||||
<span><a id="speed_reset"><span class="l10n-speed">speed<sup>*</sup></span></a><input type="range" min="0" max="100" value="50" id="speed" name="speed" /></span>
|
||||
<a class="l10n-restart" id="rewind" title="Restart story from beginning" disabled="disabled">restart</a>
|
||||
<a class="l10n-save" id="save" title="Save progress">save</a>
|
||||
<a class="l10n-load" id="reload" title="Reload from save point" disabled="disabled">load</a>
|
||||
</div>
|
||||
<div id="choices" class="container">
|
||||
<div id="command_history">
|
||||
<!-- Previous commands and responses will be displayed here -->
|
||||
</div>
|
||||
|
||||
<div id="command_input">
|
||||
<div class="input-wrapper">
|
||||
<textarea id="player_input" placeholder="Enter your command..." rows="1" autofocus></textarea>
|
||||
<span id="cursor"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="l10n-remark" id="remark"><i><sup>*</sup>click on page or press spacebar to fast forward text animation</i></div>
|
||||
</div>
|
||||
<div id="page_right">
|
||||
<div id="story" class="container">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ruler"></div>
|
||||
<div class="l10n-prompt" id="indent">What do you want to do next?</div>
|
||||
<div id="lighting" />
|
||||
|
||||
<!-- Socket.io library for client-server communication -->
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
|
||||
<!-- Core libraries -->
|
||||
<script src="js/smartypants.js"></script>
|
||||
<script src="js/linked-list.js"></script>
|
||||
<script src="js/linebreak.js"></script>
|
||||
<script src="js/knuth-and-plass.js"></script>
|
||||
<script src="js/Hyphenopoly_Loader.js"></script>
|
||||
|
||||
<script>
|
||||
var locale = "en";
|
||||
// Create global variables needed by the modules
|
||||
window.rstack = [];
|
||||
</script>
|
||||
|
||||
<!-- Kokoro TTS library - load as module -->
|
||||
<script type="module">
|
||||
try {
|
||||
// Import KokoroTTS class from the module
|
||||
const kokoroModule = await import('./js/kokoro-js.js');
|
||||
|
||||
// Expose the KokoroTTS class globally
|
||||
window.KokoroTTS = kokoroModule.KokoroTTS;
|
||||
console.log('KokoroTTS class loaded and exposed to window');
|
||||
|
||||
// Dispatch an event to signal that the class is ready
|
||||
const event = new CustomEvent('kokoro-class-loaded');
|
||||
window.dispatchEvent(event);
|
||||
} catch (error) {
|
||||
console.error('Failed to load KokoroTTS module:', error);
|
||||
// Dispatch an event even on failure so handlers don't wait forever
|
||||
const event = new CustomEvent('kokoro-class-load-failed');
|
||||
window.dispatchEvent(event);
|
||||
<title>AI Interactive Fiction</title>
|
||||
<link rel="preload" href="/fonts/EBGaramond12-Regular.otf" as="font" type="font/otf" crossorigin>
|
||||
<link rel="preload" href="/fonts/EBGaramond12-Italic.otf" as="font" type="font/otf" crossorigin>
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon">
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'EB Garamond';
|
||||
src: url('/fonts/EBGaramond12-Regular.otf') format('opentype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'EB Garamond';
|
||||
src: url('/fonts/EBGaramond12-Italic.otf') format('opentype');
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-display: swap;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #000;
|
||||
}
|
||||
.loading-overlay {
|
||||
font-family: 'EB Garamond', serif;
|
||||
color: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
transition: opacity 0.5s ease-out;
|
||||
}
|
||||
.loading-content {
|
||||
width: 80%;
|
||||
max-width: 500px;
|
||||
text-align: center;
|
||||
}
|
||||
.loading-bar {
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
background: #333;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.loading-progress {
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
background: #4CAF50;
|
||||
transition: width 0.3s ease-in-out;
|
||||
}
|
||||
.loading-text {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
}
|
||||
#modules-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
max-height: 300px; /* Increased height */
|
||||
overflow: hidden; /* Hide scrollbar */
|
||||
width: 100%;
|
||||
}
|
||||
.module-item {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
margin-bottom: 8px;
|
||||
color: #ccc;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.module-name {
|
||||
text-align: left;
|
||||
padding-right: 10px;
|
||||
grid-column: 1;
|
||||
}
|
||||
.module-status {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
grid-column: 2;
|
||||
min-width: 80px; /* Ensure status has minimum width */
|
||||
padding: 0 10px;
|
||||
}
|
||||
.module-status-detail {
|
||||
grid-column: 3;
|
||||
text-align: right;
|
||||
font-size: 11px;
|
||||
color: #aaa;
|
||||
font-style: italic;
|
||||
padding-left: 10px;
|
||||
}
|
||||
.status-pending {
|
||||
color: #ccc;
|
||||
}
|
||||
.status-loading {
|
||||
color: #FFC107;
|
||||
}
|
||||
.status-waiting {
|
||||
color: #FF9800;
|
||||
}
|
||||
.status-initializing {
|
||||
color: #2196F3;
|
||||
}
|
||||
.status-finished {
|
||||
color: #4CAF50;
|
||||
}
|
||||
.status-error {
|
||||
color: #F44336;
|
||||
}
|
||||
|
||||
/* Update loader module list scrolling */
|
||||
.loading-overlay #modules-list {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto; /* Enable vertical scrolling */
|
||||
width: 100%;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #555 #333;
|
||||
}
|
||||
|
||||
.loading-overlay #modules-list::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.loading-overlay #modules-list::-webkit-scrollbar-track {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.loading-overlay #modules-list::-webkit-scrollbar-thumb {
|
||||
background-color: #555;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Debug output area -->
|
||||
<div id="debug-output" style="position:fixed; bottom:10px; left:10px; background:rgba(0,0,0,0.7); color:white; padding:10px; border-radius:5px; font-family:monospace; max-width:80%; max-height:200px; overflow:auto; z-index:10000; display:none;">
|
||||
<div id="debug-content"></div>
|
||||
</div>
|
||||
<script>
|
||||
// Set up error tracking
|
||||
window.addEventListener('error', function(event) {
|
||||
const debugOutput = document.getElementById('debug-output');
|
||||
const debugContent = document.getElementById('debug-content');
|
||||
if (debugOutput && debugContent) {
|
||||
debugOutput.style.display = 'block';
|
||||
const errorMsg = document.createElement('div');
|
||||
errorMsg.style.color = '#ff6b6b';
|
||||
errorMsg.textContent = `ERROR: ${event.message} at ${event.filename}:${event.lineno}`;
|
||||
debugContent.appendChild(errorMsg);
|
||||
}
|
||||
console.error(event);
|
||||
});
|
||||
|
||||
// Debug logger
|
||||
window.debugLog = function(message) {
|
||||
const debugOutput = document.getElementById('debug-output');
|
||||
const debugContent = document.getElementById('debug-content');
|
||||
if (debugOutput && debugContent) {
|
||||
debugOutput.style.display = 'block';
|
||||
const logMsg = document.createElement('div');
|
||||
logMsg.textContent = message;
|
||||
debugContent.appendChild(logMsg);
|
||||
}
|
||||
console.log(message);
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Main application script - imports all needed modules -->
|
||||
<script type="module" src="js/ai-fiction.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<script type="module" src="/js/loader.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user