@owomark/core 0.1.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.
@@ -0,0 +1,364 @@
1
+ import { B as BlockNode, a as BlockContextType, O as OwoMarkSelection, C as CoreStateSnapshot, S as SlashState, b as CommandRegistry, c as OwoMarkDocument, D as DirtyRange, P as PreviewBlockKind, d as PreviewBlock, e as BlockTransform, f as OwoMarkSharedStateController, I as InlineToken, g as InlineTokenType } from './dom-adapter-IZEW91gZ.js';
2
+ export { h as BeforeInputIntent, i as BlockContext, j as BlockContextListener, k as BlockInsertType, l as BlockType, m as CommandContext, n as CommandDefinition, o as CompositionState, p as CoreApplyAction, q as CoreApplyResult, r as CoreSelectionSnapshot, s as CreateOwoMarkCoreOptions, t as Decorator, u as DecoratorType, v as DocumentChangeCallback, w as DomAdapterInstance, H as HeadingLevel, x as HistoryEntry, y as IndentMode, z as IndentResult, J as JsonPrimitive, A as JsonValue, K as KeyDownIntent, L as Leaf, E as OwoMarkCommands, F as OwoMarkCore, G as OwoMarkEditorInstance, M as OwoMarkEditorLike, N as OwoMarkSharedState, Q as OwoMarkSharedStateStore, R as PasteIntent, T as PreviewDirtyReason, U as SlashStateListener, V as SlashTriggerInfo, W as VirtualPosition, X as VirtualSelection, Y as applyMarkdownIndent, Z as createOwoMarkCore, _ as getBlockIndexForPosition, $ as isVirtualSelectionCollapsed, a0 as linearToVirtual, a1 as linearToVirtualPosition, a2 as resolveIndentSize, a3 as virtualPositionToLinear, a4 as virtualPositionsEqual, a5 as virtualToLinear } from './dom-adapter-IZEW91gZ.js';
3
+ export { enableMapSet, produce } from 'immer';
4
+
5
+ /**
6
+ * Resolve the extended BlockContextType from a BlockNode.
7
+ *
8
+ * Now that math-block and table are first-class document model types,
9
+ * this module is a thin projection layer. The only derived type is
10
+ * 'empty' (blank paragraphs) for UI convenience.
11
+ */
12
+
13
+ /**
14
+ * Map a document-model BlockNode to BlockContextType.
15
+ *
16
+ * @param block The BlockNode at cursor position
17
+ */
18
+ declare function resolveBlockContextType(block: BlockNode): BlockContextType;
19
+
20
+ type CoreChangeListener = (markdown: string) => void;
21
+ type CoreSelectionListener = (selection: OwoMarkSelection) => void;
22
+ type CoreCompositionListener = (active: boolean) => void;
23
+ type CoreStateListener = (snapshot: CoreStateSnapshot) => void;
24
+ type CoreSlashStateListener = (state: SlashState) => void;
25
+ type CoreEventHub = {
26
+ onChange(callback: CoreChangeListener): () => void;
27
+ onSelectionChange(callback: CoreSelectionListener): () => void;
28
+ onCompositionStateChange(callback: CoreCompositionListener): () => void;
29
+ onStateChange(callback: CoreStateListener): () => void;
30
+ onSlashStateChange(callback: CoreSlashStateListener): () => void;
31
+ emitChange(markdown: string): void;
32
+ emitSelectionChange(selection: OwoMarkSelection): void;
33
+ emitCompositionChange(active: boolean): void;
34
+ emitStateChange(snapshot: CoreStateSnapshot): void;
35
+ emitSlashStateChange(state: SlashState): void;
36
+ };
37
+
38
+ declare function createCommandRegistry(): CommandRegistry;
39
+
40
+ type BlockIdGenerator = () => string;
41
+ /** Create a per-instance block ID generator. */
42
+ declare function createBlockIdGenerator(): BlockIdGenerator;
43
+ /** Reset the default block ID counter (for testing). */
44
+ declare function resetBlockIdCounter(): void;
45
+ declare function parseMarkdownToDocument(markdown: string, genId?: BlockIdGenerator): OwoMarkDocument;
46
+ /**
47
+ * Reconcile old and new block arrays using head+tail scanning.
48
+ * Unchanged blocks at the head and tail preserve old identity (including ID).
49
+ * Middle blocks (inserted, deleted, or modified) use new identity.
50
+ */
51
+ declare function reconcileBlocks(oldBlocks: readonly BlockNode[], newBlocks: readonly BlockNode[]): BlockNode[];
52
+ declare function serializeDocument(doc: OwoMarkDocument): string;
53
+ declare function getBlockById(doc: OwoMarkDocument, blockId: string): BlockNode | undefined;
54
+ declare function getBlockIndexById(doc: OwoMarkDocument, blockId: string): number;
55
+ declare function getBlockAtOffset(doc: OwoMarkDocument, offset: number): {
56
+ blockIndex: number;
57
+ offsetInBlock: number;
58
+ };
59
+ declare function getBlockStartOffset(doc: OwoMarkDocument, blockIndex: number): number;
60
+
61
+ /**
62
+ * Convert a DOM Selection/Range to a linear character offset relative to
63
+ * the editor root element.
64
+ */
65
+ declare function domRangeToOffset(root: HTMLElement, range: {
66
+ startContainer: Node;
67
+ startOffset: number;
68
+ endContainer: Node;
69
+ endOffset: number;
70
+ }): OwoMarkSelection | null;
71
+ /**
72
+ * Convert a linear character offset back to a DOM Range within the editor root.
73
+ */
74
+ declare function offsetToDomRange(root: HTMLElement, selection: OwoMarkSelection): Range | null;
75
+ /**
76
+ * Restore a selection on the editor root from linear offsets.
77
+ */
78
+ declare function restoreSelection(root: HTMLElement, selection: OwoMarkSelection): void;
79
+ /**
80
+ * Read current DOM selection as linear offsets.
81
+ */
82
+ declare function readSelection(root: HTMLElement): OwoMarkSelection | null;
83
+ /** Invalidate the cached block element list. Call after every DOM render. */
84
+ declare function invalidateBlockCache(root: HTMLElement): void;
85
+
86
+ /**
87
+ * Merge a new dirty block index into an existing dirty range.
88
+ */
89
+ declare function expandDirtyRange(current: DirtyRange | null, blockIndex: number, totalBlocks: number): DirtyRange | null;
90
+ /**
91
+ * Expand dirty range to include adjacent context blocks.
92
+ */
93
+ declare function expandWithContext(range: DirtyRange, totalBlocks: number, context?: number): DirtyRange | null;
94
+
95
+ /**
96
+ * Stable block identity derivation.
97
+ *
98
+ * Both editor and preview sides derive blockId from the same source line
99
+ * range, ensuring they share a common identity without runtime DOM coupling.
100
+ */
101
+ declare function deriveBlockId(startLine: number, endLine: number): string;
102
+
103
+ /**
104
+ * Derive a stable render key for a preview block.
105
+ *
106
+ * The render key determines cache validity. If the key is unchanged,
107
+ * the preview can skip re-rendering and reuse the cached result.
108
+ */
109
+
110
+ declare function deriveRenderKey(raw: string, kind: PreviewBlockKind, themeKey?: string): string;
111
+
112
+ /**
113
+ * Project a OwoMarkDocument into PreviewBlocks.
114
+ *
115
+ * Groups adjacent same-type container blocks (lists, blockquotes) into
116
+ * single preview blocks, computes source line ranges, and derives stable
117
+ * blockIds and renderKeys.
118
+ */
119
+
120
+ declare function projectToPreviewBlocks(doc: OwoMarkDocument, themeKey?: string, transforms?: BlockTransform[]): PreviewBlock[];
121
+ /**
122
+ * Compare two preview block arrays and return the dirty range.
123
+ * Uses two-pointer scan to find the tightest changed range (EV3).
124
+ * Returns null if no blocks changed.
125
+ * endBlock is always clamped to valid newBlocks range (RISK-3).
126
+ */
127
+ declare function computePreviewDirtyRange(oldBlocks: PreviewBlock[], newBlocks: PreviewBlock[]): {
128
+ startBlock: number;
129
+ endBlock: number;
130
+ } | null;
131
+
132
+ /**
133
+ * Framework-agnostic shared state store for editor <-> preview coordination.
134
+ *
135
+ * Wraps a OwoMarkEditorLike and produces OwoMarkSharedState snapshots
136
+ * that the preview engine can consume incrementally.
137
+ */
138
+
139
+ type CreateSharedStateOptions = {
140
+ initialMarkdown?: string;
141
+ themeKey?: string;
142
+ /** Block transforms applied during projection (shared by preview & build). */
143
+ transforms?: BlockTransform[];
144
+ };
145
+ declare function createSharedStateStore(options?: CreateSharedStateOptions): OwoMarkSharedStateController;
146
+
147
+ /**
148
+ * Tokenize inline Markdown content into decoration tokens.
149
+ * Pure function, no DOM dependency.
150
+ */
151
+ declare function tokenizeInline(raw: string, baseOffset?: number): InlineToken[];
152
+
153
+ /**
154
+ * Tokenize a single block's raw text into InlineToken[].
155
+ * Block-level markers (heading #, list bullet, etc.) get their own token types.
156
+ */
157
+ declare function tokenizeBlock(raw: string, blockType: string, baseOffset?: number): InlineToken[];
158
+
159
+ /**
160
+ * Enter key handling: list continuation, blockquote continuation,
161
+ * code fence auto-close and indent continuation.
162
+ *
163
+ * Migrated from admin-editor-writing-assists.ts — pure function,
164
+ * operates on text + selection, no DOM dependency.
165
+ */
166
+ type CommandResult = {
167
+ handled: boolean;
168
+ value: string;
169
+ selectionStart: number;
170
+ selectionEnd: number;
171
+ };
172
+ declare const NOT_HANDLED: CommandResult;
173
+ declare function handleMarkdownEnter(params: {
174
+ text: string;
175
+ selectionStart: number;
176
+ selectionEnd: number;
177
+ enableSideAnnotation?: boolean;
178
+ }): CommandResult;
179
+
180
+ /**
181
+ * Character input handling: paired symbol completion and forward delete pairing.
182
+ * Migrated from admin-editor-writing-assists.ts — pure function.
183
+ */
184
+
185
+ declare function handleCharInput(params: {
186
+ key: string;
187
+ text: string;
188
+ selectionStart: number;
189
+ selectionEnd: number;
190
+ isComposing: boolean;
191
+ }): CommandResult;
192
+ declare function handleSmartDelete(params: {
193
+ text: string;
194
+ selectionStart: number;
195
+ selectionEnd: number;
196
+ }): CommandResult;
197
+
198
+ /**
199
+ * Backspace handling: paired deletion and structural line collapse.
200
+ *
201
+ * Kept separate from char-input so structural Backspace rules
202
+ * (such as side-annotation continuation cleanup) can evolve independently.
203
+ */
204
+
205
+ declare function handleSmartBackspace(params: {
206
+ text: string;
207
+ selectionStart: number;
208
+ selectionEnd: number;
209
+ }): CommandResult;
210
+
211
+ /**
212
+ * Inline formatting commands: bold, italic, link, code fence.
213
+ * Operates on text + selection, no DOM dependency.
214
+ */
215
+
216
+ declare function toggleBold(params: {
217
+ text: string;
218
+ selectionStart: number;
219
+ selectionEnd: number;
220
+ }): CommandResult;
221
+ declare function toggleItalic(params: {
222
+ text: string;
223
+ selectionStart: number;
224
+ selectionEnd: number;
225
+ }): CommandResult;
226
+ declare function insertLink(params: {
227
+ text: string;
228
+ selectionStart: number;
229
+ selectionEnd: number;
230
+ url?: string;
231
+ }): CommandResult;
232
+ declare function insertCodeFence(params: {
233
+ text: string;
234
+ selectionStart: number;
235
+ selectionEnd: number;
236
+ language?: string;
237
+ }): CommandResult;
238
+ declare function insertMathBlock(params: {
239
+ text: string;
240
+ selectionStart: number;
241
+ selectionEnd: number;
242
+ }): CommandResult;
243
+ declare function insertTable(params: {
244
+ text: string;
245
+ selectionStart: number;
246
+ selectionEnd: number;
247
+ }): CommandResult;
248
+ declare function insertImage(params: {
249
+ text: string;
250
+ selectionStart: number;
251
+ selectionEnd: number;
252
+ }): CommandResult;
253
+ /**
254
+ * Insert side annotation syntax around selected blocks.
255
+ *
256
+ * Strategy (per spec):
257
+ * - 1-3 lines selected: wrap each line with inline (>} ...) + (>+)
258
+ * - 4+ lines selected: wrap in :::side container
259
+ * - No selection: insert skeleton (>} annotation) at cursor
260
+ */
261
+ declare function insertSideAnnotation(params: {
262
+ text: string;
263
+ selectionStart: number;
264
+ selectionEnd: number;
265
+ type?: string;
266
+ }): CommandResult;
267
+
268
+ type WordBoundaryResult = {
269
+ newText: string;
270
+ newPos: number;
271
+ };
272
+ declare function deleteWordBackward(text: string, pos: number): WordBoundaryResult;
273
+ declare function deleteWordForward(text: string, pos: number): WordBoundaryResult;
274
+ declare function deleteToLineStart(text: string, pos: number): WordBoundaryResult;
275
+ declare function deleteToLineEnd(text: string, pos: number): WordBoundaryResult;
276
+
277
+ /**
278
+ * Block transform: extract image dimensions from Markdown image syntax.
279
+ *
280
+ * Supports three configurable syntaxes:
281
+ * - obsidian: ![alt|800x600](url) or ![alt|100%x300](url)
282
+ * - pandoc: ![alt](url){width=800 height=600} or {w=800 h=600}
283
+ * - mou: ![alt](url =300x200)
284
+ *
285
+ * Also always parses <img> width/height attributes in HTML blocks.
286
+ *
287
+ * Extracted dimensions are stored in block.attributes.images as an array
288
+ * of { src, width, height } objects.
289
+ */
290
+
291
+ type ImageSizeSyntax = 'obsidian' | 'pandoc' | 'mou' | 'none';
292
+ /**
293
+ * Create a BlockTransform that extracts image dimensions.
294
+ *
295
+ * When images with size info are found, the block's `attributes.images`
296
+ * is set to an array of `{ src, width, height }` objects.
297
+ */
298
+ declare function createImageSizeTransform(syntax?: ImageSizeSyntax): BlockTransform;
299
+
300
+ declare function normalizeMarkdownPaste(raw: string, tabSize?: number): string;
301
+
302
+ /**
303
+ * Incremental DOM patch: only re-render dirty blocks.
304
+ */
305
+
306
+ /**
307
+ * Full render: build entire editor DOM from document model.
308
+ */
309
+ declare function fullRender(root: HTMLElement, doc: OwoMarkDocument): void;
310
+ /**
311
+ * Incremental patch: only re-render blocks in dirty range.
312
+ */
313
+ declare function patchDirtyBlocks(root: HTMLElement, doc: OwoMarkDocument, dirty: DirtyRange): void;
314
+ /**
315
+ * Detect changed blocks between old and new document, then render minimally.
316
+ * Falls back to full render when block count changes or no dirty blocks found
317
+ * despite text difference (structural shift).
318
+ */
319
+ declare function detectAndRenderDirty(root: HTMLElement, oldDoc: OwoMarkDocument, newDoc: OwoMarkDocument, fullFallback?: boolean): void;
320
+
321
+ /**
322
+ * Render a block's inline tokens into DOM nodes within a block container.
323
+ * Each block is a <div data-owo-block="index"> containing text/span nodes.
324
+ */
325
+
326
+ declare const TOKEN_TO_CLASS: Record<InlineTokenType, string>;
327
+ declare const BLOCK_TYPE_TO_CLASS: Record<string, string>;
328
+ declare function createBlockElement(doc: Document, tokens: InlineToken[], blockIndex: number, blockType: string, headingLevel?: number, depth?: number): HTMLDivElement;
329
+ /**
330
+ * Update an existing block element's content with new tokens.
331
+ * Returns true if the block was modified.
332
+ */
333
+ declare function updateBlockElement(doc: Document, existing: HTMLDivElement, tokens: InlineToken[], blockType: string, headingLevel?: number, depth?: number): boolean;
334
+
335
+ declare const BQ_STEP: number;
336
+ /**
337
+ * Build the CSS box-shadow value for nested blockquote bars.
338
+ * Returns null when depth <= 1 (no extra bars needed — the first bar is
339
+ * rendered by the block's own border/class styling).
340
+ */
341
+ declare function buildBlockquoteBarsBoxShadow(depth: number): string | null;
342
+
343
+ /** A flattened row for virtual list computation. */
344
+ type VirtualRow = {
345
+ blockIndex: number;
346
+ blockId: string;
347
+ height: number;
348
+ };
349
+ /** Result of visible range computation. */
350
+ type VisibleRange = {
351
+ startIndex: number;
352
+ endIndex: number;
353
+ totalHeight: number;
354
+ offsetTop: number;
355
+ offsetBottom: number;
356
+ };
357
+ /** Estimate a block's height in the editor (source view). */
358
+ declare function estimateEditorBlockHeight(block: BlockNode, charsPerLine?: number): number;
359
+ /** Build VirtualRow[] from blocks + height cache. */
360
+ declare function buildVirtualRows(blocks: readonly BlockNode[], heightCache: Map<string, number>, charsPerLine?: number): VirtualRow[];
361
+ /** Compute the visible range given scroll state. */
362
+ declare function computeVisibleRange(rows: VirtualRow[], scrollTop: number, viewportHeight: number, overscan?: number): VisibleRange;
363
+
364
+ export { BLOCK_TYPE_TO_CLASS, BQ_STEP, BlockContextType, type BlockIdGenerator, BlockNode, BlockTransform, CommandRegistry, type CommandResult, type CoreEventHub, type CoreSlashStateListener, CoreStateSnapshot, type CreateSharedStateOptions, DirtyRange, type ImageSizeSyntax, InlineToken, InlineTokenType, NOT_HANDLED, OwoMarkDocument, OwoMarkSelection, OwoMarkSharedStateController, PreviewBlock, PreviewBlockKind, SlashState, TOKEN_TO_CLASS, type VirtualRow, type VisibleRange, type WordBoundaryResult, buildBlockquoteBarsBoxShadow, buildVirtualRows, computePreviewDirtyRange, computeVisibleRange, createBlockElement, createBlockIdGenerator, createCommandRegistry, createImageSizeTransform, createSharedStateStore, deleteToLineEnd, deleteToLineStart, deleteWordBackward, deleteWordForward, deriveBlockId, deriveRenderKey, detectAndRenderDirty, domRangeToOffset, estimateEditorBlockHeight, expandDirtyRange, expandWithContext, fullRender, getBlockAtOffset, getBlockById, getBlockIndexById, getBlockStartOffset, handleCharInput, handleMarkdownEnter, handleSmartBackspace, handleSmartDelete, insertCodeFence, insertImage, insertLink, insertMathBlock, insertSideAnnotation, insertTable, invalidateBlockCache, normalizeMarkdownPaste, offsetToDomRange, parseMarkdownToDocument, patchDirtyBlocks, projectToPreviewBlocks, readSelection, reconcileBlocks, resetBlockIdCounter, resolveBlockContextType, restoreSelection, serializeDocument, toggleBold, toggleItalic, tokenizeBlock, tokenizeInline, updateBlockElement };