@synclineapi/mdx-editor 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![WCAG AA](https://img.shields.io/badge/Accessibility-WCAG%20AA-green.svg)](https://www.w3.org/TR/WCAG21/)
6
6
  [![Website](https://img.shields.io/badge/Website-markdown.synclineapi.com-blue)](https://markdown.synclineapi.com/)
7
7
 
8
- A **framework-agnostic**, plugin-based MDX/Markdown editor with a high-performance virtual-rendering code pane, live HTML preview, a configurable toolbar, and 33+ built-in content plugins. Works with React, Vue, Angular, Next.js, Svelte, or plain JavaScript.
8
+ A **framework-agnostic**, plugin-based MDX/Markdown editor with a high-performance virtual-rendering code pane, live HTML preview, a configurable toolbar, and 38 built-in content plugins. Works with React, Vue, Angular, Next.js, Svelte, or plain JavaScript.
9
9
 
10
10
  **[Live Demo →](https://markdown.synclineapi.com/)**
11
11
 
@@ -76,7 +76,7 @@ const editor = new SynclineMDXEditor({
76
76
 
77
77
  ## Features
78
78
 
79
- ### 33+ Built-in Plugins
79
+ ### 38 Built-in Plugins
80
80
 
81
81
  | Category | Plugins |
82
82
  |----------|---------|
@@ -88,6 +88,7 @@ const editor = new SynclineMDXEditor({
88
88
  | **Components** | Accordion, Accordion Group, Card, Card Group, Steps |
89
89
  | **Callouts** | Admonition (Tip / Warning / Caution / Danger / Info / Note), Tip (Good / Bad / Info) |
90
90
  | **Rich Content** | Highlight (8 colours), Emoji, Formula (KaTeX inline & block), Tooltip, Copy Text |
91
+ | **Inline labels** | Badge (success / warning / error / info), Status Tag (live / beta / soon / archived) |
91
92
  | **Embeds** | YouTube, Video file, GitHub Gist, Twitter/X, CodePen, CodeSandbox |
92
93
  | **Diagrams** | Mermaid (Flowchart, Sequence, Class, State, ER, Journey, Gantt) |
93
94
  | **Insert** | API Endpoint, Markdown Import, Code Snippet |
@@ -96,8 +97,8 @@ const editor = new SynclineMDXEditor({
96
97
 
97
98
  - **Virtual rendering** — only visible rows are in the DOM; handles documents of 10 000+ lines at 60 fps
98
99
  - **Word wrap** — proper pixel-width wrap with full active-line highlight across all visual rows
99
- - **MDX autocomplete** — context-aware component-tag and attribute suggestions; Tab-trigger snippet expansion
100
- - **Single-colour prose mode** — all syntax tokens collapse to the text colour for distraction-free writing
100
+ - **MDX autocomplete** — context-aware component-tag and attribute suggestions; Tab-trigger snippet expansion; plugins contribute items declaratively via `completions: [...]` or dynamically via `ctx.registerCompletion()`
101
+ - **Semantic syntax highlighting** — every built-in plugin declares a `provideTokens` function mapping its MDX syntax to semantic token classes (`kw`, `cls`, `fn`, `str`, `op`, `typ`, `num`, `cmt`); consumers can extend this with `registerSyntaxHighlighter()`
101
102
  - **Live HTML preview** — side-by-side split / editor-only / preview-only modes with a draggable splitter
102
103
  - **Table of Contents** — auto-generated from headings, collapsible panel
103
104
  - **Theme system** — light / dark toggle; auto-syncs with `data-theme`, `.smdx-dark`, or `data-color-scheme`
@@ -165,6 +166,71 @@ document.documentElement.dataset.theme = 'dark';
165
166
 
166
167
  ---
167
168
 
169
+ ## Syntax Highlighting
170
+
171
+ ### `registerSyntaxHighlighter()`
172
+
173
+ Add custom token providers that colour your own MDX component syntax on top of the built-in highlighting. Every built-in plugin already declares a `provideTokens` function; this API lets you extend it from outside.
174
+
175
+ ```ts
176
+ import type { PluginTokenProvider } from '@synclineapi/mdx-editor';
177
+ import { componentTagTokens } from '@synclineapi/mdx-editor';
178
+
179
+ // Quickest option — use the built-in JSX helper
180
+ // Highlights <MyCard …> tag names as `cls`, attribute names as `fn`, values as `str`.
181
+ // Handles boolean attributes like `defaultOpen` and `disabled` automatically.
182
+ editor.registerSyntaxHighlighter(componentTagTokens(['MyCard', 'MyCardGroup']));
183
+
184
+ // Custom provider for non-JSX syntax
185
+ const myProvider: PluginTokenProvider = (line) => {
186
+ const segs = [];
187
+ // Highlight :::type admonition-style fences
188
+ const m = line.match(/^(:::)(\w+)/);
189
+ if (m) {
190
+ segs.push({ cls: 'kw', start: 0, end: 3 });
191
+ segs.push({ cls: 'cls', start: 3, end: 3 + m[2].length });
192
+ }
193
+ return segs;
194
+ };
195
+ editor.registerSyntaxHighlighter(myProvider);
196
+
197
+ // Pass an array to register several at once
198
+ editor.registerSyntaxHighlighter([providerA, providerB]);
199
+ ```
200
+
201
+ ### Token classes
202
+
203
+ | `cls` | Colour role | Typical MDX use |
204
+ |-------|-------------|-----------------|
205
+ | `kw` | purple | Heading `#`, code fences ` ``` `, `:::`, `---`, blockquotes `>` |
206
+ | `str` | green | Link URLs, attribute values, inline `` `code` ``, `$math$` |
207
+ | `cmt` | muted gray | ~~Strikethrough~~ text |
208
+ | `fn` | blue | Link labels, *italic*, attribute names |
209
+ | `num` | orange | **Bold** text, `$$formula$$` markers |
210
+ | `cls` | yellow | `<Card>`, `<Tabs>`, `<Accordion>` — JSX component tag names |
211
+ | `op` | cyan | List markers `- 1.`, table pipes `\|` |
212
+ | `typ` | blue | Code-fence language identifiers (`mermaid`, `ts`, `python`) |
213
+ | `dec` | red | Decorators (reserved for custom use) |
214
+
215
+ ### `componentTagTokens()` helper
216
+
217
+ The built-in JSX highlighter factory. Handles:
218
+
219
+ - **Tag names**: `<Card`, `</Card>`, `<Card />` → `cls`
220
+ - **Value attributes**: `title="…"`, `src="…"` → name as `fn`, value as `str`
221
+ - **Boolean attributes**: `defaultOpen`, `disabled`, `open` (no `=`) → `fn`
222
+ - **Multi-line tags**: attributes that continue on the next line(s) are highlighted correctly — the provider tracks open-tag state across lines.
223
+ - Attribute scanning is scoped to the region between the tag name and `>` so tag body text is never falsely coloured.
224
+
225
+ ```ts
226
+ import { componentTagTokens } from '@synclineapi/mdx-editor';
227
+
228
+ provideTokens: componentTagTokens(['Accordion', 'AccordionGroup']),
229
+ // <Accordion title="…" defaultOpen> → Accordion=cls title=fn "…"=str defaultOpen=fn
230
+ ```
231
+
232
+ ---
233
+
168
234
  ## Autocomplete
169
235
 
170
236
  ### `registerAutoComplete()`
@@ -251,6 +317,8 @@ const myPlugin: EditorPlugin = {
251
317
  detail: '<MyBlock> component',
252
318
  body: '<MyBlock>\n $1Content\n</MyBlock>',
253
319
  },
320
+ // Component name entry (shows in autocomplete as a class suggestion)
321
+ { label: 'MyBlock', kind: 'cls', detail: 'custom block component' },
254
322
  ],
255
323
 
256
324
  // Preview renderer
@@ -263,6 +331,21 @@ const myPlugin: EditorPlugin = {
263
331
  },
264
332
  }],
265
333
 
334
+ // Syntax highlighting — called per-line, highlight component tag
335
+ // names, attribute names, and attribute values automatically.
336
+ // Use the built-in helper for JSX components:
337
+ provideTokens: componentTagTokens(['MyBlock']),
338
+ // Or write a custom provider for any syntax pattern:
339
+ // provideTokens: (line) => {
340
+ // const segs = [];
341
+ // const m = line.match(/^(:::)(\w+)/);
342
+ // if (m) {
343
+ // segs.push({ cls: 'kw', start: 0, end: 3 });
344
+ // segs.push({ cls: 'cls', start: 3, end: 3 + m[2].length });
345
+ // }
346
+ // return segs;
347
+ // },
348
+
266
349
  shortcuts: [
267
350
  {
268
351
  key: 'Ctrl+Shift+m',
@@ -398,6 +481,9 @@ interface SynclineMDXEditor {
398
481
  // Autocomplete
399
482
  registerAutoComplete(items: CompletionItem | CompletionItem[]): void;
400
483
 
484
+ // Syntax highlighting
485
+ registerSyntaxHighlighter(fn: PluginTokenProvider | PluginTokenProvider[]): void;
486
+
401
487
  // Theme sync
402
488
  syncCodeEditorTheme(): void;
403
489
 
@@ -1,4 +1,4 @@
1
- import { EditorConfig, EditorAPI, EditorPlugin, EditorMode, SelectionState } from './types';
1
+ import { EditorConfig, EditorAPI, EditorPlugin, EditorMode, SelectionState, PluginTokenProvider } from './types';
2
2
  import { CompletionItem } from '@synclineapi/editor';
3
3
  export declare class SynclineMDXEditor implements EditorAPI {
4
4
  private root;
@@ -58,6 +58,8 @@ export declare class SynclineMDXEditor implements EditorAPI {
58
58
  private setupThemeObserver;
59
59
  /** Completions registered directly by the consumer via `registerAutoComplete()`. */
60
60
  private _userCompletions;
61
+ /** Token providers registered directly by the consumer via `registerSyntaxHighlighter()`. */
62
+ private _userTokenProviders;
61
63
  private mountCodeEditor;
62
64
  /**
63
65
  * Rebuilds the full completions list pushed into the SynclineEditor.
@@ -96,6 +98,43 @@ export declare class SynclineMDXEditor implements EditorAPI {
96
98
  * ```
97
99
  */
98
100
  registerAutoComplete(items: CompletionItem | CompletionItem[]): void;
101
+ /**
102
+ * Rebuilds the composed `provideTokens` function pushed into the
103
+ * SynclineEditor, merging:
104
+ * 1. Built-in MDX base tokeniser (headings, bold, italic, links, etc.)
105
+ * 2. Plugin token providers — each registered plugin's `provideTokens`
106
+ * 3. User token providers — added via `registerSyntaxHighlighter()`
107
+ *
108
+ * Called automatically after every `registerPlugin` / `unregisterPlugin`
109
+ * and every `registerSyntaxHighlighter()` call.
110
+ */
111
+ private _refreshTokenProvider;
112
+ /**
113
+ * Register one or more custom syntax token providers on top of the
114
+ * built-in MDX tokeniser and any plugin-contributed providers.
115
+ *
116
+ * Each provider is called on every visible line in the code editor and
117
+ * may return `TokenSegment` objects covering the character ranges that
118
+ * should receive custom syntax colouring. The result is LRU-cached by
119
+ * the underlying `SynclineEditor`.
120
+ *
121
+ * Providers added here are equivalent to declaring `provideTokens` on a
122
+ * custom `EditorPlugin` — use whichever is more convenient.
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * editor.registerSyntaxHighlighter((line, _lang) => {
127
+ * const segs: TokenSegment[] = [];
128
+ * // Highlight <MyBlock component names
129
+ * for (const m of line.matchAll(/<\/?( MyBlock)(?=[\s>/])/g)) {
130
+ * const s = m.index! + 1 + (m[0][1] === '/' ? 1 : 0);
131
+ * segs.push({ cls: 'cls', start: s, end: s + 'MyBlock'.length });
132
+ * }
133
+ * return segs;
134
+ * });
135
+ * ```
136
+ */
137
+ registerSyntaxHighlighter(fn: PluginTokenProvider | PluginTokenProvider[]): void;
99
138
  private buildDOM;
100
139
  /** Convert a flat character offset to { row, col } in the document. */
101
140
  private offsetToPos;
@@ -1,4 +1,4 @@
1
- import { EditorAPI, ToolbarItemConfig, ShortcutConfig, RendererConfig, ParserConfig, EventHandler } from '../types';
1
+ import { EditorAPI, ToolbarItemConfig, ShortcutConfig, RendererConfig, ParserConfig, EventHandler, PluginTokenProvider } from '../types';
2
2
  export interface PluginContextOptions {
3
3
  editor: EditorAPI;
4
4
  registerToolbarItem: (item: ToolbarItemConfig) => void;
@@ -9,6 +9,7 @@ export interface PluginContextOptions {
9
9
  emit: (event: string, data?: unknown) => void;
10
10
  on: (event: string, handler: EventHandler) => void;
11
11
  off: (event: string, handler: EventHandler) => void;
12
+ registerTokenProvider: (fn: PluginTokenProvider) => void;
12
13
  }
13
14
  export declare class PluginContext {
14
15
  readonly editor: EditorAPI;
@@ -20,5 +21,6 @@ export declare class PluginContext {
20
21
  readonly emit: (event: string, data?: unknown) => void;
21
22
  readonly on: (event: string, handler: EventHandler) => void;
22
23
  readonly off: (event: string, handler: EventHandler) => void;
24
+ readonly registerTokenProvider: (fn: PluginTokenProvider) => void;
23
25
  constructor(options: PluginContextOptions);
24
26
  }
@@ -1,4 +1,4 @@
1
- import { EditorPlugin, ToolbarItemConfig, ShortcutConfig, RendererConfig, ParserConfig, EditorAPI, CompletionItem } from '../types';
1
+ import { EditorPlugin, ToolbarItemConfig, ShortcutConfig, RendererConfig, ParserConfig, EditorAPI, CompletionItem, PluginTokenProvider } from '../types';
2
2
  import { EventEmitter } from '../events';
3
3
  export declare class PluginManager {
4
4
  private editorApi;
@@ -11,6 +11,8 @@ export declare class PluginManager {
11
11
  private events;
12
12
  /** All completion items contributed by plugins, keyed by plugin name. */
13
13
  private completionsByPlugin;
14
+ /** All token providers contributed by plugins, keyed by plugin name. */
15
+ private tokenProvidersByPlugin;
14
16
  constructor(editorApi: EditorAPI, events: EventEmitter);
15
17
  register(plugin: EditorPlugin): Promise<void>;
16
18
  unregister(name: string): void;
@@ -25,6 +27,12 @@ export declare class PluginManager {
25
27
  * items added dynamically via `ctx.registerCompletion()`).
26
28
  */
27
29
  getCompletions(): CompletionItem[];
30
+ /**
31
+ * Returns the flat list of all token provider functions contributed by every
32
+ * currently-registered plugin (both static `provideTokens` declarations and
33
+ * providers added dynamically via `ctx.registerTokenProvider()`).
34
+ */
35
+ getTokenProviders(): PluginTokenProvider[];
28
36
  hasPlugin(name: string): boolean;
29
37
  getPlugin(name: string): EditorPlugin | undefined;
30
38
  private createContext;
@@ -1,5 +1,7 @@
1
- import { CompletionItem, CompletionKind } from '@synclineapi/editor';
2
- export type { CompletionItem, CompletionKind };
1
+ import { CompletionItem, CompletionKind, TokenSegment } from '@synclineapi/editor';
2
+ export type { CompletionItem, CompletionKind, TokenSegment };
3
+ /** Function signature for a plugin-level syntax token provider. */
4
+ export type PluginTokenProvider = (line: string, language: string) => TokenSegment[];
3
5
  export interface EditorConfig {
4
6
  container: HTMLElement | string;
5
7
  /** Initial markdown content */
@@ -70,6 +72,36 @@ export interface EditorPlugin {
70
72
  * ```
71
73
  */
72
74
  completions?: CompletionItem[];
75
+ /**
76
+ * Custom syntax token provider for this plugin's MDX constructs.
77
+ *
78
+ * Called on every visible line in the code editor **in addition to** the
79
+ * built-in MDX tokeniser. Return `TokenSegment` objects for the character
80
+ * ranges you want coloured. Ranges not covered fall back to the base MDX
81
+ * tokeniser.
82
+ *
83
+ * All plugin providers are composed into a single `provideTokens` function
84
+ * that is passed to the underlying `SynclineEditor`. The result is LRU-
85
+ * cached by the editor, so the function is only called once per unique
86
+ * `(text, language)` pair.
87
+ *
88
+ * Use `ctx.registerTokenProvider()` inside `init()` when the segments
89
+ * need to be computed dynamically (e.g. based on runtime config).
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * provideTokens: (line, _lang) => {
94
+ * const segs: TokenSegment[] = [];
95
+ * // Highlight <MyBlock component name
96
+ * for (const m of line.matchAll(/<\/?( MyBlock)(?=[\s>/])/g)) {
97
+ * const s = m.index! + 1 + (m[0][1] === '/' ? 1 : 0);
98
+ * segs.push({ cls: 'cls', start: s, end: s + 'MyBlock'.length });
99
+ * }
100
+ * return segs;
101
+ * }
102
+ * ```
103
+ */
104
+ provideTokens?: PluginTokenProvider;
73
105
  }
74
106
  export interface PluginContext {
75
107
  /** The editor instance */
@@ -100,6 +132,27 @@ export interface PluginContext {
100
132
  * ```
101
133
  */
102
134
  registerCompletion(item: CompletionItem): void;
135
+ /**
136
+ * Register a dynamic token provider for this plugin's MDX syntax.
137
+ * Equivalent to declaring `provideTokens` on the plugin definition but
138
+ * useful when the provider needs to be built dynamically inside `init()`.
139
+ *
140
+ * Multiple providers registered from the same plugin are all called and
141
+ * their results merged into the final token list.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * ctx.registerTokenProvider((line, _lang) => {
146
+ * const segs: TokenSegment[] = [];
147
+ * for (const m of line.matchAll(/<\/?( MyBlock)(?=[\s>/])/g)) {
148
+ * const s = m.index! + 1 + (m[0][1] === '/' ? 1 : 0);
149
+ * segs.push({ cls: 'cls', start: s, end: s + 'MyBlock'.length });
150
+ * }
151
+ * return segs;
152
+ * });
153
+ * ```
154
+ */
155
+ registerTokenProvider(fn: PluginTokenProvider): void;
103
156
  /** Emit a plugin event */
104
157
  emit(event: string, data?: unknown): void;
105
158
  /** Listen to events */
@@ -236,6 +289,31 @@ export interface EditorAPI {
236
289
  * ```
237
290
  */
238
291
  registerAutoComplete(items: CompletionItem | CompletionItem[]): void;
292
+ /**
293
+ * Register one or more custom syntax token providers on top of the
294
+ * built-in MDX tokeniser and any plugin-contributed providers.
295
+ *
296
+ * Each provider is called on every visible line in the code editor and
297
+ * may return `TokenSegment` objects covering the character ranges that
298
+ * should receive custom syntax colouring. The result is LRU-cached by
299
+ * the underlying `SynclineEditor`.
300
+ *
301
+ * Equivalent to declaring `provideTokens` on a custom `EditorPlugin` —
302
+ * use whichever is more convenient.
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * editor.registerSyntaxHighlighter((line, _lang) => {
307
+ * const segs: TokenSegment[] = [];
308
+ * for (const m of line.matchAll(/<\/?( MyBlock)(?=[\s>/])/g)) {
309
+ * const s = m.index! + 1 + (m[0][1] === '/' ? 1 : 0);
310
+ * segs.push({ cls: 'cls', start: s, end: s + 'MyBlock'.length });
311
+ * }
312
+ * return segs;
313
+ * });
314
+ * ```
315
+ */
316
+ registerSyntaxHighlighter(fn: PluginTokenProvider | PluginTokenProvider[]): void;
239
317
  }
240
318
  export interface SelectionState {
241
319
  start: number;
package/dist/index.d.ts CHANGED
@@ -7,7 +7,8 @@ export { Toolbar } from './core/toolbar';
7
7
  export { Renderer } from './core/renderer';
8
8
  export { History } from './core/history';
9
9
  export { icons } from './core/icons';
10
- export type { EditorConfig, EditorPlugin, EditorAPI, EditorMode, PluginContext, ToolbarConfig, ToolbarRow, ToolbarGroup, ToolbarDivider, ToolbarItemConfig, ToolbarAction, ToolbarActionContext, SelectionState, RendererFn, RendererConfig, ParserConfig, ShortcutConfig, EventHandler, EditorLocale, CompletionItem, CompletionKind, } from './core/types';
10
+ export type { EditorConfig, EditorPlugin, EditorAPI, EditorMode, PluginContext, ToolbarConfig, ToolbarRow, ToolbarGroup, ToolbarDivider, ToolbarItemConfig, ToolbarAction, ToolbarActionContext, SelectionState, RendererFn, RendererConfig, ParserConfig, ShortcutConfig, EventHandler, EditorLocale, CompletionItem, CompletionKind, TokenSegment, PluginTokenProvider, } from './core/types';
11
+ export { componentTagTokens, mdxBaseTokens, composeTokenProviders } from './plugins/token-utils';
11
12
  export { headingPlugin, boldPlugin, italicPlugin, strikethroughPlugin, quotePlugin, linkPlugin, imagePlugin, codePlugin, unorderedListPlugin, orderedListPlugin, taskListPlugin, tablePlugin, highlightPlugin, admonitionPlugin, tabPlugin, imageBackgroundPlugin, imageFramePlugin, accordionPlugin, accordionGroupPlugin, multiColumnPlugin, cardPlugin, cardGroupPlugin, stepPlugin, tipPlugin, containerPlugin, copyTextPlugin, tooltipPlugin, embedVideoPlugin, embedOthersPlugin, mermaidPlugin, emojiPlugin, formulaPlugin, insertPlugin, tocPlugin, breakLinePlugin, horizontalRulePlugin, allPlugins, defaultToolbar, } from './plugins';
12
13
  export { Renderer as RendererPipeline } from './core/renderer/Renderer';
13
14
  export { MarkdownRenderer } from './core/renderer/MarkdownRenderer';
@@ -0,0 +1,49 @@
1
+ import { TokenSegment, PluginTokenProvider } from '../core/types';
2
+ /**
3
+ * Creates a `provideTokens` function that highlights JSX component tag names
4
+ * for the given list of components with the `cls` (class/component) token class.
5
+ *
6
+ * Handles:
7
+ * - Opening tags: `<Card`, `<CardGroup`
8
+ * - Closing tags: `</Card>`, `</CardGroup>`
9
+ * - Self-closing tags: `<Card />`, `<Card/>`
10
+ * - Value attributes: `title="…"`, `src="…"` → name as `fn`, value as `str`
11
+ * - Boolean attributes:`defaultOpen`, `open`, `disabled` (no `=`) → `fn`
12
+ *
13
+ * Attribute scanning is scoped to the character region between the tag name
14
+ * and the closing `>` so tag body content is never falsely coloured.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * // In a plugin definition:
19
+ * provideTokens: componentTagTokens(['Accordion', 'AccordionGroup']),
20
+ * ```
21
+ */
22
+ export declare function componentTagTokens(tagNames: string[]): PluginTokenProvider;
23
+ /**
24
+ * Returns token segments for standard inline Markdown constructs on a line:
25
+ * - ATX headings: `# … ######` → `kw`
26
+ * - Blockquote prefix: `>` → `kw`
27
+ * - Horizontal rule: `---` / `***` / `___` alone on a line → `kw`
28
+ * - Bold: `**text**` → `num`
29
+ * - Italic: `*text*` / `_text_` → `fn`
30
+ * - Strikethrough: `~~text~~` → `cmt`
31
+ * - Inline code: `` `code` `` → `str`
32
+ * - Code fence marker: ` ``` ` / `~~~` + optional language → `kw` + `typ`
33
+ * - Links: `[text](url)` → `fn` for `[text]`, `str` for `(url)`
34
+ * - Images: `![alt](url)` → `fn` for `![alt]`, `str` for `(url)`
35
+ * - List markers: `- `, `* `, `+ ` / `1. ` → `op`
36
+ * - Task list checkbox: `[ ]` / `[x]` → `kw`
37
+ * - Table pipes: `|` separators → `op`
38
+ * - Import / Export: MDX `import`/`export` keyword lines → `kw` for the keyword
39
+ */
40
+ export declare function mdxBaseTokens(line: string, _language: string): TokenSegment[];
41
+ /**
42
+ * Compose an array of `PluginTokenProvider` functions into a single
43
+ * `provideTokens` function suitable for passing directly to `SynclineEditor`.
44
+ *
45
+ * Plugin providers run first (in registration order), then user providers.
46
+ * Segments from earlier providers take precedence for overlapping character
47
+ * ranges (the `SynclineEditor` renders the first covering segment).
48
+ */
49
+ export declare function composeTokenProviders(pluginProviders: PluginTokenProvider[], userProviders: PluginTokenProvider[]): PluginTokenProvider;