diff --git a/packages/codemirror/autocomplete.mjs b/packages/codemirror/autocomplete.mjs
index 203ab8556..d3091d874 100644
--- a/packages/codemirror/autocomplete.mjs
+++ b/packages/codemirror/autocomplete.mjs
@@ -1,68 +1,91 @@
import jsdoc from '../../doc.json';
-// import { javascriptLanguage } from '@codemirror/lang-javascript';
import { autocompletion } from '@codemirror/autocomplete';
import { h } from './html';
-function plaintext(str) {
+const escapeHtml = (str) => {
const div = document.createElement('div');
div.innerText = str;
return div.innerHTML;
-}
+};
-const getDocLabel = (doc) => doc.name || doc.longname;
-const getInnerText = (html) => {
- var div = document.createElement('div');
+const stripHtml = (html) => {
+ const div = document.createElement('div');
div.innerHTML = html;
return div.textContent || div.innerText || '';
};
-export function Autocomplete({ doc, label }) {
- return h`
-
${label || getDocLabel(doc)}
-${doc.description}
-
- ${doc.params?.map(
- ({ name, type, description }) =>
- `- ${name} : ${type.names?.join(' | ')} ${description ? ` - ${getInnerText(description)}` : ''}
`,
- )}
-
-
- ${doc.examples?.map((example) => `
`)}
-
-
`[0];
- /*
- {
- console.log('ola!');
- navigator.clipboard.writeText(example);
- e.stopPropagation();
-}}
->
-{example}
-
-*/
-}
+const getDocLabel = (doc) => doc.name || doc.longname;
+
+const buildParamsList = (params) =>
+ params?.length
+ ? `
+
+ `
+ : '';
+
+const buildExamples = (examples) =>
+ examples?.length
+ ? `
+
+
Examples
+ ${examples
+ .map(
+ (example) => `
+
${escapeHtml(example)}
+ `,
+ )
+ .join('')}
+
+ `
+ : '';
+
+export const Autocomplete = ({ doc, label }) =>
+ h`
+
+`[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));
const jsdocCompletions = jsdoc.docs
- .filter(
- (doc) =>
- getDocLabel(doc) &&
- !getDocLabel(doc).startsWith('_') &&
- !['package'].includes(doc.kind) &&
- !['superdirtOnly', 'noAutocomplete'].some((tag) => doc.tags?.find((t) => t.originalTitle === tag)),
- )
- // https://codemirror.net/docs/ref/#autocomplete.Completion
- .map((doc) /*: Completion */ => ({
+ .filter((doc) => isValidDoc(doc) && !hasExcludedTags(doc))
+ // https://codemirror.net/docs/ref/#autocomplete.Completion
+ .map((doc) => ({
label: getDocLabel(doc),
// detail: 'xxx', // An optional short piece of information to show (with a different style) after the label.
info: () => Autocomplete({ doc }),
type: 'function', // https://codemirror.net/docs/ref/#autocomplete.Completion.type
}));
-export const strudelAutocomplete = (context /* : CompletionContext */) => {
- let word = context.matchBefore(/\w*/);
- if (word.from == word.to && !context.explicit) return null;
+export const strudelAutocomplete = (context) => {
+ const word = context.matchBefore(/\w*/);
+ if (word.from === word.to && !context.explicit) return null;
+
return {
from: word.from,
options: jsdocCompletions,
@@ -74,11 +97,5 @@ export const strudelAutocomplete = (context /* : CompletionContext */) => {
};
};
-export function isAutoCompletionEnabled(on) {
- return on
- ? [
- autocompletion({ override: [strudelAutocomplete] }),
- //javascriptLanguage.data.of({ autocomplete: strudelAutocomplete }),
- ]
- : []; // autocompletion({ override: [] })
-}
+export const isAutoCompletionEnabled = (enabled) =>
+ enabled ? [autocompletion({ override: [strudelAutocomplete] })] : [];
diff --git a/website/src/repl/Repl.css b/website/src/repl/Repl.css
index 3e13ff5a2..62e7dcf24 100644
--- a/website/src/repl/Repl.css
+++ b/website/src/repl/Repl.css
@@ -69,3 +69,134 @@
text-decoration: underline 0.18rem;
text-underline-offset: 0.22rem;
}
+
+/* Override default styles from the codemirror inline css for autocomplete info tooltip*/
+.cm-tooltip.cm-completionInfo {
+ padding: 12px !important;
+ padding-bottom: 12px !important;
+ border: 1px solid var(--foreground) !important;
+ border-radius: 4px !important;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3) !important;
+ max-width: 500px !important;
+ min-width: 300px !important;
+ max-height: 400px !important;
+ white-space: normal !important;
+ overflow: auto !important;
+ background-color: var(--lineHighlight) !important;
+}
+
+/* Main tooltip container */
+.autocomplete-info-tooltip {
+ border-radius: 4px !important;
+ color: var(--foreground);
+ font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
+ font-size: var(--font-size, 13px);
+ line-height: 1.4;
+ max-width: 600px;
+ max-height: 400px;
+ min-width: 400px;
+}
+
+.autocomplete-info-function-name {
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--foreground);
+ margin: 0 0 8px 0;
+}
+
+.autocomplete-info-function-description {
+ margin: 0 0 12px 0;
+ color: var(--foreground);
+ line-height: 1.5;
+ opacity: 0.8;
+}
+
+.autocomplete-info-section-title {
+ font-size: 12px;
+ font-weight: 600;
+ color: var(--foreground);
+ margin: 16px 0 6px 0;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.autocomplete-info-section-title:first-child {
+ margin-top: 0;
+}
+
+.autocomplete-info-params-section {
+ margin-top: 12px;
+}
+
+.autocomplete-info-params-list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.autocomplete-info-param-item {
+ margin-bottom: 8px;
+ padding: 8px;
+ background-color: var(--lineBackground);
+ border-radius: 3px;
+ border-left: 2px solid var(--foreground, #555);
+}
+
+.autocomplete-info-param-item:last-child {
+ margin-bottom: 0;
+}
+
+.autocomplete-info-param-name {
+ font-weight: 600;
+ color: var(--variable, var(--foreground));
+ margin-right: 8px;
+}
+
+.autocomplete-info-param-type {
+ color: var(--comment);
+ font-size: 12px;
+ background-color: var(--gutterForeground);
+ padding: 1px 4px;
+ border-radius: 2px;
+}
+
+.autocomplete-info-param-desc {
+ color: var(--foreground);
+ font-size: 10px;
+ margin-top: 4px;
+ line-height: 1.4;
+ opacity: 0.7;
+}
+
+.autocomplete-info-examples-section {
+ margin-top: 12px;
+}
+
+.autocomplete-info-example-code {
+ background: var(--lineBackground);
+ color: var(--foreground);
+ padding: 8px;
+ border-radius: 3px;
+ font-family: var(--font-family, 'SF Mono', 'Monaco', monospace);
+ font-size: 12px;
+ line-height: 1.5;
+ margin: 4px 0;
+ overflow-x: auto;
+ white-space: pre;
+ border: 1px solid var(--foreground, #3a3a3a);
+}
+
+.autocomplete-info-tooltip::-webkit-scrollbar {
+ width: 4px;
+}
+
+.autocomplete-info-tooltip::-webkit-scrollbar-track {
+}
+
+.autocomplete-info-tooltip::-webkit-scrollbar-thumb {
+ border-radius: 2px;
+}
+
+.autocomplete-info-tooltip::-webkit-scrollbar-thumb:hover {
+
+}