import jsdoc from '../../doc.json'; import { autocompletion } from '@codemirror/autocomplete'; import { h } from './html'; const escapeHtml = (str) => { const div = document.createElement('div'); div.innerText = str; return div.innerHTML; }; const stripHtml = (html) => { const div = document.createElement('div'); div.innerHTML = html; return div.textContent || div.innerText || ''; }; const getDocLabel = (doc) => doc.name || doc.longname; const buildParamsList = (params) => params?.length ? `

Parameters

` : ''; const buildExamples = (examples) => examples?.length ? `

Examples

${examples .map( (example) => `
${escapeHtml(example)}
`, ) .join('')}
` : ''; export const Autocomplete = (doc) => h`

${getDocLabel(doc)}

${doc.synonyms_text ? `
Synonyms: ${doc.synonyms_text}
` : ''} ${doc.description ? `
${doc.description}
` : ''} ${buildParamsList(doc.params)} ${buildExamples(doc.examples)}
`[0]; const isValidDoc = (doc) => { const label = getDocLabel(doc); return label && !label.startsWith('_') && !['package'].includes(doc.kind); }; const hasExcludedTags = (doc) => ['superdirtOnly', 'noAutocomplete'].some((tag) => doc.tags?.find((t) => t.originalTitle === tag)); export const getSynonymDoc = (doc, synonym) => { const synonyms = doc.synonyms || []; const docLabel = getDocLabel(doc); // Swap `doc.name` in for `s` in the list of synonyms const synonymsWithDoc = [docLabel, ...synonyms].filter((x) => x && x !== synonym); return { ...doc, name: synonym, longname: synonym, synonyms: synonymsWithDoc, synonyms_text: synonymsWithDoc.join(', '), }; }; const jsdocCompletions = (() => { const seen = new Set(); // avoid repetition const completions = []; for (const doc of jsdoc.docs) { if (!isValidDoc(doc) || hasExcludedTags(doc)) continue; const docLabel = getDocLabel(doc); // Remove duplicates const synonyms = doc.synonyms || []; let labels = [docLabel, ...synonyms]; for (const label of labels) { // https://codemirror.net/docs/ref/#autocomplete.Completion if (label && !seen.has(label)) { seen.add(label); completions.push({ label, info: () => Autocomplete(getSynonymDoc(doc, label)), type: 'function', // https://codemirror.net/docs/ref/#autocomplete.Completion.type }); } } } return completions; })(); export const strudelAutocomplete = (context) => { const word = context.matchBefore(/\w*/); if (word.from === word.to && !context.explicit) return null; return { from: word.from, options: jsdocCompletions, /* options: [ { label: 'match', type: 'keyword' }, { label: 'hello', type: 'variable', info: '(World)' }, { label: 'magic', type: 'text', apply: '⠁⭒*.✩.*⭒⠁', detail: 'macro' }, ], */ }; }; export const isAutoCompletionEnabled = (enabled) => enabled ? [autocompletion({ override: [strudelAutocomplete], closeOnBlur: false })] : [];