# Module Conventions Ped-AI currently uses mixed JavaScript module styles. This is intentional during incremental modernization. ## Current Convention | Area | Module Style | Notes | |---|---|---| | Backend `server.js`, `src/**` | CommonJS | Use `require` and `module.exports` for now | | New frontend modules | ESM | Use `import` and `export` | | Older frontend files | Classic browser globals | Convert only when touching the feature intentionally | | Dual browser/test files | Case-by-case | Keep classic style only when tests or browser globals require it | Do not add root-level `"type": "module"` without a full backend migration plan. It would change how every `.js` file is interpreted by Node. ## CommonJS Example ```js var express = require('express'); var router = express.Router(); module.exports = router; ``` ## ESM Example ```js import { escapeHtml } from './assistant/citations.js'; export function renderSourcesList(sources) { return ''; } ``` ## Frontend Modernization Path 1. New frontend code should be ESM where possible. 2. Existing globals can remain until that feature is refactored. 3. Keep browser script load order stable while refactoring. 4. Export pure helper functions so Node tests can import them. 5. Use `CustomEvent` or explicit imports instead of adding new global APIs when practical. ## Acceptable Globals Globals are acceptable when they are part of the current shell contract. Examples: - `window.activateTab`, - `window.getAuthHeaders`, - shared UI helpers still consumed by legacy feature files. Do not add new globals when an import or event would be clearer. ## Rendering And `innerHTML` `innerHTML` is allowed only when one of these is true: - the HTML is a static template controlled by the app, - all dynamic values are escaped before insertion, - the HTML has passed through the approved sanitizer, - the content is a trusted app component fetched from `public/components/`. Prefer `textContent` for plain text. Unsafe: ```js el.innerHTML = userText; el.innerHTML = modelOutput; ``` Safer: ```js el.textContent = userText; el.innerHTML = escapeHtml(userText).replace(/\n/g, '
'); el.innerHTML = sanitizeHtml(renderMarkdown(modelOutput)); ``` ## Test Expectations When converting a frontend file to ESM, add or update tests for: - exported helper functions, - expected globals still present if legacy code needs them, - no browser-native `prompt`, `alert`, or `confirm`, - no unescaped dynamic text inserted through `innerHTML`.