Initial commit

This commit is contained in:
2026-05-25 13:00:20 -04:00
commit e14e43da42
49 changed files with 26892 additions and 0 deletions

172
js/loader.js Normal file
View File

@@ -0,0 +1,172 @@
/**
* On-demand page loader for Babel/JSX scripts.
*
* Instead of loading ALL pages as <script type="text/babel"> upfront
* (which forces Babel to parse ~580KB of JSX at once), this loader
* fetches individual page scripts only when the user navigates to them,
* then transforms with Babel and evaluates the result.
*
* Must be loaded as a plain <script> BEFORE any page scripts.
*/
(function() {
'use strict';
window.GDD = window.GDD || {};
var _cache = {}; // pageId -> true (loaded)
var _loading = {}; // pageId -> Promise
var _scriptCache = {}; // src -> transformed code
var PAGE_SCRIPTS = {
'overview': 'js/pages/overview.js',
'architecture': 'js/pages/architecture.js',
'techstack': 'js/pages/techstack.js',
'backend': 'js/pages/backend.js',
'agents': 'js/pages/agents.js',
'gameplay': 'js/pages/gameplay.js',
'ships': 'js/pages/ships.js',
'economy': 'js/pages/economy.js',
'social': 'js/pages/social.js',
'ship-ai': 'js/pages/ship-ai.js',
'roadmap': 'js/pages/roadmap.js',
'risks': 'js/pages/risks.js',
'demo-gallery': 'js/pages/demo-gallery.js',
'demo-starmap': 'js/demos/starmap.js',
'demo-movement': 'js/demos/movement.js',
'demo-combat': 'js/demos/combat.js',
'demo-market': 'js/demos/market.js',
'demo-fitting': 'js/demos/fitting.js',
'demo-refining': 'js/demos/refining.js',
'demo-progression':'js/demos/progression.js',
'demo-bounty': 'js/demos/bounty.js',
'demo-gamehud': 'js/demos/gamehud.js',
'demo-chat': 'js/demos/chat.js',
'demo-zora': 'js/demos/zora.js',
'demo-galaxy': 'js/demos/galaxy.js',
};
// Component name map — mirrors the one in app.js
var PAGE_COMP_NAMES = {
'overview': 'OverviewPage',
'architecture': 'ArchitecturePage',
'techstack': 'TechStackPage',
'backend': 'BackendPage',
'agents': 'AgentsPage',
'gameplay': 'GameplayPage',
'ships': 'ShipsPage',
'economy': 'EconomyPage',
'social': 'SocialPage',
'ship-ai': 'ShipAIPage',
'roadmap': 'RoadmapPage',
'risks': 'RisksPage',
'demo-gallery': 'DemoGalleryPage',
'demo-starmap': 'StarMapDemo',
'demo-movement': 'ShipMovementDemo',
'demo-combat': 'CombatDemo',
'demo-market': 'MarketDemo',
'demo-fitting': 'FittingDemo',
'demo-refining': 'RefiningDemo',
'demo-progression':'ProgressionDemo',
'demo-bounty': 'BountyDemo',
'demo-gamehud': 'GameHudDemo',
'demo-chat': 'ChatDemo',
'demo-zora': 'ZoraDemo',
'demo-galaxy': 'GalaxyDemo',
};
var _isFileProtocol = (window.location.protocol === 'file:');
function fetchAndTransform(src) {
// Check memory cache first
if (_scriptCache[src]) {
return Promise.resolve(_scriptCache[src]);
}
// On file:// protocol, fetch() is blocked by the browser.
// Try injecting a <script type="text/babel" src> tag instead —
// Babel standalone's MutationObserver will pick it up.
if (_isFileProtocol) {
return new Promise(function(resolve, reject) {
// Check if component appeared (Babel may have processed it
// from a previously injected tag)
var compName = PAGE_COMP_NAMES[Object.keys(PAGE_SCRIPTS).filter(
function(k) { return PAGE_SCRIPTS[k] === src; }
)[0]];
if (compName && window.GDD[compName]) {
resolve('');
return;
}
reject(new Error(
'Cannot load page from file:// protocol. ' +
'Serve this folder via HTTP for full navigation. ' +
'Run: python3 -m http.server 8000 (then open http://localhost:8000)'
));
});
}
return fetch(src)
.then(function(r) {
if (!r.ok) throw new Error('HTTP ' + r.status + ' loading ' + src);
return r.text();
})
.then(function(code) {
// Transform JSX → JS using Babel standalone
var transformed = Babel.transform(code, {
presets: ['react'],
plugins: [],
}).code;
_scriptCache[src] = transformed;
return transformed;
});
}
/**
* Load a page script on demand. Returns a Promise.
*/
window.GDD.loadPage = function loadPage(pageId) {
if (_cache[pageId]) return Promise.resolve();
if (_loading[pageId]) return _loading[pageId];
// Check if component was already registered by an inline <script type="text/babel">
var compName = PAGE_COMP_NAMES[pageId];
if (compName && window.GDD[compName]) {
_cache[pageId] = true;
return Promise.resolve();
}
var src = PAGE_SCRIPTS[pageId];
if (!src) return Promise.resolve();
var promise = fetchAndTransform(src)
.then(function(code) {
// Execute in global scope so window.GDD assignments work
(0, eval)(code);
_cache[pageId] = true;
delete _loading[pageId];
})
.catch(function(err) {
delete _loading[pageId];
console.error('[loader] Failed to load page:', pageId, err);
throw err;
});
_loading[pageId] = promise;
return promise;
};
/**
* Preload a page in the background (no-op if already loaded/loading).
*/
window.GDD.preloadPage = function preloadPage(pageId) {
if (_cache[pageId] || _loading[pageId]) return;
setTimeout(function() { window.GDD.loadPage(pageId); }, 200);
};
/**
* Check if a page is loaded and its component is available.
*/
window.GDD.isPageLoaded = function isPageLoaded(pageId) {
return !!_cache[pageId];
};
})();