import { memo, useEffect, useMemo, useState, Fragment } from 'react'; import jsdocJson from '../../../../../doc.json'; import { Textbox } from '@src/repl/components/panel/SettingsTab'; import { settingsMap, useSettings } from '@src/settings.mjs'; const isValid = ({ name, description, tags = [] }) => { const isSupradoughOnly = tags.includes('supradough') && !tags.includes('superdough'); const isSuperdirtOnly = tags.includes('superdirt') && !tags.includes('superdough'); return name && !name.startsWith('_') && !!description && !isSupradoughOnly && !isSuperdirtOnly; }; const availableFunctions = (() => { const seen = new Set(); // avoid repetition const functions = []; for (const doc of jsdocJson.docs) { if (!isValid(doc)) continue; if (seen.has(doc.name)) continue; // jsdoc also uses "tags" for when you use @something in the comments and it doesn't know what // @something is. We only want data from comments like `@tags superdough` here. // If nothing is specified, we default to "untagged" for debugging doc.tags = doc.tags?.filter((t) => t && typeof t === 'string') || ['untagged']; const synonyms = doc.synonyms || []; let names = [doc.name]; seen.add(doc.name); for (const s of synonyms) { if (!s || seen.has(s)) continue; names.push(s); seen.add(s); } doc.allNames = names.join(' '); doc.synonyms = names.slice(1); functions.push(doc); } return functions.sort((a, b) => /* a.meta.filename.localeCompare(b.meta.filename) + */ a.name.localeCompare(b.name)); })(); const tagCounts = {}; const ignoredTags = ['supradough', 'superdirt']; // const tagOptions = { all: `all (${availableFunctions.length})` }; const tagOptions = { all: `all` }; for (const doc of availableFunctions) { (doc.tags || ['untagged']).forEach((t) => { if (typeof t === 'string' && t && !ignoredTags.includes(t)) { tagCounts[t] = (tagCounts[t] || 0) + 1; //tagOptions[t] = `${t} (${tagCounts[t]})`; tagOptions[t] = t; } }); } const getInnerText = (html) => { var div = document.createElement('div'); div.innerHTML = html; return div.textContent || div.innerText || ''; }; export const Reference = memo(function Reference() { const [search, setSearch] = useState(''); const [selectedFunction, setSelectedFunction] = useState(null); const { referenceTag } = useSettings(); const toggleTag = (tag) => { if (referenceTag === tag) { setReferenceTag('all'); } else { setReferenceTag(tag); } }; const searchVisibleFunctions = useMemo(() => { return availableFunctions.filter((entry) => { if (referenceTag && referenceTag !== 'all') { if (!(entry.tags || ['untagged']).includes(referenceTag)) { return false; } } if (!search) { return true; } const lowerCaseSearch = search.toLowerCase(); return ( (entry.allNames || entry.name).toLowerCase().includes(lowerCaseSearch) || (entry.synonyms?.some((s) => s.toLowerCase().includes(lowerCaseSearch)) ?? false) ); }); }, [search, referenceTag]); const detailVisibleFunctions = useMemo(() => { return searchVisibleFunctions.filter((x) => { if (referenceTag === null || referenceTag === 'all') { if (search) { return true; } return x.name === selectedFunction; } else { return true; } }); }, [searchVisibleFunctions, selectedFunction, referenceTag]); const onSearchTagFilterClick = () => { setReferenceTag('all'); setSelectedFunction(null); }; useEffect(() => { if (selectedFunction) { const el = document.getElementById(`doc-${selectedFunction}`); const container = document.getElementById('reference-container'); container.scrollTo(0, el.offsetTop); } }, [selectedFunction]); let setReferenceTag = (value) => settingsMap.setKey('referenceTag', value); return (
This is the long list of functions you can use. Remember that you don't need to remember all of those and that you can already make music with a small set of functions!
Synonyms: {entry.synonyms_text}
{example}
))}
Search or select a tag to get started.
} {detailVisibleFunctions.length > 0 && }