diff --git a/lib/codemirror/caddyfile-mode.ts b/lib/codemirror/caddyfile-mode.ts new file mode 100644 index 0000000..87de6b7 --- /dev/null +++ b/lib/codemirror/caddyfile-mode.ts @@ -0,0 +1,31 @@ +import { StreamLanguage, type StreamParser } from '@codemirror/language' + +const CADDY_DIRECTIVES = new Set([ + 'reverse_proxy', 'encode', 'file_server', 'handle', 'handle_errors', + 'root', 'header', 'redir', 'rewrite', 'respond', 'route', 'tls', + 'log', 'basicauth', 'request_body', 'try_files', 'php_fastcgi', + 'templates', 'import', 'bind', 'metrics', 'admin', 'auto_https', +]) +const CADDY_GLOBAL = new Set(['email', 'storage', 'order', 'servers', 'log']) + +const parser: StreamParser = { + token(stream) { + if (stream.eatSpace()) return null + if (stream.match(/^#.*/)) return 'comment' + if (stream.match(/^"(?:[^"\\]|\\.)*"/)) return 'string' + if (stream.match(/^@[A-Za-z_][\w-]*/)) return 'variableName' + if (stream.match(/^[{}]/)) return 'brace' + const word = stream.match(/^[A-Za-z_][\w.-]*/) as RegExpMatchArray | null + if (word) { + const w = word[0] + if (CADDY_DIRECTIVES.has(w)) return 'keyword' + if (CADDY_GLOBAL.has(w)) return 'typeName' + return 'variableName' + } + stream.next() + return null + }, + languageData: { commentTokens: { line: '#' } }, +} + +export const caddyfileLanguage = StreamLanguage.define(parser)