1// The reference tab's functions (repl/components/panel/Reference.jsx), out 2// of jsdoc's doc.json, as data both it and the MCP's api_reference read: 3// the tab renders `referenceFunctions`, and pages/jev/reference.json.js 4// writes `referenceData` for the Worker (worker/src/reference.ts). 5 6// What the tab lists: named, not internal, described, and not only for an 7// engine other than superdough. 8const isValid = ({ name, description, tags = [] }) => { 9 const isSupradoughOnly = tags.includes('supradough') && !tags.includes('superdough'); 10 const isSuperdirtOnly = tags.includes('superdirt') && !tags.includes('superdough'); 11 return name && !name.startsWith('_') && !!description && !isSupradoughOnly && !isSuperdirtOnly; 12}; 13 14// Each function once, under its first name; a synonym another function 15// already took is dropped. `tags` only jsdoc's `@tags` strings ('untagged' 16// when none), `synonyms` the names left, `allNames` all of them. 17export function referenceFunctions(docs) { 18 const seen = new Set(); 19 const functions = []; 20 for (const doc of docs) { 21 if (!isValid(doc) || seen.has(doc.name)) continue; 22 const tags = doc.tags?.filter((t) => t && typeof t === 'string') || ['untagged']; 23 const names = [doc.name]; 24 seen.add(doc.name); 25 for (const s of doc.synonyms || []) { 26 if (!s || seen.has(s)) continue; 27 names.push(s); 28 seen.add(s); 29 } 30 functions.push({ ...doc, tags, allNames: names.join(' '), synonyms: names.slice(1) }); 31 } 32 return functions.sort((a, b) => a.name.localeCompare(b.name)); 33} 34 35const ENTITIES = { amp: '&', lt: '<', gt: '>', quot: '"', '#39': "'", apos: "'", nbsp: ' ' }; 36 37// jsdoc's HTML as plain text: paragraphs as blank lines, list items as 38// '- ' lines, no tags. 39export function htmlText(html) { 40 return String(html ?? '') 41 .replace(/<\/p>\s*<p>/g, '\n\n') 42 .replace(/<br\s*\/?>/g, '\n') 43 .replace(/<li>\s*/g, '- ') 44 .replace(/<[^>]*>/g, '') 45 .replace(/&(amp|lt|gt|quot|#39|apos|nbsp);/g, (_, e) => ENTITIES[e]) 46 .replace(/[ \t]+/g, ' ') 47 .replace(/\n{3,}/g, '\n\n') 48 .trim(); 49} 50 51// What api_reference serves: every function the tab lists, as text. 52export function referenceData(docs) { 53 return referenceFunctions(docs).map((f) => ({ 54 name: f.name, 55 synonyms: f.synonyms, 56 tags: f.tags.filter((t) => !['supradough', 'superdirt'].includes(t)), 57 description: htmlText(f.description), 58 params: (f.params ?? []).map((p) => ({ 59 name: String(p.name ?? ''), 60 type: (p.type?.names ?? []).join(' | '), 61 description: htmlText(p.description), 62 })), 63 examples: (f.examples ?? []).filter((e) => typeof e === 'string'), 64 })); 65}