UNPKG

cm-tarnation

Version:

An alternative parser for CodeMirror 6

145 lines (110 loc) 3.99 kB
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import type { Tag as cmTag, tags as cmTags } from "@lezer/highlight" /** Filters a record for any properties which are equivalent to a given type. */ type FilterFor<O extends Record<string, any>, T> = { [Property in keyof O as O[Property] extends T ? Property : never]: O[Property] } /** Filters out of a record any properties which are equivalent to a given type. */ type FilterOut<O extends Record<string, any>, T> = { [Property in keyof O as O[Property] extends T ? never : Property]: O[Property] } /** A type which may be an array of itself, or just itself. */ type Arrayable<T> = T | T[] // TODO: document this // adding doc comments would be helpful, but what would be more helpful // is a JSON schema. doing that will take a while, so for now this is undocumented. // it's _mostly_ self-explanatory, but there are some things that are not obvious export interface Grammar { // CodeMirror language data comments?: { block?: { open: string; close: string } line?: string } closeBrackets?: { brackets?: string[] before?: string } indentOnInput?: Regex wordChars?: string // actual grammar ignoreCase?: boolean default?: Node repository?: Record<string, RepositoryItem> includes?: Record<string, string[]> global?: Inside root: Inside } export type RepositoryItem = Regex | Node | ReuseNode | Rule | State export type Rule = Lookup | Pattern | Chain export interface Node { type?: string open?: string close?: string emit?: string | boolean nest?: string // CodeMirror properties, doesn't affect grammar tag?: Tag openedBy?: Arrayable<string> closedBy?: Arrayable<string> group?: Arrayable<string> autocomplete?: true | string fold?: boolean | "inside" | "past_first_line" | `offset(${number}, ${number})` indent?: | "flat" | `delimited(${string})` | "continued" | `continued(${Regex})` | `add(${number})` | `set(${number})` } export interface State extends Node { begin: string | Rule end: string | Rule inside?: Inside | Node | ReuseNode | "inherit" | "loose" } export interface RuleOptions extends Node { captures?: Record<string, Node | ReuseNode | CaptureCondition> context?: Arrayable<ContextSetter> contextImmediate?: boolean lookbehind?: LookbehindSource lookahead?: Regex rematch?: boolean } export interface Lookup extends RuleOptions { lookup: string[] | VarIndex } export interface Pattern extends RuleOptions { match: Arrayable<string | Regex | VarIndex> } export interface Chain extends RuleOptions { chain: string[] skip?: Regex } export interface ContextSetter { if?: MatchIndex matches?: string | Regex | VarIndex set: string to: string | MatchIndex | null } export interface CaptureCondition { if?: MatchIndex matches: string | Regex | VarIndex | MatchIndex then?: Node | ReuseNode else?: Node | ReuseNode } export type ReuseNode = { is: string } export type Inside = (string | Rule | Include | State)[] export type Include = { include: string } export type StyleTag = keyof FilterOut<typeof cmTags, (tag: cmTag) => cmTag> export type FunctionTag = keyof FilterFor<typeof cmTags, (tag: cmTag) => cmTag> export type TagModifier = `(${`${string}/` | "!" | "..."}) ` | "" export type TagFunction = `${FunctionTag}(${StyleTag})` export type Tag = `${TagModifier}${string}` export type ChainItem = `${string}${"?" | "*" | "+" | ""}` export type Regex = `/${string}/${string}` export type LookbehindSource = `${"!" | ""}${Regex}` export type MatchIndex = `$${number}` export type VarIndex = `$var:${string}` export type ContextIndex = `$ctx:${string}`