In this gist we add Custom HTML and JSON autocomplete without overriding the original autocomplete.
Each language support in code mirror exports nameLanguage
(eg: htmlLanguage) to allow you to add custom autocomplete.
import React, { useMemo } from 'react'
import CodeMirror from '@uiw/react-codemirror'
import { json, jsonLanguage } from '@codemirror/lang-json'
import { html, htmlLanguage } from '@codemirror/lang-html'
import { syntaxTree } from '@codemirror/language'
const getExtension=(mode)=>{
switch (mode) {
case "json":
return [
json(),
jsonLanguage.data.of({
autocomplete: function myCompletions(context) {
const word = context.matchBefore(/\w*/);
if (word.from === word.to && !context.explicit) return null;
return {
from: word.from,
options: [
{
label: "some_key",
apply: '"some_key":"value",',
info: "key value pair auto complete",
},
{
label: "some_key",
apply: '"some_key":"value",',
info: "yet another key value pair auto complete",
},
],
};
},
}),
];
case "html":
return [
html(),
htmlLanguage.data.of({
autocomplete: function htmlCompletionSource(context) {
const { state, pos } = context;
let around = syntaxTree(state).resolveInner(pos),
tree = around.resolve(pos, -1);
for (
let scan = pos, before;
around === tree && (before = tree.childBefore(scan));
) {
const last = before.lastChild;
if (!last || !last.type.isError || last.from < last.to) break;
around = tree = before;
scan = last.from;
}
if (
tree.name === "TagName" &&
!(tree.parent && /CloseTag$/.test(tree.parent.name))
) {
return {
from:tree.from,
to:pos,
options: [
{
label:"audio",
info:"HTML audio tag",
}
],
span: /^\/?[:\-\.\w\u00b7-\uffff]*$/
};
}
else if (
(context.explicit &&
(tree.name === 'OpenTag' || tree.name === 'SelfClosingTag')) ||
tree.name === 'AttributeName'
) {
return {
from: tree.name === 'AttributeName' ? tree.from : pos,
to: pos,
options: [
{
label:"aria-label",
info:"HTML aria-label attribute",
}
],
span: /^[:\-\.\w\u00b7-\uffff]+$/
}
}
},
}),
];
}
}
const Editor = (props) => {
const { value,mode } = props
return (
<div className='editorContainer'>
<CodeMirror
mode={mode}
value={value}
extensions={getExtension(mode)}
/>
</div>
)
}
export default Editor