@malva-ui/editor 0.1.13 → 0.1.14
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 +5 -5
- package/fesm2022/malva-ui-editor-ai.mjs +17 -0
- package/fesm2022/malva-ui-editor-ai.mjs.map +1 -0
- package/fesm2022/malva-ui-editor.mjs +10227 -0
- package/fesm2022/malva-ui-editor.mjs.map +1 -0
- package/package.json +35 -26
- package/types/malva-ui-editor-ai.d.ts +1 -0
- package/types/malva-ui-editor.d.ts +2995 -0
- package/ai/index.d.ts +0 -12
- package/ai/malva-ui-editor-ai.d.ts +0 -5
- package/esm2022/ai/index.js +0 -12
- package/esm2022/ai/index.js.map +0 -1
- package/esm2022/ai/malva-ui-editor-ai.js +0 -5
- package/esm2022/ai/malva-ui-editor-ai.js.map +0 -1
- package/esm2022/index.js +0 -37
- package/esm2022/index.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-actions.js +0 -69
- package/esm2022/lib/ai/editor-ai-actions.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-context.js +0 -612
- package/esm2022/lib/ai/editor-ai-context.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-menu.js +0 -288
- package/esm2022/lib/ai/editor-ai-menu.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-review-bar.js +0 -223
- package/esm2022/lib/ai/editor-ai-review-bar.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-stream.js +0 -677
- package/esm2022/lib/ai/editor-ai-stream.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-suggestions.js +0 -751
- package/esm2022/lib/ai/editor-ai-suggestions.js.map +0 -1
- package/esm2022/lib/ai/editor-ai.tokens.js +0 -10
- package/esm2022/lib/ai/editor-ai.tokens.js.map +0 -1
- package/esm2022/lib/ai/editor-ai.types.js +0 -1
- package/esm2022/lib/ai/editor-ai.types.js.map +0 -1
- package/esm2022/lib/editor/editor.js +0 -985
- package/esm2022/lib/editor/editor.js.map +0 -1
- package/esm2022/lib/editor-extension-preflight.js +0 -83
- package/esm2022/lib/editor-extension-preflight.js.map +0 -1
- package/esm2022/lib/editor-serialization.js +0 -152
- package/esm2022/lib/editor-serialization.js.map +0 -1
- package/esm2022/lib/editor-toolbar-context.js +0 -259
- package/esm2022/lib/editor-toolbar-context.js.map +0 -1
- package/esm2022/lib/editor.tokens.js +0 -10
- package/esm2022/lib/editor.tokens.js.map +0 -1
- package/esm2022/lib/editor.types.js +0 -48
- package/esm2022/lib/editor.types.js.map +0 -1
- package/esm2022/lib/extensions/editor-block-handle.js +0 -760
- package/esm2022/lib/extensions/editor-block-handle.js.map +0 -1
- package/esm2022/lib/extensions/editor-extensions.js +0 -321
- package/esm2022/lib/extensions/editor-extensions.js.map +0 -1
- package/esm2022/lib/extensions/editor-markdown-compatibility.js +0 -162
- package/esm2022/lib/extensions/editor-markdown-compatibility.js.map +0 -1
- package/esm2022/lib/extensions/editor-upload-placeholder.js +0 -156
- package/esm2022/lib/extensions/editor-upload-placeholder.js.map +0 -1
- package/esm2022/lib/status/editor-status.js +0 -64
- package/esm2022/lib/status/editor-status.js.map +0 -1
- package/esm2022/lib/toolbar/editor-alignment.js +0 -203
- package/esm2022/lib/toolbar/editor-alignment.js.map +0 -1
- package/esm2022/lib/toolbar/editor-block-insert.js +0 -101
- package/esm2022/lib/toolbar/editor-block-insert.js.map +0 -1
- package/esm2022/lib/toolbar/editor-color-control.js +0 -71
- package/esm2022/lib/toolbar/editor-color-control.js.map +0 -1
- package/esm2022/lib/toolbar/editor-command-button.js +0 -115
- package/esm2022/lib/toolbar/editor-command-button.js.map +0 -1
- package/esm2022/lib/toolbar/editor-heading.js +0 -266
- package/esm2022/lib/toolbar/editor-heading.js.map +0 -1
- package/esm2022/lib/toolbar/editor-highlight.js +0 -84
- package/esm2022/lib/toolbar/editor-highlight.js.map +0 -1
- package/esm2022/lib/toolbar/editor-image-upload-dialog.js +0 -289
- package/esm2022/lib/toolbar/editor-image-upload-dialog.js.map +0 -1
- package/esm2022/lib/toolbar/editor-image-upload.js +0 -315
- package/esm2022/lib/toolbar/editor-image-upload.js.map +0 -1
- package/esm2022/lib/toolbar/editor-inline-marks.js +0 -124
- package/esm2022/lib/toolbar/editor-inline-marks.js.map +0 -1
- package/esm2022/lib/toolbar/editor-link.js +0 -265
- package/esm2022/lib/toolbar/editor-link.js.map +0 -1
- package/esm2022/lib/toolbar/editor-list.js +0 -249
- package/esm2022/lib/toolbar/editor-list.js.map +0 -1
- package/esm2022/lib/toolbar/editor-table.js +0 -292
- package/esm2022/lib/toolbar/editor-table.js.map +0 -1
- package/esm2022/lib/toolbar/editor-text-color.js +0 -82
- package/esm2022/lib/toolbar/editor-text-color.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar-widget.js +0 -41
- package/esm2022/lib/toolbar/editor-toolbar-widget.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar.defs.js +0 -60
- package/esm2022/lib/toolbar/editor-toolbar.defs.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar.js +0 -826
- package/esm2022/lib/toolbar/editor-toolbar.js.map +0 -1
- package/esm2022/lib/toolbar/editor-undo-redo.js +0 -72
- package/esm2022/lib/toolbar/editor-undo-redo.js.map +0 -1
- package/esm2022/lib/toolbar/editor-zoom.js +0 -330
- package/esm2022/lib/toolbar/editor-zoom.js.map +0 -1
- package/esm2022/lib/upload/editor-image-upload-coordinator.js +0 -480
- package/esm2022/lib/upload/editor-image-upload-coordinator.js.map +0 -1
- package/esm2022/malva-ui-editor.js +0 -5
- package/esm2022/malva-ui-editor.js.map +0 -1
- package/index.d.ts +0 -35
- package/lib/ai/editor-ai-actions.d.ts +0 -27
- package/lib/ai/editor-ai-context.d.ts +0 -307
- package/lib/ai/editor-ai-menu.d.ts +0 -142
- package/lib/ai/editor-ai-review-bar.d.ts +0 -116
- package/lib/ai/editor-ai-stream.d.ts +0 -207
- package/lib/ai/editor-ai-suggestions.d.ts +0 -219
- package/lib/ai/editor-ai.tokens.d.ts +0 -10
- package/lib/ai/editor-ai.types.d.ts +0 -176
- package/lib/editor/editor.d.ts +0 -243
- package/lib/editor-extension-preflight.d.ts +0 -23
- package/lib/editor-serialization.d.ts +0 -74
- package/lib/editor-toolbar-context.d.ts +0 -116
- package/lib/editor.tokens.d.ts +0 -6
- package/lib/editor.types.d.ts +0 -194
- package/lib/extensions/editor-block-handle.d.ts +0 -59
- package/lib/extensions/editor-extensions.d.ts +0 -165
- package/lib/extensions/editor-markdown-compatibility.d.ts +0 -11
- package/lib/extensions/editor-upload-placeholder.d.ts +0 -75
- package/lib/status/editor-status.d.ts +0 -24
- package/lib/toolbar/editor-alignment.d.ts +0 -61
- package/lib/toolbar/editor-block-insert.d.ts +0 -26
- package/lib/toolbar/editor-color-control.d.ts +0 -32
- package/lib/toolbar/editor-command-button.d.ts +0 -29
- package/lib/toolbar/editor-heading.d.ts +0 -68
- package/lib/toolbar/editor-highlight.d.ts +0 -21
- package/lib/toolbar/editor-image-upload-dialog.d.ts +0 -96
- package/lib/toolbar/editor-image-upload.d.ts +0 -71
- package/lib/toolbar/editor-inline-marks.d.ts +0 -30
- package/lib/toolbar/editor-link.d.ts +0 -78
- package/lib/toolbar/editor-list.d.ts +0 -67
- package/lib/toolbar/editor-table.d.ts +0 -133
- package/lib/toolbar/editor-text-color.d.ts +0 -21
- package/lib/toolbar/editor-toolbar-widget.d.ts +0 -19
- package/lib/toolbar/editor-toolbar.d.ts +0 -157
- package/lib/toolbar/editor-toolbar.defs.d.ts +0 -35
- package/lib/toolbar/editor-undo-redo.d.ts +0 -26
- package/lib/toolbar/editor-zoom.d.ts +0 -108
- package/lib/upload/editor-image-upload-coordinator.d.ts +0 -55
- package/malva-ui-editor.d.ts +0 -5
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"editor-block-handle.js","sourceRoot":"","sources":["../../../../../../libs/editor/src/lib/extensions/editor-block-handle.ts"],"names":[],"mappings":"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","sourcesContent":["import { Extension } from '@tiptap/core';\nimport type { Node as ProseMirrorNode } from '@tiptap/pm/model';\nimport type { EditorState } from '@tiptap/pm/state';\nimport { NodeSelection, Plugin, TextSelection } from '@tiptap/pm/state';\nimport type { EditorView } from '@tiptap/pm/view';\n\n/** A completed block move, reported so the host can announce it. */\nexport interface MlvEditorBlockMove {\n /** ProseMirror node type name of the moved block, untranslated. */\n readonly type: string;\n\n /** One-based position the block now occupies among the blocks counted by `total`. */\n readonly position: number;\n\n /**\n * Top-level block count of the document the move was computed against, i.e.\n * **before** the move — the same snapshot `position` is derived from. Reading\n * it after the move instead would announce schema-maintained artifacts the\n * user never authored: `trailingNode` appends an empty paragraph whenever the\n * last block is not a textblock, so moving a horizontal rule to the end would\n * otherwise report \"3 of 4\".\n */\n readonly total: number;\n}\n\n/** Host-supplied capabilities for the block drag handle. */\nexport interface MlvEditorBlockHandleOptions {\n /**\n * Container the floating handle is appended to. Must be the layer carrying the\n * editor zoom transform so the handle shares its coordinate space.\n */\n readonly mount: () => HTMLElement | null;\n\n /** Accessible label for the handle, read live so locale changes apply. */\n readonly label: () => string;\n\n /** Receives every completed move; the host formats and announces it. */\n readonly announceMove: (move: MlvEditorBlockMove) => void;\n\n /** Whether block moving is currently permitted; false while readonly or disabled. */\n readonly enabled: () => boolean;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n mlvEditorBlockHandle: {\n /**\n * Moves one top-level block. Both indices address the document as it stands\n * **before** the move, so moving index 0 to index 2 of three blocks yields\n * the order `[1, 2, 0]`.\n */\n moveBlock: (options: { from: number; to: number }) => ReturnType;\n\n /** Moves the top-level block containing the selection one position earlier. */\n moveBlockUp: () => ReturnType;\n\n /** Moves the top-level block containing the selection one position later. */\n moveBlockDown: () => ReturnType;\n };\n }\n}\n\n/** @internal Class of the floating drop indicator. */\nconst MLV_EDITOR_DROP_INDICATOR_CLASS = 'mlv-editor__drop-indicator';\n\n/** @internal Class of the off-screen wrapper handed to `setDragImage`. */\nconst MLV_EDITOR_DRAG_GHOST_CLASS = 'mlv-editor__drag-ghost';\n\n/**\n * @internal Marks the editor DOM while a block drag is in flight, so the\n * stylesheet — not this file — owns the partition's transition and its\n * reduced-motion fallback. JavaScript writes only the `transform` itself.\n */\nconst MLV_EDITOR_DRAGGING_CLASS = 'ProseMirror--block-dragging';\n\n/** @internal Marks the block currently on the cursor, dimmed in place. */\nconst MLV_EDITOR_DRAG_SOURCE_CLASS = 'mlv-editor__block--dragging';\n\n/** @internal Duration of the post-drop settle, matching `--mlv-duration-normal`. */\nconst MLV_EDITOR_SETTLE_DURATION = 200;\n\n/** @internal Sub-pixel movement not worth animating after a drop. */\nconst MLV_EDITOR_SETTLE_EPSILON = 0.5;\n\n/** @internal Document position where the given top-level child begins. */\nfunction childStart(doc: ProseMirrorNode, index: number): number {\n let position = 0;\n for (let i = 0; i < index; i += 1) {\n position += doc.child(i).nodeSize;\n }\n return position;\n}\n\n/**\n * @internal Document position `moveBlock({ from, to })` inserts at, expressed\n * against the document as it stands **before** the move.\n *\n * Shared by the command and the drop indicator so the line the user sees can\n * never point at a gap other than the one the drop actually uses.\n */\nfunction insertAnchor(doc: ProseMirrorNode, from: number, to: number): number {\n return to > from\n ? childStart(doc, to) + doc.child(to).nodeSize\n : childStart(doc, to);\n}\n\n/** @internal Reads the live scale of the mount layer instead of trusting a CSS variable. */\nfunction layerScale(mount: HTMLElement): number {\n const width = mount.offsetWidth;\n if (!width) return 1;\n const scaled = mount.getBoundingClientRect().width;\n return scaled > 0 ? scaled / width : 1;\n}\n\n/**\n * @internal A top-level block resolved from a pointer position.\n *\n * The coordinate space is the caller's: `blockAtPoint` produces viewport-space\n * boxes in scaled pixels, `snapshotBlocks` produces mount-relative boxes in the\n * layer's unscaled space. `dropTargetIndex` only compares a y against this\n * box's own midpoint, so it serves both — provided the caller passes a y from\n * the same space it took the box from.\n */\ninterface MlvEditorBlockHit {\n /** Top-level child index of the resolved block. */\n readonly index: number;\n\n /** Top edge of the block's rendered box. */\n readonly top: number;\n\n /**\n * Bottom edge of the same box. Read from the rect the producer already\n * measured, so deciding which of the block's two edges a drop belongs to\n * costs no second layout read.\n */\n readonly bottom: number;\n}\n\n/**\n * @internal Top-level child index for one rendered child of the editor DOM, or\n * null when that child is not a top-level node at all.\n *\n * Indexing `view.dom.children` positionally would not do: widget decorations\n * are rendered children that own no document node, so the two sequences do not\n * line up. This library alone puts three of them at the top level — the drop\n * indicator below, `MlvEditorUploadPlaceholder`'s pending image, and\n * StarterKit's gap cursor — and any future block-level decoration joins them.\n *\n * `posAtDOM` on its own does not discriminate either, which is the whole\n * difficulty: a widget anchored in a top-level gap maps to a perfectly valid\n * index — the one belonging to the block it sits beside. So the resolved index\n * is handed back to `nodeDOM`, and only the element ProseMirror actually\n * rendered *for* that child may claim it. Containment rather than identity,\n * because an outer node decoration wraps a node's own DOM in another element.\n */\nfunction topLevelIndexOfDom(view: EditorView, element: Element): number | null {\n let position: number;\n try {\n position = view.posAtDOM(element, 0);\n } catch {\n // `posAtDOM` throws for DOM the editor view does not own. A foreign child\n // must not take a pointer handler down with it.\n return null;\n }\n const doc = view.state.doc;\n const index = doc.resolve(position).index(0);\n if (index >= doc.childCount) return null;\n return element.contains(view.nodeDOM(childStart(doc, index))) ? index : null;\n}\n\n/**\n * @internal Top-level block the given viewport y falls on, or the nearest one\n * above it. Null for an empty document, or for a point the view cannot map.\n *\n * Resolves geometrically instead of through `EditorView.posAtCoords`, which\n * cannot serve this affordance at all. `.ProseMirror` is the\n * `max-inline-size: var(--mlv-editor-measure)` text column, so the gutter the\n * handle lives in is outside `view.dom`'s rect by construction — and\n * `posAtCoords` falls back to an `inRect(coords, view.dom.getBoundingClientRect())`\n * test and returns null for every point outside it, in a real browser as much\n * as under a test DOM.\n *\n * Rendered children lay out in document order, so the scan stops at the first\n * one starting below the pointer, costing one `getBoundingClientRect()` and\n * one index mapping per child down to the hovered one.\n *\n * Mapping inside the loop is what makes widget decorations skippable as a\n * category rather than by class name, and it is not free: `posAtDOM`,\n * `nodeDOM`, and `childStart` each walk linearly to the child they address, so\n * the scan down to index `k` is quadratic in `k` — measured at roughly 4x per\n * doubling, against 2x for the map-only-the-winner scan this replaced. That\n * one was abandoned because it could not tell a widget from a block, and\n * pairing a block's index with a widget's box drops the block on the wrong\n * side of its neighbour. Correctness first; the cost is only paid down to the\n * *hovered* child, so it is deep hovering in a long document that degrades.\n * Restoring the linear scan without losing the category skip means deferring\n * the mapping until a winner is picked and walking back over the few\n * consecutive widgets — the clamp above the first block is what makes that\n * more than a one-liner, so it is deliberately left as follow-up.\n */\nfunction blockAtPoint(\n view: EditorView,\n clientY: number,\n): MlvEditorBlockHit | null {\n const children = view.dom.children;\n let candidate: MlvEditorBlockHit | null = null;\n\n for (let i = 0; i < children.length; i += 1) {\n const element = children[i];\n // A widget decoration owns no top-level node, and its box is a sliver\n // rather than a block's. Letting one become the candidate would pair a\n // neighbouring block's index with the widget's geometry, so\n // `dropTargetIndex` would take that block's midpoint from the wrong box\n // and land the drop on the wrong side of it — silently, in one undo step.\n const index = topLevelIndexOfDom(view, element);\n if (index === null) continue;\n\n const rect = element.getBoundingClientRect();\n if (clientY < rect.top) {\n // Above the first block clamps to it; in the gap between two blocks the\n // preceding one was already recorded on the previous iteration.\n candidate ??= { index, top: rect.top, bottom: rect.bottom };\n break;\n }\n candidate = { index, top: rect.top, bottom: rect.bottom };\n if (clientY <= rect.bottom) break;\n }\n return candidate;\n}\n\n/**\n * @internal Pre-move `to` index for dropping the block at `from` onto `hit`,\n * or null when that drop would leave the document unchanged.\n *\n * `blockAtPoint` clamps to the nearest block and carries no before/after bias,\n * so the hovered block's own midpoint decides which of its two edges the\n * dragged block would land on. That yields one of the `childCount + 1` gaps,\n * which is then folded back onto `moveBlock`'s pre-move index convention:\n * `to` names the block the moved one ends up *after* when moving down and\n * *before* when moving up, so both gaps bordering the source are no-ops.\n */\nfunction dropTargetIndex(\n hit: MlvEditorBlockHit,\n clientY: number,\n from: number,\n): number | null {\n const gap = clientY < (hit.top + hit.bottom) / 2 ? hit.index : hit.index + 1;\n const to = gap <= from ? gap : gap - 1;\n return to === from ? null : to;\n}\n\n/**\n * @internal One top-level block measured into the drag snapshot: its box in the\n * mount's own unscaled space, paired with the element that rendered it.\n *\n * Carrying the element is what keeps everything after `dragstart` off\n * `topLevelIndexOfDom`. The partition has to decide, for every rendered child,\n * whether it sits at or after the insertion point; resolving that through the\n * index mapping per child would reintroduce the same quadratic walk the scan\n * pays, on every target change. Mapped once here, the rest is array work.\n */\ninterface MlvEditorBlockSlot extends MlvEditorBlockHit {\n /** The element ProseMirror rendered for this top-level child. */\n readonly element: HTMLElement;\n}\n\n/**\n * @internal Measures every top-level block once, in the mount's unscaled space.\n *\n * Taken at `dragstart` and read by everything downstream, which is a\n * correctness requirement rather than an optimisation. The partition applies\n * `transform` to blocks, and a transform *is* reflected in\n * `getBoundingClientRect()`. Resolving the target from live rects after moving\n * them would feed this plugin's own output back into its input: the gap opens,\n * the pointer is now over a different block, the target changes, the gap moves.\n * A snapshot taken before any transform breaks that loop.\n *\n * Mount-relative rather than viewport-relative so drag-autoscroll cannot\n * invalidate it — only the mount's own rect is re-read per event, one layout\n * read instead of one per block. Unscaled for the same reason the handle's\n * `top` is: a CSS length on a child of the zoom layer applies in that layer's\n * space, while `getBoundingClientRect()` reports scaled screen pixels.\n */\nfunction snapshotBlocks(\n view: EditorView,\n mount: HTMLElement,\n): MlvEditorBlockSlot[] {\n const scale = layerScale(mount);\n const mountTop = mount.getBoundingClientRect().top;\n const slots: MlvEditorBlockSlot[] = [];\n const children = view.dom.children;\n\n for (let i = 0; i < children.length; i += 1) {\n const element = children[i];\n // Same category check the hover scan uses: a widget decoration owns no\n // top-level node and must not occupy a slot, or the partition would shift\n // it as though it were a block.\n const index = topLevelIndexOfDom(view, element);\n if (index === null) continue;\n const rect = element.getBoundingClientRect();\n slots.push({\n index,\n top: (rect.top - mountTop) / scale,\n bottom: (rect.bottom - mountTop) / scale,\n element: element as HTMLElement,\n });\n }\n return slots;\n}\n\n/**\n * @internal Slot the given mount-space y falls on, or the nearest one above it.\n *\n * Reproduces `blockAtPoint`'s clamping exactly — above the first block resolves\n * to the first, a point in the gap between two blocks resolves to the\n * preceding one, below the last resolves to the last — but against a static\n * array, so it is a binary search rather than a scan that maps every child it\n * passes.\n */\nfunction slotAt(\n slots: readonly MlvEditorBlockSlot[],\n y: number,\n): MlvEditorBlockSlot | null {\n if (slots.length === 0) return null;\n if (y < slots[0].top) return slots[0];\n\n let low = 0;\n let high = slots.length - 1;\n while (low < high) {\n const middle = Math.ceil((low + high) / 2);\n if (slots[middle].top <= y) low = middle;\n else high = middle - 1;\n }\n return slots[low];\n}\n\n/**\n * @internal Mount-space y of the boundary the given gap sits on, where `gap`\n * counts the `slots.length + 1` positions a block can be inserted at.\n *\n * Deliberately the *pre-partition* boundary: the indicator is offset into the\n * opened space by half the gap in CSS, so the gap's size stays a single token\n * and this never has to resolve a rem into pixels.\n */\nfunction gapOffset(slots: readonly MlvEditorBlockSlot[], gap: number): number {\n if (gap <= 0) return slots[0].top;\n if (gap >= slots.length) return slots[slots.length - 1].bottom;\n return (slots[gap - 1].bottom + slots[gap].top) / 2;\n}\n\n/**\n * @internal Deep-clones an element with every computed style written inline.\n *\n * The clone is handed to `setDragImage` from `document.body`, outside every\n * `.mlv-editor`/`.ProseMirror` selector that styles it in place. Inlining the\n * resolved styles makes it self-contained, which is sturdier than rebuilding\n * an ancestor class chain that would have to track whichever selectors happen\n * to exist. Adapted from `@tiptap/extension-drag-handle`'s `cloneElement`.\n *\n * Note what this cannot carry: computed styles are used values, and an\n * ancestor `transform: scale()` never reaches them. The editor's zoom is\n * applied to the wrapper instead — see `createGhostElement`.\n */\nfunction cloneWithComputedStyles(source: HTMLElement): HTMLElement {\n const clone = source.cloneNode(true) as HTMLElement;\n const sources: HTMLElement[] = [\n source,\n ...source.querySelectorAll<HTMLElement>('*'),\n ];\n const targets: HTMLElement[] = [\n clone,\n ...clone.querySelectorAll<HTMLElement>('*'),\n ];\n\n sources.forEach((element, index) => {\n const target = targets[index];\n if (!target) return;\n const computed = getComputedStyle(element);\n let declarations = '';\n for (let i = 0; i < computed.length; i += 1) {\n declarations += `${computed[i]}:${computed.getPropertyValue(computed[i])};`;\n }\n target.style.cssText = declarations;\n });\n\n // The block's own margins would otherwise pad the drag image with empty\n // space, since the clone has no siblings to collapse against.\n clone.style.margin = '0';\n return clone;\n}\n\n/**\n * @internal Builds the off-screen element handed to `setDragImage`.\n *\n * `position: absolute; top: -10000px` keeps it rendered — which the drag image\n * requires — without ever being seen. `zoom` rather than `transform` carries\n * the editor's scale because it affects layout, so the wrapper's own box\n * reflects it before the browser rasterizes; a `transform` is honoured\n * inconsistently across engines for drag images.\n */\nfunction createGhostElement(source: HTMLElement, scale: number): HTMLElement {\n const wrapper = document.createElement('div');\n wrapper.className = MLV_EDITOR_DRAG_GHOST_CLASS;\n wrapper.setAttribute('aria-hidden', 'true');\n wrapper.style.position = 'absolute';\n wrapper.style.top = '-10000px';\n wrapper.style.insetInlineStart = '0';\n wrapper.style.inlineSize = `${source.offsetWidth}px`;\n if (scale !== 1) wrapper.style.setProperty('zoom', String(scale));\n wrapper.appendChild(cloneWithComputedStyles(source));\n document.body.appendChild(wrapper);\n return wrapper;\n}\n\n/**\n * @internal Whether the user asked for reduced motion.\n *\n * Guarded because jsdom implements no `matchMedia`; absent the query, motion\n * is allowed and the animation itself is separately guarded on `animate`.\n */\nfunction prefersReducedMotion(): boolean {\n return (\n typeof matchMedia === 'function' &&\n matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\n/** @internal Creates the single floating drop indicator element. */\nfunction createIndicatorElement(): HTMLElement {\n const element = document.createElement('div');\n element.className = MLV_EDITOR_DROP_INDICATOR_CLASS;\n element.setAttribute('aria-hidden', 'true');\n element.setAttribute('data-visible', 'false');\n return element;\n}\n\n/** @internal Creates the single floating handle element. */\nfunction createHandleElement(label: string): HTMLElement {\n const element = document.createElement('div');\n element.className = 'mlv-editor__block-handle';\n element.setAttribute('draggable', 'true');\n element.setAttribute('aria-hidden', 'true');\n element.setAttribute('data-visible', 'false');\n element.title = label;\n element.innerHTML =\n // Sized from `.mlv-editor__block-handle svg`; no intrinsic width/height\n // attributes, so the icon scales with the block's tokens.\n '<svg viewBox=\"0 0 24 24\" focusable=\"false\" aria-hidden=\"true\">' +\n '<circle cx=\"9\" cy=\"6\" r=\"1.5\"/><circle cx=\"15\" cy=\"6\" r=\"1.5\"/>' +\n '<circle cx=\"9\" cy=\"12\" r=\"1.5\"/><circle cx=\"15\" cy=\"12\" r=\"1.5\"/>' +\n '<circle cx=\"9\" cy=\"18\" r=\"1.5\"/><circle cx=\"15\" cy=\"18\" r=\"1.5\"/></svg>';\n return element;\n}\n\n/** @internal Top-level index containing the selection, or null for an empty document. */\nfunction topLevelIndexAtSelection(state: EditorState): number | null {\n if (state.doc.childCount === 0) return null;\n const index = state.selection.$from.index(0);\n return index < state.doc.childCount ? index : null;\n}\n\n/**\n * Tiptap extension supplying top-level block reordering.\n *\n * The pointer handle and the keyboard shortcuts both route through `moveBlock`,\n * so the two paths cannot drift apart. The handle itself is rendered by this\n * extension's ProseMirror plugin into the host-supplied mount container and is\n * never part of the document, so no serialized representation can contain it.\n */\nexport const MlvEditorBlockHandle =\n Extension.create<MlvEditorBlockHandleOptions>({\n name: 'mlvEditorBlockHandle',\n\n addOptions() {\n return {\n mount: () => null,\n label: () => 'Drag block',\n announceMove: () => undefined,\n enabled: () => true,\n };\n },\n\n addCommands() {\n return {\n moveBlock:\n ({ from, to }) =>\n ({ state, tr, dispatch }) => {\n if (!this.options.enabled()) return false;\n if (!Number.isInteger(from) || !Number.isInteger(to)) return false;\n\n const total = state.doc.childCount;\n if (from < 0 || from >= total) return false;\n if (to < 0 || to >= total) return false;\n if (from === to) return false;\n if (!dispatch) return true;\n\n const node = state.doc.child(from);\n const start = childStart(state.doc, from);\n const end = start + node.nodeSize;\n const anchor = insertAnchor(state.doc, from, to);\n\n tr.delete(start, end);\n const insertAt = tr.mapping.map(anchor);\n tr.insert(insertAt, node);\n // The selection must land *inside* the moved node so a following\n // moveBlockUp/Down keeps acting on it. An atom has no position\n // inside it — `insertAt + 1` is already past a leaf such as\n // horizontalRule, and TextSelection.near's forward bias would then\n // walk into the next block — so select the node itself instead.\n tr.setSelection(\n node.isAtom && NodeSelection.isSelectable(node)\n ? NodeSelection.create(tr.doc, insertAt)\n : TextSelection.near(\n tr.doc.resolve(Math.min(insertAt + 1, tr.doc.content.size)),\n ),\n );\n dispatch(tr);\n\n // Fires before the document actually changes: props `dispatch` is a\n // no-op and CommandManager runs the real `view.dispatch(tr)` only\n // after this command returns. A host callback therefore still sees\n // the pre-move `editor.state` and must rely on this payload alone.\n this.options.announceMove({\n type: node.type.name,\n position: to + 1,\n total,\n });\n return true;\n },\n\n moveBlockUp:\n () =>\n ({ state, commands }) => {\n const index = topLevelIndexAtSelection(state);\n return (\n index !== null &&\n index > 0 &&\n commands.moveBlock({ from: index, to: index - 1 })\n );\n },\n\n moveBlockDown:\n () =>\n ({ state, commands }) => {\n const index = topLevelIndexAtSelection(state);\n return (\n index !== null &&\n index < state.doc.childCount - 1 &&\n commands.moveBlock({ from: index, to: index + 1 })\n );\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n 'Alt-Shift-ArrowUp': () => this.editor.commands.moveBlockUp(),\n 'Alt-Shift-ArrowDown': () => this.editor.commands.moveBlockDown(),\n };\n },\n\n addProseMirrorPlugins() {\n const options = this.options;\n // The plugin view receives an `EditorView`, which carries no command\n // interface; the drop path has to reach `moveBlock` through Tiptap.\n const editor = this.editor;\n\n return [\n new Plugin({\n view: (view) => {\n const mount = options.mount();\n if (!mount) return { destroy: () => undefined };\n\n const handle = createHandleElement(options.label());\n mount.appendChild(handle);\n\n // The indicator lives beside the handle rather than inside the\n // document. As a `Decoration.widget` it could never move: a widget\n // at a new position is a *different* decoration, so ProseMirror\n // destroys and rebuilds its DOM on every change, and an element in\n // normal flow has no `top` to transition anyway. Out here it is\n // also further from the document than a decoration ever was — the\n // mount is a sibling of `view.dom`, so no serializer can reach it.\n const indicator = createIndicatorElement();\n mount.appendChild(indicator);\n\n const hide = () => handle.setAttribute('data-visible', 'false');\n\n const onMouseMove = (event: MouseEvent) => {\n if (!options.enabled()) return hide();\n const hit = blockAtPoint(view, event.clientY);\n if (!hit) return hide();\n\n // `getBoundingClientRect()` reports scaled screen pixels, but a\n // CSS `top` on a child of the scaled layer is applied in the\n // layer's own unscaled space. Convert once, deriving the scale\n // from the DOM rather than `--mlv-editor-zoom`, so the handle\n // stays correct if anything else ever transforms this layer.\n const scale = layerScale(mount);\n const mountTop = mount.getBoundingClientRect().top;\n handle.style.top = `${(hit.top - mountTop) / scale}px`;\n handle.dataset['index'] = String(hit.index);\n handle.title = options.label();\n handle.setAttribute('data-visible', 'true');\n };\n\n /** Top-level index being dragged, or null when no drag is active. */\n let source: number | null = null;\n\n /** The dimmed element the drag started from. */\n let sourceElement: HTMLElement | null = null;\n\n /** Geometry measured once at `dragstart`; empty while no drag runs. */\n let slots: MlvEditorBlockSlot[] = [];\n\n /** The off-screen element handed to `setDragImage`. */\n let ghost: HTMLElement | null = null;\n\n /** Gap the partition is currently opened at, or null when closed. */\n let gap: number | null = null;\n\n /** Converts a viewport y into the mount's own unscaled space. */\n const toMountSpace = (clientY: number): number =>\n (clientY - mount.getBoundingClientRect().top) / layerScale(mount);\n\n /**\n * Gap a resolved target index sits on. `dropTargetIndex` folds the\n * `slots.length + 1` gaps onto `moveBlock`'s pre-move convention,\n * where `to` names the block the moved one ends up after when\n * moving down; this is that fold inverted, so the previewed space\n * and the committed move come from one resolved index.\n */\n const gapForTarget = (to: number, from: number): number =>\n to <= from ? to : to + 1;\n\n /** Opens the partition at `next`, or closes it when null. */\n const setGap = (next: number | null) => {\n if (gap === next) return;\n gap = next;\n\n for (const slot of slots) {\n // The gap is a token rather than a number here, so the size\n // stays owned by the stylesheet.\n slot.element.style.transform =\n next !== null && slot.index >= next\n ? 'translateY(var(--mlv-editor-drop-gap))'\n : '';\n }\n\n if (next === null) {\n indicator.setAttribute('data-visible', 'false');\n return;\n }\n // The *pre-partition* boundary: the stylesheet offsets the line\n // into the opened space by half the gap, so this never has to\n // resolve the token into pixels.\n indicator.style.top = `${gapOffset(slots, next)}px`;\n indicator.setAttribute('data-visible', 'true');\n };\n\n const endDrag = () => {\n for (const slot of slots) slot.element.style.transform = '';\n indicator.setAttribute('data-visible', 'false');\n view.dom.classList.remove(MLV_EDITOR_DRAGGING_CLASS);\n sourceElement?.classList.remove(MLV_EDITOR_DRAG_SOURCE_CLASS);\n ghost?.remove();\n slots = [];\n gap = null;\n source = null;\n sourceElement = null;\n ghost = null;\n };\n\n /** Target index for the pointer, or null when the drop is a no-op. */\n const targetAt = (clientY: number): number | null => {\n if (source === null) return null;\n const y = toMountSpace(clientY);\n const slot = slotAt(slots, y);\n return slot === null ? null : dropTargetIndex(slot, y, source);\n };\n\n /**\n * FLIP the blocks the move displaced: ProseMirror has already\n * re-rendered them at their new positions, so each is offset back\n * to where it was and released. Read after `moveBlock` because the\n * DOM update is applied synchronously inside `dispatch`.\n *\n * Which block was where is derived from the move's own permutation\n * rather than by matching DOM elements against their old boxes.\n * `moveBlock` deletes the dragged node and reinserts it, so its\n * element is not the one that was measured — identity matching\n * would silently skip the one block the user actually dragged, and\n * leave every other block sliding around it.\n *\n * Only the span between the two indices moved, so the walk is\n * bounded by the distance dragged rather than by document length.\n *\n * Uses the Web Animations API rather than a transition: nothing has\n * to force a reflow between setting and clearing the offset, the\n * animation cleans itself up, and it never collides with the inline\n * `transform` the partition writes.\n */\n const settle = (\n tops: readonly number[],\n from: number,\n to: number,\n ) => {\n if (prefersReducedMotion()) return;\n // Pre-move index now occupying each post-move index.\n const order = tops.map((_, index) => index);\n order.splice(from, 1);\n order.splice(to, 0, from);\n\n const doc = view.state.doc;\n const scale = layerScale(mount);\n const mountTop = mount.getBoundingClientRect().top;\n const first = Math.min(from, to);\n const last = Math.max(from, to);\n\n for (let index = first; index <= last; index += 1) {\n const element = view.nodeDOM(childStart(doc, index));\n if (!(element instanceof HTMLElement)) continue;\n // jsdom implements no WAAPI, and neither did older engines.\n if (typeof element.animate !== 'function') return;\n const previous = tops[order[index]];\n if (previous === undefined) continue;\n const current =\n (element.getBoundingClientRect().top - mountTop) / scale;\n const delta = previous - current;\n if (Math.abs(delta) < MLV_EDITOR_SETTLE_EPSILON) continue;\n element.animate(\n [\n { transform: `translateY(${delta}px)` },\n { transform: 'translateY(0)' },\n ],\n {\n duration: MLV_EDITOR_SETTLE_DURATION,\n easing: 'cubic-bezier(0.2, 0, 0, 1)',\n },\n );\n }\n };\n\n const onDragStart = (event: DragEvent) => {\n // `data-index` is absent until the first successful hover, and a\n // revoked `enabled()` must not start a drag that could never be\n // applied. Either way, refuse the drag outright.\n const attribute = handle.dataset['index'];\n const index = attribute === undefined ? NaN : Number(attribute);\n if (!options.enabled() || !Number.isInteger(index)) {\n event.preventDefault();\n return;\n }\n\n const measured = snapshotBlocks(view, mount);\n const slot = measured.find(\n (candidate) => candidate.index === index,\n );\n // The hovered index outliving its block means the snapshot and\n // `data-index` disagree; refusing is the same answer as a drag\n // that never hovered.\n if (!slot) {\n event.preventDefault();\n return;\n }\n\n slots = measured;\n source = index;\n\n // Firefox refuses to begin a drag whose dataTransfer carries no\n // data. The payload stays empty on purpose: the reorder replays\n // `source` through `moveBlock`, never a parsed slice, so this\n // drag cannot reparent into a list or a table cell and cannot be\n // dropped into a different editor.\n event.dataTransfer?.setData('text/plain', '');\n if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move';\n\n // A `dragstart` that arrives while one is already recorded would\n // otherwise strand the previous drag image on `document.body`,\n // where nothing else reaches it.\n ghost?.remove();\n // Cloned *before* the source is dimmed: the clone carries\n // resolved computed styles, so dimming first would bake the\n // reduced opacity into the drag image.\n ghost = createGhostElement(slot.element, layerScale(mount));\n event.dataTransfer?.setDragImage(\n ghost,\n getComputedStyle(view.dom).direction === 'rtl'\n ? ghost.offsetWidth\n : 0,\n 0,\n );\n\n sourceElement = slot.element;\n sourceElement.classList.add(MLV_EDITOR_DRAG_SOURCE_CLASS);\n view.dom.classList.add(MLV_EDITOR_DRAGGING_CLASS);\n };\n\n const onDragOver = (event: DragEvent) => {\n if (source === null) return;\n // Claimed in the capture phase on the mount, so ProseMirror's own\n // `view.dom` drop handler never sees the event and cannot fall\n // back to its native slice path.\n event.stopPropagation();\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n\n const to = targetAt(event.clientY);\n setGap(to === null ? null : gapForTarget(to, source));\n };\n\n /**\n * Whether a `dragleave` is the pointer leaving the mount outright,\n * rather than crossing between two elements inside it — the event\n * fires for both, and only the first should retract the indicator.\n */\n const leavesMount = (event: DragEvent): boolean => {\n const entered = event.relatedTarget;\n // Where the browser populates it, `relatedTarget` names the\n // element being entered; one inside the mount means the drag\n // never left.\n if (entered instanceof Node) return !mount.contains(entered);\n // Chromium leaves it null on every drag event, so fall back to\n // the pointer itself. Leaving the window reports (0, 0) in some\n // browsers, which may read as inside; the drag's own `dragend`\n // still clears the indicator there, exactly as it did before.\n const rect = mount.getBoundingClientRect();\n return (\n event.clientX < rect.left ||\n event.clientX > rect.right ||\n event.clientY < rect.top ||\n event.clientY > rect.bottom\n );\n };\n\n const onDragLeave = (event: DragEvent) => {\n // Only the preview goes — the partition closes and the line\n // retracts. The drag itself is still in flight, and re-entering\n // the editor must resolve a target again rather than leave the\n // user dragging something that can no longer be dropped.\n if (source !== null && leavesMount(event)) setGap(null);\n };\n\n const onDrop = (event: DragEvent) => {\n if (source === null) return;\n event.stopPropagation();\n event.preventDefault();\n\n const from = source;\n // Resolved from the drop's own coordinates rather than the last\n // `dragover`, so the release position always wins.\n const to = targetAt(event.clientY);\n // Captured before `endDrag` discards the snapshot. These are the\n // pre-partition tops, which is exactly the FLIP's \"before\": the\n // partition's transforms are cleared by `endDrag` in the same\n // turn, so nothing the user saw shifted is measured as movement.\n const tops = slots.map((slot) => slot.top);\n\n endDrag();\n if (to === null) return;\n editor.commands.moveBlock({ from, to });\n settle(tops, from, to);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && source !== null) endDrag();\n };\n\n mount.addEventListener('mousemove', onMouseMove);\n mount.addEventListener('mouseleave', hide);\n handle.addEventListener('dragstart', onDragStart);\n handle.addEventListener('dragend', endDrag);\n // On the mount rather than `view.dom`: `.ProseMirror` is the text\n // column, so a drag that never leaves the gutter the handle lives\n // in would otherwise produce no `dragover` and no droppable target.\n mount.addEventListener('dragover', onDragOver, true);\n mount.addEventListener('dragleave', onDragLeave, true);\n mount.addEventListener('drop', onDrop, true);\n // Escape aborts a native drag in a real browser, which fires\n // `dragend` anyway; this keeps the cancellation deterministic and\n // independent of that.\n document.addEventListener('keydown', onKeyDown);\n\n return {\n // `enabled()` is checked on every pointer move too, but a host\n // can revoke it *between* moves. Disabling the editor puts\n // `pointer-events: none` on the surface containing the mount, so\n // no further mousemove or mouseleave can ever arrive to retract\n // a handle that was left visible. This runs on every state\n // update, which is what a `disabled`/`readonly` flip produces.\n update: (updated, previous) => {\n // `source` is a pre-move top-level index, exactly like the\n // anchor `apply` drops on `docChanged`, and it is the one that\n // decides *which* block moves. An insertion before it makes it\n // name a different block, so the indicator would repaint at the\n // gap the user aimed at while the drop silently moved the wrong\n // block — one undo step, no error. Abort rather than map: a\n // source block that was itself deleted has no mapped index, and\n // aborting matches what already happens to the anchor.\n //\n // Identity, not `Node.eq`: ProseMirror only replaces\n // `state.doc` when a step is applied — a meta- or\n // selection-only transaction carries the same reference — so\n // this is exactly `docChanged` at O(1), where a structural\n // compare would walk the whole document on every keystroke.\n if (previous.doc !== updated.state.doc && source !== null) {\n endDrag();\n }\n\n if (options.enabled()) return;\n hide();\n // Retracts the preview and drops the in-flight source, so\n // releasing the button after the revocation cannot reorder\n // anything. Previously the line went through `decorations`,\n // which read `enabled()` itself; a mount-owned element has to\n // be told.\n if (source !== null) endDrag();\n },\n destroy: () => {\n mount.removeEventListener('mousemove', onMouseMove);\n mount.removeEventListener('mouseleave', hide);\n handle.removeEventListener('dragstart', onDragStart);\n handle.removeEventListener('dragend', endDrag);\n mount.removeEventListener('dragover', onDragOver, true);\n mount.removeEventListener('dragleave', onDragLeave, true);\n mount.removeEventListener('drop', onDrop, true);\n document.removeEventListener('keydown', onKeyDown);\n handle.remove();\n indicator.remove();\n // A drag interrupted by teardown leaves its drag image on\n // `document.body`, outside everything else this removes.\n ghost?.remove();\n },\n };\n },\n }),\n ];\n },\n });\n"]}
|
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
import { Extension } from '@tiptap/core';
|
|
2
|
-
import { FileHandlePlugin, } from '@tiptap/extension-file-handler';
|
|
3
|
-
import Image from '@tiptap/extension-image';
|
|
4
|
-
import { TaskItem, TaskList } from '@tiptap/extension-list';
|
|
5
|
-
import TextAlign from '@tiptap/extension-text-align';
|
|
6
|
-
import { Color } from '@tiptap/extension-text-style';
|
|
7
|
-
import { CharacterCount, Placeholder } from '@tiptap/extensions';
|
|
8
|
-
import { Markdown } from '@tiptap/markdown';
|
|
9
|
-
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
10
|
-
import { MlvEditorBlockHandle, } from './editor-block-handle';
|
|
11
|
-
import { MlvEditorUploadPlaceholder } from './editor-upload-placeholder';
|
|
12
|
-
import { createMarkdownCompatibleHighlight, createMarkdownCompatibleStarterKit, createMarkdownCompatibleTableKit, createMarkdownCompatibleTextStyle, } from './editor-markdown-compatibility';
|
|
13
|
-
export { MlvEditorUploadPlaceholder, } from './editor-upload-placeholder';
|
|
14
|
-
/**
|
|
15
|
-
* Public Malva wrapper around Tiptap's official free file handling extension.
|
|
16
|
-
*
|
|
17
|
-
* The upstream plugin intentionally consumes accepted file-only paste/drop
|
|
18
|
-
* events. This companion plugin inserts a simultaneous `text/plain` payload
|
|
19
|
-
* first, then delegates the file interaction exactly once to the upstream
|
|
20
|
-
* `FileHandlePlugin`. It remains inert for either interaction when the
|
|
21
|
-
* corresponding callback is not configured, so custom presets can safely
|
|
22
|
-
* include it before they opt into file handling.
|
|
23
|
-
*/
|
|
24
|
-
export const MlvEditorFileHandler = Extension.create({
|
|
25
|
-
name: 'fileHandler',
|
|
26
|
-
addOptions() {
|
|
27
|
-
return {
|
|
28
|
-
onPaste: undefined,
|
|
29
|
-
onDrop: undefined,
|
|
30
|
-
allowedMimeTypes: undefined,
|
|
31
|
-
consumePasteEvent: false,
|
|
32
|
-
};
|
|
33
|
-
},
|
|
34
|
-
addProseMirrorPlugins() {
|
|
35
|
-
const onPaste = this.options.onPaste;
|
|
36
|
-
const onDrop = this.options.onDrop;
|
|
37
|
-
let preservedDrop;
|
|
38
|
-
const acceptedFiles = (files) => {
|
|
39
|
-
const candidates = Array.from(files);
|
|
40
|
-
return this.options.allowedMimeTypes
|
|
41
|
-
? candidates.filter((file) => this.options.allowedMimeTypes?.includes(file.type))
|
|
42
|
-
: candidates;
|
|
43
|
-
};
|
|
44
|
-
const preservePlainText = new Plugin({
|
|
45
|
-
key: new PluginKey('mlvFileHandlerPlainText'),
|
|
46
|
-
props: {
|
|
47
|
-
handlePaste: (view, event) => {
|
|
48
|
-
const clipboard = event.clipboardData;
|
|
49
|
-
if (!onPaste ||
|
|
50
|
-
!clipboard?.files.length ||
|
|
51
|
-
acceptedFiles(clipboard.files).length === 0 ||
|
|
52
|
-
clipboard.getData('text/html').length > 0) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
const plainText = clipboard.getData('text/plain');
|
|
56
|
-
if (!plainText)
|
|
57
|
-
return false;
|
|
58
|
-
view.dispatch(view.state.tr.insertText(plainText));
|
|
59
|
-
return false;
|
|
60
|
-
},
|
|
61
|
-
handleDrop: (view, event) => {
|
|
62
|
-
const transfer = event.dataTransfer;
|
|
63
|
-
if (!onDrop ||
|
|
64
|
-
!transfer?.files.length ||
|
|
65
|
-
transfer.types.includes('application/x-prosemirror-slice') ||
|
|
66
|
-
acceptedFiles(transfer.files).length === 0) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
const plainText = transfer.getData('text/plain');
|
|
70
|
-
if (!plainText)
|
|
71
|
-
return false;
|
|
72
|
-
const position = view.posAtCoords({
|
|
73
|
-
left: event.clientX,
|
|
74
|
-
top: event.clientY,
|
|
75
|
-
})?.pos;
|
|
76
|
-
if (position === undefined)
|
|
77
|
-
return false;
|
|
78
|
-
view.dispatch(view.state.tr.insertText(plainText, position));
|
|
79
|
-
preservedDrop = { position, textLength: plainText.length };
|
|
80
|
-
return false;
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
return [
|
|
85
|
-
preservePlainText,
|
|
86
|
-
FileHandlePlugin({
|
|
87
|
-
key: new PluginKey(this.name),
|
|
88
|
-
editor: this.editor,
|
|
89
|
-
allowedMimeTypes: this.options.allowedMimeTypes,
|
|
90
|
-
consumePasteEvent: this.options.consumePasteEvent,
|
|
91
|
-
onPaste,
|
|
92
|
-
onDrop: onDrop
|
|
93
|
-
? (editor, files, position) => {
|
|
94
|
-
const adjustedPosition = preservedDrop?.position === position
|
|
95
|
-
? position + preservedDrop.textLength
|
|
96
|
-
: position;
|
|
97
|
-
preservedDrop = undefined;
|
|
98
|
-
onDrop(editor, files, adjustedPosition);
|
|
99
|
-
}
|
|
100
|
-
: undefined,
|
|
101
|
-
}),
|
|
102
|
-
];
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
/**
|
|
106
|
-
* @internal Smallest size a resized image may be dragged to, in CSS pixels.
|
|
107
|
-
*
|
|
108
|
-
* Supplied explicitly rather than left to Tiptap's own defaults, which cannot
|
|
109
|
-
* be reached from here: the Image extension always forwards
|
|
110
|
-
* `min: { width: minWidth, height: minHeight }` to `ResizableNodeView`, and
|
|
111
|
-
* that object literal is truthy even when both members are `undefined`, so the
|
|
112
|
-
* node view spreads them over its `{ width: 8, height: 8 }` defaults and erases
|
|
113
|
-
* them. Every drag then computes `Math.max(undefined, n)` — `NaN` — and
|
|
114
|
-
* `style.width = 'NaNpx'` is rejected by the CSSOM without an error, so the
|
|
115
|
-
* image silently never resizes. The value matches Tiptap's own default.
|
|
116
|
-
*/
|
|
117
|
-
const MLV_EDITOR_IMAGE_MIN_SIZE = 8;
|
|
118
|
-
/**
|
|
119
|
-
* Counts words using every Unicode whitespace separator as a boundary.
|
|
120
|
-
*
|
|
121
|
-
* @param text Plain editor text.
|
|
122
|
-
* @returns The deterministic number of non-empty words.
|
|
123
|
-
*/
|
|
124
|
-
export function countMlvEditorWords(text) {
|
|
125
|
-
const normalized = text.trim();
|
|
126
|
-
return normalized ? normalized.split(/\s+/u).filter(Boolean).length : 0;
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* Normalizes a character limit to a positive finite integer.
|
|
130
|
-
*
|
|
131
|
-
* @param limit Candidate limit.
|
|
132
|
-
* @returns The usable limit, or `null` for unlimited content.
|
|
133
|
-
*/
|
|
134
|
-
export function normalizeMlvEditorCharacterLimit(limit) {
|
|
135
|
-
return typeof limit === 'number' &&
|
|
136
|
-
Number.isFinite(limit) &&
|
|
137
|
-
Number.isInteger(limit) &&
|
|
138
|
-
limit > 0
|
|
139
|
-
? limit
|
|
140
|
-
: null;
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Creates the core formatting extensions used by the default Malva preset.
|
|
144
|
-
*
|
|
145
|
-
* @param options Optional text-alignment configuration.
|
|
146
|
-
* @returns Fresh Tiptap extension instances safe to compose into one editor.
|
|
147
|
-
*/
|
|
148
|
-
export function mlvEditorFormattingExtensions(options = {}) {
|
|
149
|
-
return [
|
|
150
|
-
createMarkdownCompatibleStarterKit({
|
|
151
|
-
link: {
|
|
152
|
-
openOnClick: false,
|
|
153
|
-
HTMLAttributes: { target: null, rel: null },
|
|
154
|
-
},
|
|
155
|
-
}),
|
|
156
|
-
createMarkdownCompatibleTextStyle(),
|
|
157
|
-
Color.configure({}),
|
|
158
|
-
createMarkdownCompatibleHighlight(),
|
|
159
|
-
TextAlign.configure({
|
|
160
|
-
types: [...(options.textAlignTypes ?? ['heading', 'paragraph'])],
|
|
161
|
-
}),
|
|
162
|
-
];
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Creates task-list extensions. Bullet and ordered lists remain supplied by StarterKit.
|
|
166
|
-
*
|
|
167
|
-
* @param options Optional task-item nesting configuration.
|
|
168
|
-
* @returns Fresh task-list extension instances.
|
|
169
|
-
*/
|
|
170
|
-
export function mlvEditorListExtensions(options = {}) {
|
|
171
|
-
return [
|
|
172
|
-
TaskList.configure({}),
|
|
173
|
-
TaskItem.configure({ nested: options.nestedTaskItems ?? false }),
|
|
174
|
-
];
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Creates the free Tiptap table kit.
|
|
178
|
-
*
|
|
179
|
-
* @param options Optional table resize configuration.
|
|
180
|
-
* @returns A fresh configured table-kit extension.
|
|
181
|
-
*/
|
|
182
|
-
export function mlvEditorTableExtensions(options = {}) {
|
|
183
|
-
return [
|
|
184
|
-
createMarkdownCompatibleTableKit({
|
|
185
|
-
table: { resizable: options.resizable ?? true },
|
|
186
|
-
}),
|
|
187
|
-
];
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Creates the image and paste/drop file-handler extensions.
|
|
191
|
-
*
|
|
192
|
-
* @param options Optional image resize, MIME-type, and file callback configuration.
|
|
193
|
-
* @returns Fresh image and file-handler extension instances.
|
|
194
|
-
*/
|
|
195
|
-
export function mlvEditorImageExtensions(options = {}) {
|
|
196
|
-
const allowedMimeTypes = options.allowedMimeTypes
|
|
197
|
-
? [...options.allowedMimeTypes]
|
|
198
|
-
: undefined;
|
|
199
|
-
if (allowedMimeTypes) {
|
|
200
|
-
Object.defineProperty(allowedMimeTypes, 'includes', {
|
|
201
|
-
configurable: true,
|
|
202
|
-
value: (mimeType) => {
|
|
203
|
-
if (options.fileHandlingEnabled?.() === false)
|
|
204
|
-
return false;
|
|
205
|
-
const normalizedMimeType = mimeType.trim().toLowerCase();
|
|
206
|
-
const acceptedByPattern = allowedMimeTypes.some((pattern) => {
|
|
207
|
-
const normalizedPattern = pattern.trim().toLowerCase();
|
|
208
|
-
return normalizedPattern.endsWith('/*')
|
|
209
|
-
? normalizedMimeType.startsWith(normalizedPattern.slice(0, -1))
|
|
210
|
-
: normalizedMimeType === normalizedPattern;
|
|
211
|
-
});
|
|
212
|
-
return (acceptedByPattern &&
|
|
213
|
-
(options.acceptsMimeType?.(normalizedMimeType) ?? true));
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
const fileHandlerOptions = options.onFiles
|
|
218
|
-
? {
|
|
219
|
-
allowedMimeTypes,
|
|
220
|
-
consumePasteEvent: false,
|
|
221
|
-
onPaste: (editor, files, pasteContent) => {
|
|
222
|
-
options.onFiles?.({
|
|
223
|
-
editor,
|
|
224
|
-
files,
|
|
225
|
-
source: 'paste',
|
|
226
|
-
...(pasteContent === undefined ? {} : { pasteContent }),
|
|
227
|
-
});
|
|
228
|
-
},
|
|
229
|
-
onDrop: (editor, files, position) => {
|
|
230
|
-
options.onFiles?.({ editor, files, source: 'drop', position });
|
|
231
|
-
},
|
|
232
|
-
}
|
|
233
|
-
: { allowedMimeTypes };
|
|
234
|
-
return [
|
|
235
|
-
Image.configure({
|
|
236
|
-
resize: {
|
|
237
|
-
enabled: options.resizable ?? true,
|
|
238
|
-
// Both must be finite; see MLV_EDITOR_IMAGE_MIN_SIZE for why omitting
|
|
239
|
-
// them does not fall back to Tiptap's defaults but breaks resizing.
|
|
240
|
-
minWidth: Number.isFinite(options.minWidth)
|
|
241
|
-
? options.minWidth
|
|
242
|
-
: MLV_EDITOR_IMAGE_MIN_SIZE,
|
|
243
|
-
minHeight: Number.isFinite(options.minHeight)
|
|
244
|
-
? options.minHeight
|
|
245
|
-
: MLV_EDITOR_IMAGE_MIN_SIZE,
|
|
246
|
-
},
|
|
247
|
-
}),
|
|
248
|
-
MlvEditorFileHandler.configure(fileHandlerOptions),
|
|
249
|
-
];
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Creates placeholder and character-count utility extensions.
|
|
253
|
-
*
|
|
254
|
-
* @param options Optional placeholder text and character limit.
|
|
255
|
-
* @returns Fresh utility extension instances.
|
|
256
|
-
*/
|
|
257
|
-
export function mlvEditorUtilityExtensions(options = {}) {
|
|
258
|
-
return [
|
|
259
|
-
Placeholder.configure({
|
|
260
|
-
placeholder: options.placeholder ?? 'Write something…',
|
|
261
|
-
}),
|
|
262
|
-
CharacterCount.configure({
|
|
263
|
-
limit: normalizeMlvEditorCharacterLimit(options.characterLimit),
|
|
264
|
-
wordCounter: countMlvEditorWords,
|
|
265
|
-
}),
|
|
266
|
-
];
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Creates the block drag-handle extension.
|
|
270
|
-
*
|
|
271
|
-
* Every option is host-supplied. Omitting them yields an inert handle that never
|
|
272
|
-
* mounts, which is what a bare `mlvEditorDefaultExtensions()` call outside the
|
|
273
|
-
* `MlvEditor` shell should produce.
|
|
274
|
-
*
|
|
275
|
-
* @param options Optional host capabilities for mounting, labelling, and announcing.
|
|
276
|
-
* @returns A fresh configured block-handle extension.
|
|
277
|
-
*/
|
|
278
|
-
export function mlvEditorBlockHandleExtensions(options = {}) {
|
|
279
|
-
return [MlvEditorBlockHandle.configure({ ...options })];
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Creates the official beta Tiptap Markdown extension.
|
|
283
|
-
*
|
|
284
|
-
* @param options Optional Markdown indentation configuration.
|
|
285
|
-
* @returns A fresh Markdown extension instance.
|
|
286
|
-
*/
|
|
287
|
-
export function mlvEditorMarkdownExtensions(options = {}) {
|
|
288
|
-
return [
|
|
289
|
-
Markdown.configure(options.indentation === undefined
|
|
290
|
-
? {}
|
|
291
|
-
: {
|
|
292
|
-
indentation: {
|
|
293
|
-
...options.indentation,
|
|
294
|
-
},
|
|
295
|
-
}),
|
|
296
|
-
];
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Creates Malva's complete default extension preset.
|
|
300
|
-
*
|
|
301
|
-
* Every call creates new arrays and extension instances. Passing a custom extension
|
|
302
|
-
* list to the editor shell intentionally replaces this preset instead of extending it.
|
|
303
|
-
*
|
|
304
|
-
* @param options Optional preset configuration.
|
|
305
|
-
* @returns A duplicate-free extension set for one new Tiptap editor instance.
|
|
306
|
-
*/
|
|
307
|
-
export function mlvEditorDefaultExtensions(options = {}) {
|
|
308
|
-
return [
|
|
309
|
-
...mlvEditorFormattingExtensions(options),
|
|
310
|
-
...mlvEditorListExtensions(options),
|
|
311
|
-
...mlvEditorTableExtensions(options),
|
|
312
|
-
...mlvEditorImageExtensions(options),
|
|
313
|
-
...mlvEditorUtilityExtensions(options),
|
|
314
|
-
MlvEditorUploadPlaceholder.configure(),
|
|
315
|
-
...mlvEditorBlockHandleExtensions(options.blockHandle ?? {}),
|
|
316
|
-
...(options.format === 'markdown'
|
|
317
|
-
? mlvEditorMarkdownExtensions(options)
|
|
318
|
-
: []),
|
|
319
|
-
];
|
|
320
|
-
}
|
|
321
|
-
//# sourceMappingURL=editor-extensions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"editor-extensions.js","sourceRoot":"","sources":["../../../../../../libs/editor/src/lib/extensions/editor-extensions.ts"],"names":[],"mappings":"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","sourcesContent":["import { Extension, type Editor, type Extensions } from '@tiptap/core';\nimport {\n FileHandlePlugin,\n type FileHandlerOptions,\n} from '@tiptap/extension-file-handler';\nimport Image from '@tiptap/extension-image';\nimport { TaskItem, TaskList } from '@tiptap/extension-list';\nimport TextAlign from '@tiptap/extension-text-align';\nimport { Color } from '@tiptap/extension-text-style';\nimport { CharacterCount, Placeholder } from '@tiptap/extensions';\nimport { Markdown } from '@tiptap/markdown';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport type {\n MlvEditorFormat,\n MlvEditorImageUploadSource,\n} from '../editor.types';\nimport {\n MlvEditorBlockHandle,\n type MlvEditorBlockHandleOptions,\n} from './editor-block-handle';\nimport { MlvEditorUploadPlaceholder } from './editor-upload-placeholder';\nimport {\n createMarkdownCompatibleHighlight,\n createMarkdownCompatibleStarterKit,\n createMarkdownCompatibleTableKit,\n createMarkdownCompatibleTextStyle,\n} from './editor-markdown-compatibility';\n\nexport {\n MlvEditorUploadPlaceholder,\n type MlvEditorInsertUploadPlaceholderOptions,\n type MlvEditorRemoveUploadPlaceholderOptions,\n type MlvEditorUpdateUploadPlaceholderOptions,\n type MlvEditorUploadPlaceholderItem,\n type MlvEditorUploadPlaceholderStorage,\n} from './editor-upload-placeholder';\n\n/**\n * Public Malva wrapper around Tiptap's official free file handling extension.\n *\n * The upstream plugin intentionally consumes accepted file-only paste/drop\n * events. This companion plugin inserts a simultaneous `text/plain` payload\n * first, then delegates the file interaction exactly once to the upstream\n * `FileHandlePlugin`. It remains inert for either interaction when the\n * corresponding callback is not configured, so custom presets can safely\n * include it before they opt into file handling.\n */\nexport const MlvEditorFileHandler = Extension.create<FileHandlerOptions>({\n name: 'fileHandler',\n\n addOptions() {\n return {\n onPaste: undefined,\n onDrop: undefined,\n allowedMimeTypes: undefined,\n consumePasteEvent: false,\n };\n },\n\n addProseMirrorPlugins() {\n const onPaste = this.options.onPaste;\n const onDrop = this.options.onDrop;\n let preservedDrop:\n | { readonly position: number; readonly textLength: number }\n | undefined;\n const acceptedFiles = (files: FileList): File[] => {\n const candidates = Array.from(files);\n return this.options.allowedMimeTypes\n ? candidates.filter((file) =>\n this.options.allowedMimeTypes?.includes(file.type),\n )\n : candidates;\n };\n\n const preservePlainText = new Plugin({\n key: new PluginKey('mlvFileHandlerPlainText'),\n props: {\n handlePaste: (view, event) => {\n const clipboard = event.clipboardData;\n if (\n !onPaste ||\n !clipboard?.files.length ||\n acceptedFiles(clipboard.files).length === 0 ||\n clipboard.getData('text/html').length > 0\n ) {\n return false;\n }\n const plainText = clipboard.getData('text/plain');\n if (!plainText) return false;\n view.dispatch(view.state.tr.insertText(plainText));\n return false;\n },\n handleDrop: (view, event) => {\n const transfer = event.dataTransfer;\n if (\n !onDrop ||\n !transfer?.files.length ||\n transfer.types.includes('application/x-prosemirror-slice') ||\n acceptedFiles(transfer.files).length === 0\n ) {\n return false;\n }\n const plainText = transfer.getData('text/plain');\n if (!plainText) return false;\n const position = view.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n })?.pos;\n if (position === undefined) return false;\n view.dispatch(view.state.tr.insertText(plainText, position));\n preservedDrop = { position, textLength: plainText.length };\n return false;\n },\n },\n });\n\n return [\n preservePlainText,\n FileHandlePlugin({\n key: new PluginKey(this.name),\n editor: this.editor,\n allowedMimeTypes: this.options.allowedMimeTypes,\n consumePasteEvent: this.options.consumePasteEvent,\n onPaste,\n onDrop: onDrop\n ? (editor, files, position) => {\n const adjustedPosition =\n preservedDrop?.position === position\n ? position + preservedDrop.textLength\n : position;\n preservedDrop = undefined;\n onDrop(editor, files, adjustedPosition);\n }\n : undefined,\n }),\n ];\n },\n});\n\n/** Options used to configure formatting extensions in a Malva editor preset. */\nexport interface MlvEditorFormattingExtensionOptions {\n /** Node types that accept text alignment. Defaults to headings and paragraphs. */\n readonly textAlignTypes?: readonly string[];\n}\n\n/** Options used to configure task-list support. */\nexport interface MlvEditorListExtensionOptions {\n /** Whether task-list items may be nested. Defaults to false. */\n readonly nestedTaskItems?: boolean;\n}\n\n/** Options used to configure table support. */\nexport interface MlvEditorTableExtensionOptions {\n /** Whether users can resize table columns. Defaults to true. */\n readonly resizable?: boolean;\n}\n\n/** A pasted or dropped file event passed from Tiptap to the editor upload coordinator. */\nexport interface MlvEditorFileHandlerEvent {\n /** Editor that received the file event. */\n readonly editor: Editor;\n\n /** Files selected by the browser paste or drop event. */\n readonly files: readonly File[];\n\n /** Origin of the image files. */\n readonly source: Exclude<MlvEditorImageUploadSource, 'button'>;\n\n /** Document position at which files were dropped, when applicable. */\n readonly position?: number;\n\n /** HTML clipboard content accompanying pasted files, when available. */\n readonly pasteContent?: string;\n}\n\n/**\n * @internal Smallest size a resized image may be dragged to, in CSS pixels.\n *\n * Supplied explicitly rather than left to Tiptap's own defaults, which cannot\n * be reached from here: the Image extension always forwards\n * `min: { width: minWidth, height: minHeight }` to `ResizableNodeView`, and\n * that object literal is truthy even when both members are `undefined`, so the\n * node view spreads them over its `{ width: 8, height: 8 }` defaults and erases\n * them. Every drag then computes `Math.max(undefined, n)` — `NaN` — and\n * `style.width = 'NaNpx'` is rejected by the CSSOM without an error, so the\n * image silently never resizes. The value matches Tiptap's own default.\n */\nconst MLV_EDITOR_IMAGE_MIN_SIZE = 8;\n\n/** Options used to configure the image and file-handler extensions. */\nexport interface MlvEditorImageExtensionOptions {\n /** Whether image node resizing is enabled. Defaults to true. */\n readonly resizable?: boolean;\n\n /**\n * Smallest width, in CSS pixels, a resized image may be dragged to.\n * Defaults to 8. Must be a finite number: an undefined minimum leaves\n * Tiptap's resize arithmetic producing `NaN` and silently disables resizing.\n */\n readonly minWidth?: number;\n\n /** Smallest height, in CSS pixels, a resized image may be dragged to. Defaults to 8. */\n readonly minHeight?: number;\n\n /** MIME types forwarded to Tiptap's file handler. */\n readonly allowedMimeTypes?: readonly string[];\n\n /** Runtime guard applied before Tiptap consumes a matching file event. */\n readonly fileHandlingEnabled?: () => boolean;\n\n /** Optional runtime MIME decision used for editor-scoped upload options. */\n readonly acceptsMimeType?: (mimeType: string) => boolean;\n\n /** Callback invoked for pasted and dropped files. */\n readonly onFiles?: (event: MlvEditorFileHandlerEvent) => void;\n}\n\n/** Options used to configure editor utility extensions. */\nexport interface MlvEditorUtilityExtensionOptions {\n /** Placeholder text shown for an empty editor. */\n readonly placeholder?: string;\n\n /** Maximum character count, or null for no limit. */\n readonly characterLimit?: number | null;\n}\n\n/**\n * Counts words using every Unicode whitespace separator as a boundary.\n *\n * @param text Plain editor text.\n * @returns The deterministic number of non-empty words.\n */\nexport function countMlvEditorWords(text: string): number {\n const normalized = text.trim();\n return normalized ? normalized.split(/\\s+/u).filter(Boolean).length : 0;\n}\n\n/**\n * Normalizes a character limit to a positive finite integer.\n *\n * @param limit Candidate limit.\n * @returns The usable limit, or `null` for unlimited content.\n */\nexport function normalizeMlvEditorCharacterLimit(\n limit: number | null | undefined,\n): number | null {\n return typeof limit === 'number' &&\n Number.isFinite(limit) &&\n Number.isInteger(limit) &&\n limit > 0\n ? limit\n : null;\n}\n\n/** Options used to configure the beta Markdown extension. */\nexport interface MlvEditorMarkdownExtensionOptions {\n /** Indentation used by Markdown lists and code blocks. */\n readonly indentation?: {\n /** Use spaces or tabs for indentation. */\n readonly style?: 'space' | 'tab';\n\n /** Number of indentation characters per nesting level. */\n readonly size?: number;\n };\n}\n\n/** Aggregate options accepted by the standard Malva editor extension preset. */\nexport interface MlvEditorDefaultExtensionOptions\n extends MlvEditorFormattingExtensionOptions,\n MlvEditorListExtensionOptions,\n MlvEditorTableExtensionOptions,\n MlvEditorImageExtensionOptions,\n MlvEditorUtilityExtensionOptions,\n MlvEditorMarkdownExtensionOptions {\n /** Serialization format; Markdown support is added only for `markdown`. */\n readonly format?: MlvEditorFormat;\n\n /** Host capabilities for the block drag handle. */\n readonly blockHandle?: Partial<MlvEditorBlockHandleOptions>;\n}\n\n/**\n * Creates the core formatting extensions used by the default Malva preset.\n *\n * @param options Optional text-alignment configuration.\n * @returns Fresh Tiptap extension instances safe to compose into one editor.\n */\nexport function mlvEditorFormattingExtensions(\n options: MlvEditorFormattingExtensionOptions = {},\n): Extensions {\n return [\n createMarkdownCompatibleStarterKit({\n link: {\n openOnClick: false,\n HTMLAttributes: { target: null, rel: null },\n },\n }),\n createMarkdownCompatibleTextStyle(),\n Color.configure({}),\n createMarkdownCompatibleHighlight(),\n TextAlign.configure({\n types: [...(options.textAlignTypes ?? ['heading', 'paragraph'])],\n }),\n ];\n}\n\n/**\n * Creates task-list extensions. Bullet and ordered lists remain supplied by StarterKit.\n *\n * @param options Optional task-item nesting configuration.\n * @returns Fresh task-list extension instances.\n */\nexport function mlvEditorListExtensions(\n options: MlvEditorListExtensionOptions = {},\n): Extensions {\n return [\n TaskList.configure({}),\n TaskItem.configure({ nested: options.nestedTaskItems ?? false }),\n ];\n}\n\n/**\n * Creates the free Tiptap table kit.\n *\n * @param options Optional table resize configuration.\n * @returns A fresh configured table-kit extension.\n */\nexport function mlvEditorTableExtensions(\n options: MlvEditorTableExtensionOptions = {},\n): Extensions {\n return [\n createMarkdownCompatibleTableKit({\n table: { resizable: options.resizable ?? true },\n }),\n ];\n}\n\n/**\n * Creates the image and paste/drop file-handler extensions.\n *\n * @param options Optional image resize, MIME-type, and file callback configuration.\n * @returns Fresh image and file-handler extension instances.\n */\nexport function mlvEditorImageExtensions(\n options: MlvEditorImageExtensionOptions = {},\n): Extensions {\n const allowedMimeTypes = options.allowedMimeTypes\n ? [...options.allowedMimeTypes]\n : undefined;\n if (allowedMimeTypes) {\n Object.defineProperty(allowedMimeTypes, 'includes', {\n configurable: true,\n value: (mimeType: string): boolean => {\n if (options.fileHandlingEnabled?.() === false) return false;\n const normalizedMimeType = mimeType.trim().toLowerCase();\n const acceptedByPattern = allowedMimeTypes.some((pattern) => {\n const normalizedPattern = pattern.trim().toLowerCase();\n return normalizedPattern.endsWith('/*')\n ? normalizedMimeType.startsWith(normalizedPattern.slice(0, -1))\n : normalizedMimeType === normalizedPattern;\n });\n return (\n acceptedByPattern &&\n (options.acceptsMimeType?.(normalizedMimeType) ?? true)\n );\n },\n });\n }\n const fileHandlerOptions = options.onFiles\n ? {\n allowedMimeTypes,\n consumePasteEvent: false,\n onPaste: (editor: Editor, files: File[], pasteContent?: string) => {\n options.onFiles?.({\n editor,\n files,\n source: 'paste',\n ...(pasteContent === undefined ? {} : { pasteContent }),\n });\n },\n onDrop: (editor: Editor, files: File[], position: number) => {\n options.onFiles?.({ editor, files, source: 'drop', position });\n },\n }\n : { allowedMimeTypes };\n\n return [\n Image.configure({\n resize: {\n enabled: options.resizable ?? true,\n // Both must be finite; see MLV_EDITOR_IMAGE_MIN_SIZE for why omitting\n // them does not fall back to Tiptap's defaults but breaks resizing.\n minWidth: Number.isFinite(options.minWidth)\n ? (options.minWidth as number)\n : MLV_EDITOR_IMAGE_MIN_SIZE,\n minHeight: Number.isFinite(options.minHeight)\n ? (options.minHeight as number)\n : MLV_EDITOR_IMAGE_MIN_SIZE,\n },\n }),\n MlvEditorFileHandler.configure(fileHandlerOptions),\n ];\n}\n\n/**\n * Creates placeholder and character-count utility extensions.\n *\n * @param options Optional placeholder text and character limit.\n * @returns Fresh utility extension instances.\n */\nexport function mlvEditorUtilityExtensions(\n options: MlvEditorUtilityExtensionOptions = {},\n): Extensions {\n return [\n Placeholder.configure({\n placeholder: options.placeholder ?? 'Write something…',\n }),\n CharacterCount.configure({\n limit: normalizeMlvEditorCharacterLimit(options.characterLimit),\n wordCounter: countMlvEditorWords,\n }),\n ];\n}\n\n/**\n * Creates the block drag-handle extension.\n *\n * Every option is host-supplied. Omitting them yields an inert handle that never\n * mounts, which is what a bare `mlvEditorDefaultExtensions()` call outside the\n * `MlvEditor` shell should produce.\n *\n * @param options Optional host capabilities for mounting, labelling, and announcing.\n * @returns A fresh configured block-handle extension.\n */\nexport function mlvEditorBlockHandleExtensions(\n options: Partial<MlvEditorBlockHandleOptions> = {},\n): Extensions {\n return [MlvEditorBlockHandle.configure({ ...options })];\n}\n\n/**\n * Creates the official beta Tiptap Markdown extension.\n *\n * @param options Optional Markdown indentation configuration.\n * @returns A fresh Markdown extension instance.\n */\nexport function mlvEditorMarkdownExtensions(\n options: MlvEditorMarkdownExtensionOptions = {},\n): Extensions {\n return [\n Markdown.configure(\n options.indentation === undefined\n ? {}\n : {\n indentation: {\n ...options.indentation,\n },\n },\n ),\n ];\n}\n\n/**\n * Creates Malva's complete default extension preset.\n *\n * Every call creates new arrays and extension instances. Passing a custom extension\n * list to the editor shell intentionally replaces this preset instead of extending it.\n *\n * @param options Optional preset configuration.\n * @returns A duplicate-free extension set for one new Tiptap editor instance.\n */\nexport function mlvEditorDefaultExtensions(\n options: MlvEditorDefaultExtensionOptions = {},\n): Extensions {\n return [\n ...mlvEditorFormattingExtensions(options),\n ...mlvEditorListExtensions(options),\n ...mlvEditorTableExtensions(options),\n ...mlvEditorImageExtensions(options),\n ...mlvEditorUtilityExtensions(options),\n MlvEditorUploadPlaceholder.configure(),\n ...mlvEditorBlockHandleExtensions(options.blockHandle ?? {}),\n ...(options.format === 'markdown'\n ? mlvEditorMarkdownExtensions(options)\n : []),\n ];\n}\n"]}
|