@elabs-ai/components-editor 4.0.0
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/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/chunk-LBC5VJBD.js +3748 -0
- package/dist/chunk-LBC5VJBD.js.map +1 -0
- package/dist/index.css +233 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +199 -0
- package/dist/index.js +362 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/monaco-environment.d.ts +2 -0
- package/dist/lib/monaco-environment.js +44 -0
- package/dist/lib/monaco-environment.js.map +1 -0
- package/dist/markdown/frontmatter.d.ts +11 -0
- package/dist/markdown/frontmatter.js +33 -0
- package/dist/markdown/frontmatter.js.map +1 -0
- package/dist/markdown/index.css +233 -0
- package/dist/markdown/index.css.map +1 -0
- package/dist/markdown/index.d.ts +1486 -0
- package/dist/markdown/index.js +4882 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/markdown/parse.d.ts +25 -0
- package/dist/markdown/parse.js +14 -0
- package/dist/markdown/parse.js.map +1 -0
- package/dist/markdown-editor-DfBZibAn.d.ts +702 -0
- package/package.json +101 -0
- package/src/ai-objects/ai-objects-integration.test.tsx +128 -0
- package/src/ai-objects/ai-objects.stories.tsx +233 -0
- package/src/ai-objects/ai-objects.test.tsx +205 -0
- package/src/ai-objects/decision-card.tsx +178 -0
- package/src/ai-objects/directives.ts +136 -0
- package/src/ai-objects/entity.tsx +181 -0
- package/src/ai-objects/index.ts +34 -0
- package/src/ai-objects/knowledge-card.tsx +143 -0
- package/src/calc-block/calc-block.stories.tsx +297 -0
- package/src/calc-block/calc-block.test.tsx +164 -0
- package/src/calc-block/calc-block.tsx +398 -0
- package/src/calc-block/calc-editor-monaco.ts +214 -0
- package/src/calc-block/calc-editor-prose.ts +128 -0
- package/src/calc-block/calc-editor.css +80 -0
- package/src/calc-block/calc-editor.stories.tsx +272 -0
- package/src/calc-block/calc-editor.test.ts +228 -0
- package/src/calc-block/calc-editor.ts +270 -0
- package/src/calc-block/calc-inline.stories.tsx +44 -0
- package/src/calc-block/calc-inline.test.tsx +44 -0
- package/src/calc-block/calc-inline.tsx +75 -0
- package/src/calc-block/index.ts +20 -0
- package/src/calc-block/types.ts +164 -0
- package/src/code-editor/code-editor.stories.tsx +218 -0
- package/src/code-editor/code-editor.test.tsx +134 -0
- package/src/code-editor/code-editor.tsx +250 -0
- package/src/code-editor/index.ts +6 -0
- package/src/code-workspace/code-workspace.stories.tsx +51 -0
- package/src/code-workspace/code-workspace.test.tsx +146 -0
- package/src/code-workspace/code-workspace.tsx +253 -0
- package/src/code-workspace/index.ts +6 -0
- package/src/copy-button/copy-button.tsx +51 -0
- package/src/copy-button/index.ts +1 -0
- package/src/css.d.ts +3 -0
- package/src/diff-editor/diff-editor.stories.tsx +44 -0
- package/src/diff-editor/diff-editor.test.tsx +68 -0
- package/src/diff-editor/diff-editor.tsx +151 -0
- package/src/diff-editor/index.ts +1 -0
- package/src/editor-context-menu/editor-context-menu.tsx +120 -0
- package/src/editor-context-menu/index.ts +1 -0
- package/src/editor-toolbar/editor-toolbar.tsx +83 -0
- package/src/editor-toolbar/index.ts +1 -0
- package/src/index.ts +48 -0
- package/src/lib/editor-completions-monaco.test.ts +206 -0
- package/src/lib/editor-completions-monaco.ts +127 -0
- package/src/lib/editor-completions.test.ts +156 -0
- package/src/lib/editor-completions.ts +153 -0
- package/src/lib/editor-content-access-prose.test.ts +411 -0
- package/src/lib/editor-content-access-prose.ts +172 -0
- package/src/lib/editor-content-access.test.ts +182 -0
- package/src/lib/editor-content-access.ts +109 -0
- package/src/lib/languages.ts +32 -0
- package/src/lib/markdown/diff.test.ts +80 -0
- package/src/lib/markdown/diff.ts +194 -0
- package/src/lib/markdown/directives.ts +342 -0
- package/src/lib/markdown/frontmatter.ts +50 -0
- package/src/lib/markdown/markdown-scale.test.ts +65 -0
- package/src/lib/markdown/markdown-scale.ts +62 -0
- package/src/lib/markdown/merge.test.ts +64 -0
- package/src/lib/markdown/merge.ts +158 -0
- package/src/lib/markdown/slugify.test.ts +156 -0
- package/src/lib/markdown/slugify.ts +47 -0
- package/src/lib/monaco-environment.ts +103 -0
- package/src/lib/monaco-theme-bridge.ts +293 -0
- package/src/lib/use-data-theme.ts +61 -0
- package/src/markdown/frontmatter.ts +14 -0
- package/src/markdown/index.ts +323 -0
- package/src/markdown/parse.test.ts +60 -0
- package/src/markdown/parse.ts +38 -0
- package/src/markdown-academic/citations.test.ts +77 -0
- package/src/markdown-academic/citations.tsx +442 -0
- package/src/markdown-academic/footnotes.tsx +235 -0
- package/src/markdown-academic/index.ts +32 -0
- package/src/markdown-academic/math.tsx +163 -0
- package/src/markdown-academic/toc.tsx +88 -0
- package/src/markdown-editor/completions/completions-menu.tsx +96 -0
- package/src/markdown-editor/completions/completions-prose.test.ts +356 -0
- package/src/markdown-editor/completions/completions-prose.ts +313 -0
- package/src/markdown-editor/completions/completions-widget.tsx +75 -0
- package/src/markdown-editor/completions/index.ts +37 -0
- package/src/markdown-editor/directive-nodes.ts +151 -0
- package/src/markdown-editor/directive-views.test.tsx +189 -0
- package/src/markdown-editor/directive-views.tsx +795 -0
- package/src/markdown-editor/exit-keymap.test.ts +88 -0
- package/src/markdown-editor/exit-keymap.ts +87 -0
- package/src/markdown-editor/index.ts +6 -0
- package/src/markdown-editor/markdown-editor.css +250 -0
- package/src/markdown-editor/markdown-editor.directives.test.tsx +105 -0
- package/src/markdown-editor/markdown-editor.fill.test.ts +34 -0
- package/src/markdown-editor/markdown-editor.paste-embed.test.tsx +297 -0
- package/src/markdown-editor/markdown-editor.stories.tsx +560 -0
- package/src/markdown-editor/markdown-editor.strictmode.test.tsx +38 -0
- package/src/markdown-editor/markdown-editor.table.test.tsx +287 -0
- package/src/markdown-editor/markdown-editor.tsx +560 -0
- package/src/markdown-editor/milkdown-react/editor.tsx +33 -0
- package/src/markdown-editor/milkdown-react/index.ts +8 -0
- package/src/markdown-editor/milkdown-react/types.ts +27 -0
- package/src/markdown-editor/milkdown-react/use-editor.ts +27 -0
- package/src/markdown-editor/milkdown-react/use-get-editor.ts +56 -0
- package/src/markdown-editor/milkdown-react/use-instance.ts +23 -0
- package/src/markdown-editor/paste-embed.ts +355 -0
- package/src/markdown-editor/slash/brand-slash-commands.test.ts +194 -0
- package/src/markdown-editor/slash/brand-slash-commands.ts +324 -0
- package/src/markdown-editor/slash/brand-slash-plugin.test.ts +254 -0
- package/src/markdown-editor/slash/brand-slash-plugin.ts +385 -0
- package/src/markdown-editor/slash/index.ts +107 -0
- package/src/markdown-editor/slash/insert-directive.test.ts +263 -0
- package/src/markdown-editor/slash/insert-directive.ts +345 -0
- package/src/markdown-editor/slash/monaco-slash-menu.test.tsx +198 -0
- package/src/markdown-editor/slash/monaco-slash-menu.tsx +356 -0
- package/src/markdown-editor/slash/shortcut-monaco.ts +69 -0
- package/src/markdown-editor/slash/shortcut.test.ts +157 -0
- package/src/markdown-editor/slash/shortcut.ts +57 -0
- package/src/markdown-editor/slash/slash-menu.stories.tsx +139 -0
- package/src/markdown-editor/slash/slash-menu.tsx +115 -0
- package/src/markdown-editor/slash/slash-scroll.test.tsx +52 -0
- package/src/markdown-editor/slash/slash-widget.tsx +97 -0
- package/src/markdown-editor/slash/source-slash-trigger.test.ts +42 -0
- package/src/markdown-editor/slash/source-slash-trigger.ts +46 -0
- package/src/markdown-editor/table-view.tsx +249 -0
- package/src/markdown-iteration/directive.tsx +92 -0
- package/src/markdown-iteration/edit-context.ts +56 -0
- package/src/markdown-iteration/index.ts +24 -0
- package/src/markdown-iteration/iteration-block.test.tsx +138 -0
- package/src/markdown-iteration/iteration-builder-dialog.stories.tsx +293 -0
- package/src/markdown-iteration/iteration-builder-dialog.tsx +312 -0
- package/src/markdown-iteration/iteration-builder.test.ts +252 -0
- package/src/markdown-iteration/iteration-builder.ts +303 -0
- package/src/markdown-iteration/iteration.test.ts +56 -0
- package/src/markdown-iteration/iteration.tsx +333 -0
- package/src/markdown-iteration/template-dialog.stories.tsx +63 -0
- package/src/markdown-iteration/template-dialog.test.tsx +104 -0
- package/src/markdown-iteration/template-dialog.tsx +116 -0
- package/src/markdown-outline/document-outline.stories.tsx +76 -0
- package/src/markdown-outline/document-outline.tsx +83 -0
- package/src/markdown-outline/index.ts +2 -0
- package/src/markdown-outline/markdown-outline.test.ts +49 -0
- package/src/markdown-outline/markdown-outline.ts +60 -0
- package/src/markdown-preview/code-fence.tsx +193 -0
- package/src/markdown-preview/index.ts +8 -0
- package/src/markdown-preview/markdown-preview-academic.stories.tsx +203 -0
- package/src/markdown-preview/markdown-preview-academic.test.tsx +257 -0
- package/src/markdown-preview/markdown-preview-iteration-calc.test.tsx +71 -0
- package/src/markdown-preview/markdown-preview-iteration-nested.test.tsx +58 -0
- package/src/markdown-preview/markdown-preview-iteration.stories.tsx +187 -0
- package/src/markdown-preview/markdown-preview-iteration.test.tsx +90 -0
- package/src/markdown-preview/markdown-preview-linking.test.tsx +61 -0
- package/src/markdown-preview/markdown-preview-transclusion.test.tsx +33 -0
- package/src/markdown-preview/markdown-preview.stories.tsx +108 -0
- package/src/markdown-preview/markdown-preview.test.tsx +411 -0
- package/src/markdown-preview/markdown-preview.tsx +1541 -0
- package/src/markdown-toolbar/index.ts +8 -0
- package/src/markdown-toolbar/markdown-commands.test.ts +84 -0
- package/src/markdown-toolbar/markdown-commands.ts +104 -0
- package/src/markdown-toolbar/markdown-toolbar.stories.tsx +56 -0
- package/src/markdown-toolbar/markdown-toolbar.tsx +263 -0
- package/src/markdown-workspace/focus-writing.test.ts +52 -0
- package/src/markdown-workspace/focus-writing.ts +38 -0
- package/src/markdown-workspace/index.ts +6 -0
- package/src/markdown-workspace/markdown-workspace.stories.tsx +688 -0
- package/src/markdown-workspace/markdown-workspace.test.tsx +326 -0
- package/src/markdown-workspace/markdown-workspace.tsx +787 -0
- package/src/mermaid-diagram/index.ts +1 -0
- package/src/mermaid-diagram/mermaid-diagram.stories.tsx +42 -0
- package/src/mermaid-diagram/mermaid-diagram.test.tsx +86 -0
- package/src/mermaid-diagram/mermaid-diagram.tsx +318 -0
- package/src/mermaid-diagram/mermaid-viewer.test.tsx +89 -0
- package/src/mermaid-diagram/mermaid-viewer.tsx +367 -0
- package/src/mermaid-diagram/real-parse.test.ts +42 -0
- package/src/mermaid-diagram/remediate.test.ts +60 -0
- package/src/mermaid-diagram/remediate.ts +124 -0
- package/src/mermaid-workspace/index.ts +1 -0
- package/src/mermaid-workspace/mermaid-workspace.stories.tsx +28 -0
- package/src/mermaid-workspace/mermaid-workspace.tsx +71 -0
- package/src/metric-block/index.ts +1 -0
- package/src/metric-block/metric-block.stories.tsx +40 -0
- package/src/metric-block/metric-block.tsx +14 -0
- package/src/monaco-workers.d.ts +10 -0
- package/src/prose/index.ts +14 -0
- package/src/prose/prose.stories.tsx +44 -0
- package/src/prose/prose.test.tsx +44 -0
- package/src/prose/prose.tsx +21 -0
- package/src/timeline/index.ts +18 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @elabs-ai/components-editor/markdown — the opt-in markdown suite.
|
|
3
|
+
*
|
|
4
|
+
* Kept on its own subpath so Monaco-only consumers of `@elabs-ai/components-editor` never pull
|
|
5
|
+
* the markdown/WYSIWYG dependency tree (Milkdown, Streamdown, remark). Everything
|
|
6
|
+
* markdown-shaped — the WYSIWYG editor, the branded preview renderer, the prose /
|
|
7
|
+
* timeline / metric primitives the preview composes, and the shared remark
|
|
8
|
+
* pipeline — lives here.
|
|
9
|
+
*/
|
|
10
|
+
export {
|
|
11
|
+
MarkdownEditor,
|
|
12
|
+
type MarkdownEditorProps,
|
|
13
|
+
type MarkdownEditorHandle,
|
|
14
|
+
type EmbedAssetFn,
|
|
15
|
+
} from "../markdown-editor";
|
|
16
|
+
|
|
17
|
+
// Engine-agnostic content-access API — re-exported here for convenience so
|
|
18
|
+
// markdown-subpath consumers get the full picture from one import.
|
|
19
|
+
// `monacoContentAccess` is also on the `.` barrel; types are re-exported here
|
|
20
|
+
// for symmetry. The prose adapter is ONLY here (never on the `.` barrel — keeps
|
|
21
|
+
// @milkdown off the Monaco-only graph, #271-inverse).
|
|
22
|
+
export {
|
|
23
|
+
monacoContentAccess,
|
|
24
|
+
type EditorContentAccess,
|
|
25
|
+
type EditorSelection,
|
|
26
|
+
} from "../lib/editor-content-access";
|
|
27
|
+
export {
|
|
28
|
+
proseMirrorContentAccess,
|
|
29
|
+
selectionWatchPlugin,
|
|
30
|
+
type ProseMirrorContentAccessDeps,
|
|
31
|
+
type ProseMirrorContentAccessOptions,
|
|
32
|
+
} from "../lib/editor-content-access-prose";
|
|
33
|
+
|
|
34
|
+
// Declarative completion-provider API (#283) — e.g. `[[wikilink]]` autocomplete
|
|
35
|
+
// wired via the `completions` prop on `MarkdownWorkspace` / `MarkdownEditor`,
|
|
36
|
+
// with ZERO `monaco-editor` imports needed in consumer code. The library owns
|
|
37
|
+
// the Monaco registration lifecycle (registered once, refcounted across
|
|
38
|
+
// mounted workspaces, disposed with the last one) and mirrors providers into a
|
|
39
|
+
// deliberately minimal WYSIWYG popup — see `lib/editor-completions-monaco.ts`
|
|
40
|
+
// and `markdown-editor/completions/completions-prose.ts` for the exact
|
|
41
|
+
// Monaco-vs-WYSIWYG parity boundary. `attachCompletionsMonaco` is exported for
|
|
42
|
+
// advanced consumers composing their own Monaco surfaces (the `attachCalcMonaco`
|
|
43
|
+
// precedent).
|
|
44
|
+
export {
|
|
45
|
+
triggerQueryStart,
|
|
46
|
+
resolveReplaceRange,
|
|
47
|
+
collectCompletions,
|
|
48
|
+
type EditorCompletionItem,
|
|
49
|
+
type EditorCompletionProvider,
|
|
50
|
+
type EditorCompletionContext,
|
|
51
|
+
type CompletionReplaceRange,
|
|
52
|
+
type CompletionMatch,
|
|
53
|
+
} from "../lib/editor-completions";
|
|
54
|
+
export { attachCompletionsMonaco } from "../lib/editor-completions-monaco";
|
|
55
|
+
|
|
56
|
+
// Slash (`/`) command menu for the WYSIWYG editor — the branded at-caret block
|
|
57
|
+
// inserter (card/callout/metric/timeline + basic blocks). Opt in via the
|
|
58
|
+
// `slashMenu` prop on MarkdownEditor / MarkdownWorkspace; these exports let
|
|
59
|
+
// consumers extend the command list or build their own surface.
|
|
60
|
+
export {
|
|
61
|
+
BRAND_SLASH_COMMANDS,
|
|
62
|
+
brandSlashViewPlugins,
|
|
63
|
+
filterSlashCommands,
|
|
64
|
+
groupSlashCommands,
|
|
65
|
+
insertBrandDirective,
|
|
66
|
+
insertBasicBlock,
|
|
67
|
+
insertCalcFence,
|
|
68
|
+
resolveCalcInsert,
|
|
69
|
+
CALC_FENCE_SEED,
|
|
70
|
+
SlashMenu,
|
|
71
|
+
type SlashCommand,
|
|
72
|
+
type SlashInsertContext,
|
|
73
|
+
type SourceSlashContext,
|
|
74
|
+
type SlashMenuProps,
|
|
75
|
+
type BasicBlockId,
|
|
76
|
+
type InsertableDirective,
|
|
77
|
+
type SlashRange,
|
|
78
|
+
type BrandSlashViewOptions,
|
|
79
|
+
} from "../markdown-editor/slash";
|
|
80
|
+
// The Monaco source-pane slash popup (#271) — imported from the file directly
|
|
81
|
+
// (NOT the slash barrel) because it pulls the Monaco runtime; the slash barrel
|
|
82
|
+
// must stay Monaco-free for the Milkdown editor. This subpath already pulls
|
|
83
|
+
// Monaco via MarkdownWorkspace, so it is the right home for the parity export.
|
|
84
|
+
export {
|
|
85
|
+
MonacoSlashMenu,
|
|
86
|
+
type MonacoSlashMenuProps,
|
|
87
|
+
} from "../markdown-editor/slash/monaco-slash-menu";
|
|
88
|
+
|
|
89
|
+
// The hybrid authoring surface (source | wysiwyg | split) + its formatting toolbar.
|
|
90
|
+
export {
|
|
91
|
+
MarkdownWorkspace,
|
|
92
|
+
type MarkdownWorkspaceHandle,
|
|
93
|
+
type MarkdownWorkspaceProps,
|
|
94
|
+
type MarkdownWorkspaceMode,
|
|
95
|
+
} from "../markdown-workspace";
|
|
96
|
+
export {
|
|
97
|
+
MarkdownToolbar,
|
|
98
|
+
type MarkdownToolbarProps,
|
|
99
|
+
wrapSelection,
|
|
100
|
+
toggleLinePrefix,
|
|
101
|
+
insertLink,
|
|
102
|
+
insertHorizontalRule,
|
|
103
|
+
insertDirective,
|
|
104
|
+
} from "../markdown-toolbar";
|
|
105
|
+
|
|
106
|
+
// Shared visual scale — the single source of truth for heading sizes / weight /
|
|
107
|
+
// tracking / measure consumed by BOTH the preview (prose) and the WYSIWYG editor CSS.
|
|
108
|
+
export {
|
|
109
|
+
MARKDOWN_HEADING_REM,
|
|
110
|
+
MARKDOWN_HEADING_WEIGHT,
|
|
111
|
+
MARKDOWN_HEADING_TRACKING,
|
|
112
|
+
MARKDOWN_MEASURE,
|
|
113
|
+
markdownScaleVars,
|
|
114
|
+
type MarkdownHeadingLevel,
|
|
115
|
+
} from "../lib/markdown/markdown-scale";
|
|
116
|
+
|
|
117
|
+
// Rendering primitives (token-driven; composed by the preview + directive views).
|
|
118
|
+
export * from "../prose";
|
|
119
|
+
export { Timeline, type TimelineProps, type TimelineItem } from "../timeline";
|
|
120
|
+
export { MetricBlock, type MetricBlockProps } from "../metric-block";
|
|
121
|
+
|
|
122
|
+
// Branded preview + shared remark pipeline.
|
|
123
|
+
export {
|
|
124
|
+
MarkdownPreview,
|
|
125
|
+
type MarkdownPreviewProps,
|
|
126
|
+
type MarkdownHeadingInfo,
|
|
127
|
+
} from "../markdown-preview";
|
|
128
|
+
export {
|
|
129
|
+
buildMarkdownPlugins,
|
|
130
|
+
remarkBrandDirectives,
|
|
131
|
+
BRAND_DIRECTIVES,
|
|
132
|
+
type BrandDirectiveName,
|
|
133
|
+
type BuildMarkdownPluginsOptions,
|
|
134
|
+
type MarkdownDirectiveKind,
|
|
135
|
+
type MarkdownDirectiveContext,
|
|
136
|
+
type MarkdownDirectiveRenderer,
|
|
137
|
+
type MarkdownFenceContext,
|
|
138
|
+
type MarkdownFenceRenderer,
|
|
139
|
+
type MarkdownExtensions,
|
|
140
|
+
} from "../lib/markdown/directives";
|
|
141
|
+
// Monaco-free markdown parser (gfm + directives + frontmatter). The canonical
|
|
142
|
+
// dependency-light import is `@elabs-ai/components-editor/markdown/parse`; re-exported here for
|
|
143
|
+
// convenience when you're already pulling the full markdown suite.
|
|
144
|
+
export { parseMarkdown } from "./parse";
|
|
145
|
+
// Re-export the frontmatter utils from the `./frontmatter` subpath barrel (NOT
|
|
146
|
+
// directly from `../lib/markdown/frontmatter`) so there is a single canonical
|
|
147
|
+
// module — `lib/markdown/frontmatter` (impl) → `./frontmatter` (public barrel) →
|
|
148
|
+
// here. Importing `ParsedDocument` from either subpath resolves to one emitted
|
|
149
|
+
// module, so its type identity is assignable across import sites (see #39).
|
|
150
|
+
export { parseFrontmatter, serializeFrontmatter, type ParsedDocument } from "./frontmatter";
|
|
151
|
+
|
|
152
|
+
// Mermaid (#L1): branded diagram renderer + the source⇄diagram workspace (#L2).
|
|
153
|
+
export { MermaidDiagram, type MermaidDiagramProps } from "../mermaid-diagram";
|
|
154
|
+
export { MermaidWorkspace, type MermaidWorkspaceProps } from "../mermaid-workspace";
|
|
155
|
+
|
|
156
|
+
// Calc: a ```calc fence → a branded answer-column sheet, and `:calc[expr]` inline
|
|
157
|
+
// → a result chip — both evaluated by a consumer `evaluate` hook (the math engine
|
|
158
|
+
// stays in the app, like `resolveUrl`).
|
|
159
|
+
export { CalcBlock, type CalcBlockProps } from "../calc-block";
|
|
160
|
+
export { CalcInline, type CalcInlineProps } from "../calc-block";
|
|
161
|
+
export type {
|
|
162
|
+
CalcContext,
|
|
163
|
+
CalcLineResult,
|
|
164
|
+
CalcRule,
|
|
165
|
+
CalcSheet,
|
|
166
|
+
CalcTint,
|
|
167
|
+
CalcToken,
|
|
168
|
+
CalcTokenKind,
|
|
169
|
+
CalcValue,
|
|
170
|
+
CalcValueKind,
|
|
171
|
+
EvaluateCalc,
|
|
172
|
+
} from "../calc-block";
|
|
173
|
+
|
|
174
|
+
// Calc AUTHORING (#220): opt-in live highlighting + autocomplete + result inlays
|
|
175
|
+
// inside ```calc fences, wired via the `calc` prop on MarkdownEditor /
|
|
176
|
+
// MarkdownWorkspace. The hook TYPES let consumers type their engine; the wiring
|
|
177
|
+
// functions (`attachCalcMonaco`, `calcProsePlugins`) + `findCalcFences` are for
|
|
178
|
+
// advanced consumers composing their own Monaco / Milkdown surfaces. The library
|
|
179
|
+
// DECORATES, the consumer COMPUTES — no calc engine is bundled.
|
|
180
|
+
export type {
|
|
181
|
+
CalcComplete,
|
|
182
|
+
CalcCompletion,
|
|
183
|
+
CalcCompletionContext,
|
|
184
|
+
CalcCompletionKind,
|
|
185
|
+
CalcEditorHooks,
|
|
186
|
+
CalcTokenize,
|
|
187
|
+
} from "../calc-block";
|
|
188
|
+
export { findCalcFences, calcTokenClassName, type CalcFence } from "../calc-block/calc-editor";
|
|
189
|
+
export { attachCalcMonaco } from "../calc-block/calc-editor-monaco";
|
|
190
|
+
export { calcProsePlugins } from "../calc-block/calc-editor-prose";
|
|
191
|
+
|
|
192
|
+
// Ghost-diff annotations (#L18): line-level markdown diff → preview washes.
|
|
193
|
+
export {
|
|
194
|
+
computeMarkdownAnnotations,
|
|
195
|
+
summarizeAnnotations,
|
|
196
|
+
shiftAnnotations,
|
|
197
|
+
annotationForRange,
|
|
198
|
+
removedMarkerAt,
|
|
199
|
+
type MarkdownAnnotation,
|
|
200
|
+
type MarkdownAnnotationKind,
|
|
201
|
+
} from "../lib/markdown/diff";
|
|
202
|
+
// Normalization-aware WYSIWYG merge (WI-1) — for consumers composing their
|
|
203
|
+
// own editing surfaces on MarkdownEditor.
|
|
204
|
+
export { mergeNormalizedEdit } from "../lib/markdown/merge";
|
|
205
|
+
export type { MarkdownUrlKind } from "../markdown-preview";
|
|
206
|
+
|
|
207
|
+
// Document outline (#L6): heading extraction + the quiet TOC rail.
|
|
208
|
+
export {
|
|
209
|
+
DocumentOutline,
|
|
210
|
+
useMarkdownOutline,
|
|
211
|
+
parseMarkdownOutline,
|
|
212
|
+
type DocumentOutlineProps,
|
|
213
|
+
type MarkdownOutlineItem,
|
|
214
|
+
} from "../markdown-outline";
|
|
215
|
+
|
|
216
|
+
// AI-object directive trio: DecisionCard, EntityCard/Chip, KnowledgeCard +
|
|
217
|
+
// the renderer factories (decisionDirective, entityDirective, knowledgeDirective,
|
|
218
|
+
// aiObjectDirectives) for wiring into MarkdownPreview `extensions.directives`.
|
|
219
|
+
export {
|
|
220
|
+
DecisionCard,
|
|
221
|
+
decisionCardVariants,
|
|
222
|
+
DECISION_STATUSES,
|
|
223
|
+
type DecisionCardProps,
|
|
224
|
+
type DecisionStatus,
|
|
225
|
+
EntityCard,
|
|
226
|
+
EntityChip,
|
|
227
|
+
entityChipVariants,
|
|
228
|
+
ENTITY_KINDS,
|
|
229
|
+
type EntityCardProps,
|
|
230
|
+
type EntityChipProps,
|
|
231
|
+
type EntityKind,
|
|
232
|
+
KnowledgeCard,
|
|
233
|
+
type KnowledgeCardProps,
|
|
234
|
+
type KnowledgeSourceResolved,
|
|
235
|
+
type KnowledgeSourceResolver,
|
|
236
|
+
decisionDirective,
|
|
237
|
+
entityDirective,
|
|
238
|
+
knowledgeDirective,
|
|
239
|
+
aiObjectDirectives,
|
|
240
|
+
type AiObjectDirectivesOptions,
|
|
241
|
+
} from "../ai-objects";
|
|
242
|
+
|
|
243
|
+
// Academic layer — opt-in via MarkdownPreview props (`footnotes` / `resolveCitation`
|
|
244
|
+
// / `math` / `toc`): branded footnotes, Pandoc/Better-BibTeX citations + a generated
|
|
245
|
+
// bibliography, `$…$`/`$$…$$` math (KaTeX), and a generated `::toc`. The standalone
|
|
246
|
+
// components + the public contract types are exported here.
|
|
247
|
+
export {
|
|
248
|
+
Bibliography,
|
|
249
|
+
collectCitations,
|
|
250
|
+
FootnoteList,
|
|
251
|
+
MathBlock,
|
|
252
|
+
MathInline,
|
|
253
|
+
TableOfContents,
|
|
254
|
+
type BibliographyProps,
|
|
255
|
+
type CitationData,
|
|
256
|
+
type CitationStyle,
|
|
257
|
+
type CiteItem,
|
|
258
|
+
type CollectedCitations,
|
|
259
|
+
type FootnoteListProps,
|
|
260
|
+
type MathProps,
|
|
261
|
+
type ResolveCitation,
|
|
262
|
+
type ResolvedCitation,
|
|
263
|
+
type TableOfContentsProps,
|
|
264
|
+
} from "../markdown-academic";
|
|
265
|
+
|
|
266
|
+
// Iteration — opt-in via MarkdownPreview's `evaluateIteration` (+ `interpolate`)
|
|
267
|
+
// props: a `:::iterate` / `:::pivot` repeater that renders a per-cell markdown
|
|
268
|
+
// template over consumer-resolved data (stacked / grid / matrix layouts). The
|
|
269
|
+
// standalone `IterationBlock` + the public contract types are exported here.
|
|
270
|
+
export {
|
|
271
|
+
IterationBlock,
|
|
272
|
+
defaultInterpolate,
|
|
273
|
+
specFromDirective,
|
|
274
|
+
type EvaluateIteration,
|
|
275
|
+
type InterpolateTemplate,
|
|
276
|
+
type IterationBlockProps,
|
|
277
|
+
type IterationCell,
|
|
278
|
+
type IterationData,
|
|
279
|
+
type IterationLayout,
|
|
280
|
+
type IterationSpec,
|
|
281
|
+
} from "../markdown-iteration";
|
|
282
|
+
// The #223 template modal (Dialog + MarkdownWorkspace) + its one-liner wiring —
|
|
283
|
+
// exported from the heavy (Monaco/Milkdown) side, not the render-light
|
|
284
|
+
// `markdown-iteration` barrel. The node-view `⋯` re-edit seam is `IterationEditContext`.
|
|
285
|
+
export {
|
|
286
|
+
IterationTemplateDialog,
|
|
287
|
+
IterationTemplateProvider,
|
|
288
|
+
type IterationTemplateDialogProps,
|
|
289
|
+
} from "../markdown-iteration/template-dialog";
|
|
290
|
+
export {
|
|
291
|
+
IterationEditContext,
|
|
292
|
+
type IterationEditHandler,
|
|
293
|
+
type IterationEditRequest,
|
|
294
|
+
} from "../markdown-iteration/edit-context";
|
|
295
|
+
// The #223 GUIDED builder (A5): collects the DATA (value lists + bind name +
|
|
296
|
+
// layout) as well as the template, writes a fully-bound directive, and renders a
|
|
297
|
+
// populated result with the built-in `evaluateEmbedded`. The `⋯` re-edit reopens
|
|
298
|
+
// it losslessly via `IterationBuilderProvider`.
|
|
299
|
+
export {
|
|
300
|
+
IterationBuilderDialog,
|
|
301
|
+
IterationBuilderProvider,
|
|
302
|
+
type IterationBuilderDialogProps,
|
|
303
|
+
} from "../markdown-iteration/iteration-builder-dialog";
|
|
304
|
+
export {
|
|
305
|
+
serializeIterationDirective,
|
|
306
|
+
parseIterationDirective,
|
|
307
|
+
builderValueFromParts,
|
|
308
|
+
directivePartsFromValue,
|
|
309
|
+
emptyBuilderValue,
|
|
310
|
+
evaluateEmbedded,
|
|
311
|
+
splitList,
|
|
312
|
+
parseAttributes,
|
|
313
|
+
DEFAULT_TEMPLATE,
|
|
314
|
+
type IterationBuilderValue,
|
|
315
|
+
} from "../markdown-iteration/iteration-builder";
|
|
316
|
+
// The #223 node-menu model helpers: "Transpose" (swap a pivot's rows/cols) and
|
|
317
|
+
// "Convert to static" (render the resolved cells as plain markdown, no
|
|
318
|
+
// ProseMirror dependency) — the pure functions behind the iteration node-view's
|
|
319
|
+
// right-click / `⋯` menu actions (see `markdown-editor/directive-views.tsx`).
|
|
320
|
+
export {
|
|
321
|
+
transposeIterationValue,
|
|
322
|
+
staticMarkdownFromValue,
|
|
323
|
+
} from "../markdown-iteration/iteration-builder";
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { parseMarkdown } from "./parse";
|
|
4
|
+
|
|
5
|
+
/** Minimal recursive mdast shape for walking without pulling the full types. */
|
|
6
|
+
type MdNode = { type: string; name?: string; children?: MdNode[] };
|
|
7
|
+
|
|
8
|
+
function nodeTypes(tree: MdNode): Set<string> {
|
|
9
|
+
const types = new Set<string>();
|
|
10
|
+
const walk = (n: MdNode) => {
|
|
11
|
+
types.add(n.type);
|
|
12
|
+
for (const c of n.children ?? []) walk(c);
|
|
13
|
+
};
|
|
14
|
+
walk(tree);
|
|
15
|
+
return types;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe("parseMarkdown", () => {
|
|
19
|
+
it("parses gfm + directives + frontmatter into one mdast tree", () => {
|
|
20
|
+
const tree = parseMarkdown(
|
|
21
|
+
[
|
|
22
|
+
"---",
|
|
23
|
+
"title: X",
|
|
24
|
+
"---",
|
|
25
|
+
"# Heading",
|
|
26
|
+
"",
|
|
27
|
+
':::card{title="T"}',
|
|
28
|
+
"body",
|
|
29
|
+
":::",
|
|
30
|
+
"",
|
|
31
|
+
"| a | b |",
|
|
32
|
+
"| - | - |",
|
|
33
|
+
"| 1 | 2 |",
|
|
34
|
+
].join("\n"),
|
|
35
|
+
) as unknown as MdNode;
|
|
36
|
+
|
|
37
|
+
const types = nodeTypes(tree);
|
|
38
|
+
expect(tree.type).toBe("root");
|
|
39
|
+
expect(types.has("yaml")).toBe(true); // frontmatter
|
|
40
|
+
expect(types.has("containerDirective")).toBe(true); // remark-directive
|
|
41
|
+
expect(types.has("table")).toBe(true); // gfm
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("parses inline + leaf directives", () => {
|
|
45
|
+
// Inline `:entity` sits mid-sentence; a leaf `::metric` occupies its own line.
|
|
46
|
+
const tree = parseMarkdown(
|
|
47
|
+
"Owner :entity[Acme]{kind=org} ships it.\n\n::metric{value=1}",
|
|
48
|
+
) as unknown as MdNode;
|
|
49
|
+
const types = nodeTypes(tree);
|
|
50
|
+
expect(types.has("textDirective")).toBe(true);
|
|
51
|
+
expect(types.has("leafDirective")).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("returns RAW directive mdast — it does NOT rewrite to <brand-directive>", () => {
|
|
55
|
+
const tree = parseMarkdown(":::card\nx\n:::") as unknown as MdNode;
|
|
56
|
+
const json = JSON.stringify(tree);
|
|
57
|
+
expect(json).toContain("containerDirective");
|
|
58
|
+
expect(json).not.toContain("brand-directive");
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@elabs-ai/components-editor/markdown/parse` — a Monaco-free markdown parser.
|
|
3
|
+
*
|
|
4
|
+
* `parseMarkdown(md)` returns the mdast `Root` for the SAME dialect the branded
|
|
5
|
+
* preview parses: GitHub-flavored markdown + `:::`/`::`/`:` directives + YAML
|
|
6
|
+
* frontmatter. Split onto its own leaf subpath (like `./markdown/frontmatter`) so
|
|
7
|
+
* SERVER, RSC, and unit-test consumers can parse markdown WITHOUT pulling the
|
|
8
|
+
* editor engines (Milkdown, Monaco, Streamdown) into their bundle — the whole
|
|
9
|
+
* reason the `.` vs `./markdown` split exists. Depends only on `unified` +
|
|
10
|
+
* `remark-*` (no React, no Monaco).
|
|
11
|
+
*
|
|
12
|
+
* It returns RAW directive mdast (`containerDirective` / `leafDirective` /
|
|
13
|
+
* `textDirective` nodes) — it does NOT run `remarkBrandDirectives` (that rewrites
|
|
14
|
+
* directives into the `<brand-directive>` hast tag, which is a RENDER concern).
|
|
15
|
+
* Walk the tree by `node.type` + `node.name` yourself. The match is at the
|
|
16
|
+
* DIALECT level (same plugins/extensions); it is not byte-identical to the tree
|
|
17
|
+
* Streamdown builds internally (which also applies a streaming block-splitter).
|
|
18
|
+
*/
|
|
19
|
+
import type { Root } from "mdast";
|
|
20
|
+
import remarkDirective from "remark-directive";
|
|
21
|
+
import remarkFrontmatter from "remark-frontmatter";
|
|
22
|
+
import remarkGfm from "remark-gfm";
|
|
23
|
+
import remarkParse from "remark-parse";
|
|
24
|
+
import { unified } from "unified";
|
|
25
|
+
|
|
26
|
+
// Built once: a frozen parser-only processor (gfm + frontmatter + directive
|
|
27
|
+
// syntax extensions). `parse()` is stateless per call, so one instance is safe.
|
|
28
|
+
const processor = unified()
|
|
29
|
+
.use(remarkParse)
|
|
30
|
+
.use(remarkGfm)
|
|
31
|
+
.use(remarkFrontmatter, ["yaml"])
|
|
32
|
+
.use(remarkDirective)
|
|
33
|
+
.freeze();
|
|
34
|
+
|
|
35
|
+
/** Parse markdown to mdast (gfm + directives + frontmatter). Monaco-free. */
|
|
36
|
+
export function parseMarkdown(md: string): Root {
|
|
37
|
+
return processor.parse(md) as Root;
|
|
38
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { collectCitations, parseCitationBracket, type CitationData } from "./citations";
|
|
4
|
+
|
|
5
|
+
describe("parseCitationBracket", () => {
|
|
6
|
+
it("parses a single key", () => {
|
|
7
|
+
expect(parseCitationBracket("@smith2020")).toEqual([{ key: "smith2020" }]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("parses multiple `;`-separated keys", () => {
|
|
11
|
+
expect(parseCitationBracket("@a; @b")).toEqual([{ key: "a" }, { key: "b" }]);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("captures a locator after the key", () => {
|
|
15
|
+
expect(parseCitationBracket("@smith2020, p. 5")).toEqual([
|
|
16
|
+
{ key: "smith2020", locator: "p. 5" },
|
|
17
|
+
]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("captures the suppress-author marker", () => {
|
|
21
|
+
expect(parseCitationBracket("-@smith2020")).toEqual([
|
|
22
|
+
{ key: "smith2020", suppressAuthor: true },
|
|
23
|
+
]);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("captures a prefix", () => {
|
|
27
|
+
expect(parseCitationBracket("see @smith2020")).toEqual([{ key: "smith2020", prefix: "see" }]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("accepts Better-BibTeX keys with separators", () => {
|
|
31
|
+
expect(parseCitationBracket("@smith:2020a")).toEqual([{ key: "smith:2020a" }]);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("returns null for ordinary bracketed prose (no @key)", () => {
|
|
35
|
+
expect(parseCitationBracket("see figure 1")).toBeNull();
|
|
36
|
+
expect(parseCitationBracket("i")).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("returns null when any `;`-part is not a citation", () => {
|
|
40
|
+
expect(parseCitationBracket("@a; not a cite")).toBeNull();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("collectCitations", () => {
|
|
45
|
+
const DB: Record<string, CitationData> = {
|
|
46
|
+
smith2020: { author: "Smith", year: 2020 },
|
|
47
|
+
jones2019: { author: "Jones", year: 2019 },
|
|
48
|
+
};
|
|
49
|
+
const resolve = (k: string) => DB[k] ?? null;
|
|
50
|
+
|
|
51
|
+
it("numbers resolved citations in first-appearance order", () => {
|
|
52
|
+
const md = "First [@jones2019], then [@smith2020], then [@jones2019] again.";
|
|
53
|
+
const { order, byKey } = collectCitations(md, resolve);
|
|
54
|
+
expect(order.map((e) => e.key)).toEqual(["jones2019", "smith2020"]);
|
|
55
|
+
expect(byKey.get("jones2019")?.n).toBe(1);
|
|
56
|
+
expect(byKey.get("smith2020")?.n).toBe(2);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("records unresolved keys without assigning a number", () => {
|
|
60
|
+
const md = "Known [@smith2020] and unknown [@ghost1999].";
|
|
61
|
+
const { order, byKey } = collectCitations(md, resolve);
|
|
62
|
+
expect(order.map((e) => e.key)).toEqual(["smith2020"]);
|
|
63
|
+
expect(byKey.get("ghost1999")).toEqual({ key: "ghost1999", data: null });
|
|
64
|
+
expect(byKey.get("smith2020")?.n).toBe(1);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("collects every key in a multi-key bracket", () => {
|
|
68
|
+
const { byKey } = collectCitations("[@smith2020; @jones2019]", resolve);
|
|
69
|
+
expect(byKey.get("smith2020")?.n).toBe(1);
|
|
70
|
+
expect(byKey.get("jones2019")?.n).toBe(2);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("ignores non-citation brackets", () => {
|
|
74
|
+
const { order } = collectCitations("An array[index] and a [link](x).", resolve);
|
|
75
|
+
expect(order).toHaveLength(0);
|
|
76
|
+
});
|
|
77
|
+
});
|