import { LRLanguage, LanguageSupport, HighlightStyle, syntaxHighlighting, foldNodeProp, indentNodeProp } from '@codemirror/language'; import { styleTags, tags as t } from '@lezer/highlight'; import { parser } from './decodal-parser.js'; const parserWithMetadata = parser.configure({ props: [ styleTags({ 'Let In Match Import Default': t.keyword, 'True False': t.bool, Identifier: t.variableName, String: t.string, Regex: t.regexp, 'Integer Float': t.number, Comment: t.lineComment, 'Plus Minus Star Slash PlusPlus Equal EqualEqual Bang BangEqual Amp AmpAmp PipePipe SlashSlash Gt Gte Lt Lte Arrow': t.operator, 'LBrace RBrace': t.brace, 'LBracket RBracket': t.squareBracket, 'LParen RParen': t.paren, 'Semicolon Comma Dot Colon': t.punctuation, }), indentNodeProp.add({ Object: context => context.column(context.node.from) + context.unit, Array: context => context.column(context.node.from) + context.unit, MatchExpression: context => context.column(context.node.from) + context.unit, LetExpression: context => context.column(context.node.from) + context.unit, }), foldNodeProp.add({ Object: foldDelimited('{', '}'), Array: foldDelimited('[', ']'), MatchExpression: foldDelimited('{', '}'), }), ], }); function foldDelimited(open, close) { return (node, state) => { const text = state.doc.sliceString(node.from, node.to); const openIndex = text.indexOf(open); const closeIndex = text.lastIndexOf(close); if (openIndex < 0 || closeIndex <= openIndex) return null; const from = node.from + openIndex + open.length; const to = node.from + closeIndex; return from < to ? { from, to } : null; }; } export const decodalLanguage = LRLanguage.define({ parser: parserWithMetadata, languageData: { commentTokens: { line: '#' }, closeBrackets: { brackets: ['(', '[', '{', '"'] }, }, }); export const decodalHighlightStyle = HighlightStyle.define([ { tag: t.keyword, color: '#93c5fd', fontWeight: '700' }, { tag: t.variableName, color: 'inherit' }, { tag: t.bool, color: '#fbbf24' }, { tag: t.number, color: '#fbbf24' }, { tag: t.string, color: '#86efac' }, { tag: t.regexp, color: '#86efac' }, { tag: t.lineComment, color: '#94a3b8', fontStyle: 'italic' }, { tag: t.operator, color: '#f9a8d4' }, { tag: [t.brace, t.squareBracket, t.paren, t.punctuation], color: '#f9a8d4' }, ]); export function decodal() { return new LanguageSupport(decodalLanguage, [syntaxHighlighting(decodalHighlightStyle)]); }