@cocoar/vue-markdown-editor 2.9.0 → 2.10.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,6 +65,69 @@ const value = ref('# Hello\n\nStart typing **markdown**.');
65
65
  | `placeholder` | `string` | `''` | Markdown hint shown while empty. Overlay-only — never written to `modelValue` |
66
66
  | `toolbarMode` | `'floating' \| 'fixed' \| 'both'` | `'floating'` | Toolbar layout |
67
67
  | `toolbarPosition` | `'left' \| 'right'` | `'left'` | Sidebar position when `toolbarMode` is `'fixed'` or `'both'` |
68
+ | `flavor` | `'commonmark' \| 'gfm' \| 'cocoar' \| { gfm?, textColor? }` | `'cocoar'` | Portability contract — hard-enforces which features can be authored (see [Flavors](#flavors-portability)) |
69
+ | `uploadImage` | `(file: File) => Promise<{ url: string; alt?: string }>` | _undefined_ | Enables paste / drag-drop image upload (see [Images](#images)) |
70
+ | `pickImage` | `(ctx: ImagePickContext) => void` | _undefined_ | Override the Insert Image button with your own asset picker (see [Custom image source](#custom-image-source-pickimage)) |
71
+
72
+ ## Flavors (portability)
73
+
74
+ The `flavor` prop is a portability contract — it picks which features the editor offers and **hard-enforces** them (only the matching plugins are registered, so non-flavor constructs can't be typed or pasted; they degrade to plain text).
75
+
76
+ | Flavor | Adds on top of CommonMark | Renders in |
77
+ |---|---|---|
78
+ | `'commonmark'` | _(nothing — the portable floor)_ | any Markdown renderer (incl. minimal SwiftUI) |
79
+ | `'gfm'` | tables, task lists, strikethrough | GFM-capable renderers |
80
+ | `'cocoar'` _(default)_ | inline text color (non-portable HTML) | the Cocoar viewer / your own renderer |
81
+
82
+ ```vue
83
+ <CoarMarkdownEditor v-model="value" flavor="commonmark" />
84
+ <!-- or fine control -->
85
+ <CoarMarkdownEditor v-model="value" :flavor="{ gfm: true, textColor: false }" />
86
+ ```
87
+
88
+ Pick the flavor that matches your strictest downstream renderer (e.g. a native SwiftUI Markdown view) and authors can't produce content it won't render. `flavor` is the hard format contract; the `tools` whitelist is soft toolbar curation within it. To change `flavor` on a live editor, re-key it (`:key="flavor"`) so the plugin set re-registers.
89
+
90
+ ## Images
91
+
92
+ Images round-trip as standard Markdown — `![alt](url "title")`. Three ways to add one:
93
+
94
+ - **Insert by URL** — the **Insert Image** sidebar button opens a dialog for `url` / `alt` / `title`. Like the table/code-block buttons it lives in the sidebar, so use `toolbar-mode="fixed"` or `"both"`.
95
+ - **Paste** an image from the clipboard (e.g. a screenshot).
96
+ - **Drag & drop** an image file into the writing area.
97
+
98
+ Paste and drop require an `upload-image` callback — it receives the `File`, stores it, and resolves with the resulting `url`. A spinner placeholder shows at the insertion point until it resolves, then is replaced by the image. Without the callback, image files fall through to the browser's default handling.
99
+
100
+ ```vue
101
+ <CoarMarkdownEditor v-model="value" toolbar-mode="both" :upload-image="uploadImage" />
102
+
103
+ <script setup lang="ts">
104
+ async function uploadImage(file: File) {
105
+ const url = await myAssetService.upload(file)
106
+ return { url, alt: file.name }
107
+ }
108
+ </script>
109
+ ```
110
+
111
+ ### Custom image source (`pickImage`)
112
+
113
+ Wire the **Insert Image** button to your own asset library / gallery with `pickImage`. When set it **replaces** the URL dialog — clicking the button calls it with a context bound to the cursor: `insertImage(...)` plus `selectedText` (a default for `alt`). Open your own modal and call `ctx.insertImage(...)` for each chosen image (it can stay open and insert several). The editor keeps all ProseMirror handling, so you never touch the selection.
114
+
115
+ ```vue
116
+ <CoarMarkdownEditor v-model="value" toolbar-mode="both" :pick-image="openGallery" />
117
+
118
+ <script setup lang="ts">
119
+ function openGallery(ctx) {
120
+ myGalleryModal.open({
121
+ defaultAlt: ctx.selectedText,
122
+ onPick: (asset) => ctx.insertImage({ url: asset.url, alt: asset.title }),
123
+ })
124
+ }
125
+ </script>
126
+ ```
127
+
128
+ `pickImage` (button) and `uploadImage` (paste / drop) are orthogonal and compose.
129
+
130
+ > Resize / alignment / captions aren't part of standard Markdown and aren't supported yet — a richer image block is planned as a separate slice.
68
131
 
69
132
  ## Events
70
133
 
@@ -1,11 +1,14 @@
1
1
  import { PropType } from 'vue';
2
+ import { CoarMarkdownFlavorInput } from './flavor';
3
+ import { ImageUploader } from './image/imageUpload';
4
+ import { ImagePicker } from './image/pickImage';
2
5
  export type CoarMarkdownEditorToolbarMode = 'floating' | 'fixed' | 'both';
3
6
  export type CoarMarkdownEditorToolbarPosition = 'left' | 'right' | 'top' | 'bottom';
4
7
  /**
5
8
  * Toolbar tool identifiers — pass an array of these to the `tools` prop to
6
9
  * restrict which buttons are shown. When `tools` is undefined, all are shown.
7
10
  */
8
- export type CoarMarkdownEditorTool = 'bold' | 'italic' | 'strikethrough' | 'inlineCode' | 'textColor' | 'headings' | 'bulletList' | 'orderedList' | 'taskList' | 'indent' | 'outdent' | 'blockquote' | 'horizontalRule' | 'codeBlock' | 'table' | 'tableOps' | 'clearFormatting' | 'undo' | 'redo';
11
+ export type CoarMarkdownEditorTool = 'bold' | 'italic' | 'strikethrough' | 'inlineCode' | 'textColor' | 'headings' | 'bulletList' | 'orderedList' | 'taskList' | 'indent' | 'outdent' | 'blockquote' | 'horizontalRule' | 'codeBlock' | 'table' | 'tableOps' | 'image' | 'clearFormatting' | 'undo' | 'redo';
9
12
  /** Canonical list of all toolbar tools — exported so consumers can build
10
13
  * custom subsets (e.g. `tools: COAR_MARKDOWN_EDITOR_ALL_TOOLS.filter(...)`). */
11
14
  export declare const COAR_MARKDOWN_EDITOR_ALL_TOOLS: readonly CoarMarkdownEditorTool[];
@@ -42,6 +45,40 @@ export interface CoarMarkdownEditorProps {
42
45
  * does not influence button order).
43
46
  */
44
47
  tools?: CoarMarkdownEditorTool[];
48
+ /**
49
+ * Markdown **flavor** — the portability contract, hard-enforced. Picks which
50
+ * features are available: the editor only registers the matching plugins (so
51
+ * non-flavor constructs can't be typed/pasted — they degrade to plain text)
52
+ * and hides their toolbar buttons.
53
+ *
54
+ * - `'commonmark'` — portable floor: headings, bold/italic, lists, links,
55
+ * images, code, blockquote, hr. Renders in any Markdown renderer.
56
+ * - `'gfm'` — + tables, task lists, strikethrough (GFM).
57
+ * - `'cocoar'` (default) — + inline text color (non-portable raw HTML).
58
+ *
59
+ * Or pass a partial capability object `{ gfm?, textColor? }` (unspecified =
60
+ * off). Defaults to `'cocoar'` so existing editors are unchanged. Use the
61
+ * separate `tools` prop for soft toolbar curation within a flavor.
62
+ */
63
+ flavor?: CoarMarkdownFlavorInput;
64
+ /**
65
+ * Enables pasting and dragging image files into the editor. The callback
66
+ * receives the dropped/pasted `File`, stores it wherever the consumer wants
67
+ * (CDN, asset service, data-URL, …) and resolves with the resulting `url`
68
+ * (plus optional `alt`). A spinner placeholder is shown until it resolves,
69
+ * then replaced by a standard Markdown image. When omitted, image files fall
70
+ * through to the browser's default handling.
71
+ */
72
+ uploadImage?: ImageUploader;
73
+ /**
74
+ * Override the **Insert Image** toolbar button. When set, clicking it calls
75
+ * this callback (instead of the built-in URL dialog) with an
76
+ * `insertImage(...)` function bound to the cursor position plus the selected
77
+ * text. Open your own asset / gallery modal and call `ctx.insertImage(...)`.
78
+ * Pairs naturally with `uploadImage` (paste / drop). Requires a sidebar
79
+ * toolbar (`toolbarMode` `'fixed'` or `'both'`), like the other insert buttons.
80
+ */
81
+ pickImage?: ImagePicker;
45
82
  }
46
83
  declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
47
84
  modelValue: {
@@ -92,6 +129,18 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
92
129
  type: PropType<CoarMarkdownEditorTool[]>;
93
130
  default: undefined;
94
131
  };
132
+ flavor: {
133
+ type: PropType<CoarMarkdownFlavorInput>;
134
+ default: undefined;
135
+ };
136
+ uploadImage: {
137
+ type: PropType<ImageUploader | undefined>;
138
+ default: undefined;
139
+ };
140
+ pickImage: {
141
+ type: PropType<ImagePicker | undefined>;
142
+ default: undefined;
143
+ };
95
144
  }>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
96
145
  [key: string]: any;
97
146
  }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, "update:modelValue"[], "update:modelValue", import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
@@ -143,6 +192,18 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
143
192
  type: PropType<CoarMarkdownEditorTool[]>;
144
193
  default: undefined;
145
194
  };
195
+ flavor: {
196
+ type: PropType<CoarMarkdownFlavorInput>;
197
+ default: undefined;
198
+ };
199
+ uploadImage: {
200
+ type: PropType<ImageUploader | undefined>;
201
+ default: undefined;
202
+ };
203
+ pickImage: {
204
+ type: PropType<ImagePicker | undefined>;
205
+ default: undefined;
206
+ };
146
207
  }>> & Readonly<{
147
208
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
148
209
  }>, {
@@ -157,7 +218,10 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
157
218
  toolbarMode: CoarMarkdownEditorToolbarMode;
158
219
  toolbarPosition: CoarMarkdownEditorToolbarPosition;
159
220
  tools: CoarMarkdownEditorTool[];
221
+ flavor: CoarMarkdownFlavorInput;
160
222
  sourceToggle: boolean;
223
+ uploadImage: ImageUploader | undefined;
224
+ pickImage: ImagePicker | undefined;
161
225
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
162
226
  export default _default;
163
227
  //# sourceMappingURL=CoarMarkdownEditor.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CoarMarkdownEditor.vue.d.ts","sourceRoot":"","sources":["../src/CoarMarkdownEditor.vue"],"names":[],"mappings":"AA0lDA,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,KAAK,CAAC;AAoCb,MAAM,MAAM,6BAA6B,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAC1E,MAAM,MAAM,iCAAiC,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEpF;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAC9B,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,YAAY,GAClD,WAAW,GACX,UAAU,GACV,YAAY,GAAG,aAAa,GAAG,UAAU,GACzC,QAAQ,GAAG,SAAS,GACpB,YAAY,GAAG,gBAAgB,GAC/B,WAAW,GAAG,OAAO,GAAG,UAAU,GAClC,iBAAiB,GACjB,MAAM,GAAG,MAAM,CAAC;AAEpB;iFACiF;AACjF,eAAO,MAAM,8BAA8B,EAAE,SAAS,sBAAsB,EAU3E,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yFAAyF;IACzF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,6BAA6B,CAAC;IAC5C,eAAe,CAAC,EAAE,iCAAiC,CAAC;IACpD;;;;OAIG;IACH,KAAK,CAAC,EAAE,sBAAsB,EAAE,CAAC;CAClC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgnCkC,QAAQ,CAAC,6BAA6B,CAAC;;;;cACnC,QAAQ,CAAC,iCAAiC,CAAC;;;;cACtD,QAAQ,CAAC,sBAAsB,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAF3B,QAAQ,CAAC,6BAA6B,CAAC;;;;cACnC,QAAQ,CAAC,iCAAiC,CAAC;;;;cACtD,QAAQ,CAAC,sBAAsB,EAAE,CAAC;;;;;;;;;;;;;;;;;;;AAd9D,wBAsDG"}
1
+ {"version":3,"file":"CoarMarkdownEditor.vue.d.ts","sourceRoot":"","sources":["../src/CoarMarkdownEditor.vue"],"names":[],"mappings":"AA43DA,OAAO,EAGL,KAAK,QAAQ,EACd,MAAM,KAAK,CAAC;AASb,OAAO,EAAuB,KAAK,uBAAuB,EAAiC,MAAM,UAAU,CAAC;AAS5G,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAuBrD,MAAM,MAAM,6BAA6B,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAC1E,MAAM,MAAM,iCAAiC,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEpF;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAC9B,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,YAAY,GAClD,WAAW,GACX,UAAU,GACV,YAAY,GAAG,aAAa,GAAG,UAAU,GACzC,QAAQ,GAAG,SAAS,GACpB,YAAY,GAAG,gBAAgB,GAC/B,WAAW,GAAG,OAAO,GAAG,UAAU,GAClC,OAAO,GACP,iBAAiB,GACjB,MAAM,GAAG,MAAM,CAAC;AAEpB;iFACiF;AACjF,eAAO,MAAM,8BAA8B,EAAE,SAAS,sBAAsB,EAW3E,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yFAAyF;IACzF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,6BAA6B,CAAC;IAC5C,eAAe,CAAC,EAAE,iCAAiC,CAAC;IACpD;;;;OAIG;IACH,KAAK,CAAC,EAAE,sBAAsB,EAAE,CAAC;IACjC;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,uBAAuB,CAAC;IACjC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,WAAW,CAAC;CACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAy0CkC,QAAQ,CAAC,6BAA6B,CAAC;;;;cACnC,QAAQ,CAAC,iCAAiC,CAAC;;;;cACtD,QAAQ,CAAC,sBAAsB,EAAE,CAAC;;;;cACtB,QAAQ,CAAC,uBAAuB,CAAC;;;;cACpC,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;;;;cACrC,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cALjC,QAAQ,CAAC,6BAA6B,CAAC;;;;cACnC,QAAQ,CAAC,iCAAiC,CAAC;;;;cACtD,QAAQ,CAAC,sBAAsB,EAAE,CAAC;;;;cACtB,QAAQ,CAAC,uBAAuB,CAAC;;;;cACpC,QAAQ,CAAC,aAAa,GAAG,SAAS,CAAC;;;;cACrC,QAAQ,CAAC,WAAW,GAAG,SAAS,CAAC;;;;;;;;;;;;;;;;;;;;;;AAjBpE,wBA4DG"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Markdown **flavor** — the portability contract, enforced at authoring time.
3
+ *
4
+ * Tellify (and any consumer with a strict downstream renderer, e.g. a native
5
+ * SwiftUI markdown view) needs a guarantee that authored content only uses
6
+ * constructs the target renderer understands. The `flavor` picks a capability
7
+ * set; the editor then **hard-enforces** it — it only registers the matching
8
+ * Milkdown plugins (so non-flavor constructs can't be typed or pasted, they
9
+ * degrade to plain text) AND hides the matching toolbar buttons.
10
+ *
11
+ * The two cleanly-enforceable axes map to real renderer tiers:
12
+ * - `gfm` — GFM tables + task lists + strikethrough (one Milkdown bundle)
13
+ * - `textColor` — Cocoar inline color spans (`<span style="color">`), which are
14
+ * raw HTML and therefore **not portable** (they degrade to
15
+ * plain text in a CommonMark/GFM renderer).
16
+ *
17
+ * CommonMark basics (headings, bold/italic, lists, links, images, code,
18
+ * blockquote, hr) are always on — they are the portable floor.
19
+ *
20
+ * For finer toolbar curation *within* a flavor (e.g. keep GFM parsing but hide
21
+ * the table button), use the separate `tools` whitelist — that is soft UI
22
+ * curation, this is the hard format contract.
23
+ */
24
+ /** Named flavor presets, from most portable to richest. */
25
+ export type CoarMarkdownFlavor = 'commonmark' | 'gfm' | 'cocoar';
26
+ /** The hard-enforceable capability axes. Each is independently on/off. */
27
+ export interface CoarMarkdownCapabilities {
28
+ /** GFM tables + task lists + strikethrough. Portable in GFM-capable renderers. */
29
+ gfm: boolean;
30
+ /** Cocoar inline text color. NOT portable (raw HTML; degrades to plain text). */
31
+ textColor: boolean;
32
+ }
33
+ /**
34
+ * The `flavor` prop accepts a preset name OR a partial capability object.
35
+ * In object form, unspecified capabilities are **off** (opt-in) — `{}` is
36
+ * therefore equivalent to `'commonmark'`, `{ gfm: true }` to `'gfm'`.
37
+ */
38
+ export type CoarMarkdownFlavorInput = CoarMarkdownFlavor | Partial<CoarMarkdownCapabilities>;
39
+ /**
40
+ * Resolve a flavor input to a concrete capability set.
41
+ *
42
+ * - `undefined` → `'cocoar'` (everything on — preserves the pre-flavor default,
43
+ * so existing consumers are unaffected).
44
+ * - a preset name → its capability set.
45
+ * - a partial object → each unspecified capability defaults to `false` (opt-in).
46
+ */
47
+ export declare function resolveCapabilities(flavor: CoarMarkdownFlavorInput | undefined): CoarMarkdownCapabilities;
48
+ //# sourceMappingURL=flavor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flavor.d.ts","sourceRoot":"","sources":["../src/flavor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,2DAA2D;AAC3D,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEjE,0EAA0E;AAC1E,MAAM,WAAW,wBAAwB;IACvC,kFAAkF;IAClF,GAAG,EAAE,OAAO,CAAC;IACb,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,kBAAkB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAQ7F;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAAG,wBAAwB,CAIzG"}
@@ -0,0 +1,17 @@
1
+ export interface ImageInsertResult {
2
+ url: string;
3
+ alt: string;
4
+ title: string;
5
+ }
6
+ type __VLS_Props = {
7
+ /** Injected by CoarDialogShell — resolves the dialog. */
8
+ close: (result?: ImageInsertResult) => void;
9
+ initialUrl?: string;
10
+ initialAlt?: string;
11
+ initialTitle?: string;
12
+ };
13
+ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
14
+ urlField: HTMLDivElement;
15
+ }, HTMLDivElement>;
16
+ export default _default;
17
+ //# sourceMappingURL=ImageInsertDialog.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImageInsertDialog.vue.d.ts","sourceRoot":"","sources":["../../src/image/ImageInsertDialog.vue"],"names":[],"mappings":"AAyGA,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,KAAK,WAAW,GAAG;IACjB,yDAAyD;IACzD,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;;;;AA0MF,wBAQG"}
@@ -0,0 +1,16 @@
1
+ /** Resolves to the stored image's URL (and optional alt text). */
2
+ export type ImageUploader = (file: File) => Promise<{
3
+ url: string;
4
+ alt?: string;
5
+ }>;
6
+ export interface ImageUploadOptions {
7
+ /** Read the current uploader lazily so a reactive prop can change at runtime. */
8
+ getUploader: () => ImageUploader | undefined;
9
+ /** Called when an upload rejects. Defaults to `console.error`. */
10
+ onError?: (error: unknown, file: File) => void;
11
+ }
12
+ /** Extract image files from a clipboard/drag data-transfer, if any. Exported
13
+ * for unit testing — the paste/drop handlers gate on its result. */
14
+ export declare function imageFilesFrom(data: DataTransfer | null): File[];
15
+ export declare function imageUpload(options: ImageUploadOptions): import('@milkdown/utils').$Prose;
16
+ //# sourceMappingURL=imageUpload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imageUpload.d.ts","sourceRoot":"","sources":["../../src/image/imageUpload.ts"],"names":[],"mappings":"AAyBA,kEAAkE;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEnF,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,WAAW,EAAE,MAAM,aAAa,GAAG,SAAS,CAAC;IAC7C,kEAAkE;IAClE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChD;AA2BD;qEACqE;AACrE,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,EAAE,CAGhE;AA2CD,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,oCAiDtD"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Types for the `pickImage` extension hook.
3
+ *
4
+ * When a consumer passes a `pickImage` callback to `<CoarMarkdownEditor>`, the
5
+ * toolbar's **Insert Image** button calls it instead of opening the built-in
6
+ * URL dialog. The callback receives an {@link ImagePickContext} — an
7
+ * `insertImage` function already bound to the editor's stored cursor position,
8
+ * plus the text that was selected when the button was clicked (a sensible
9
+ * default for `alt`). The consumer typically opens its own asset/gallery modal
10
+ * and calls `ctx.insertImage(...)` for each chosen image.
11
+ *
12
+ * The editor keeps ownership of the actual insertion (cursor retention,
13
+ * Markdown round-trip), so the consumer never touches ProseMirror.
14
+ */
15
+ /** A Markdown image to insert: `![alt](url "title")`. */
16
+ export interface ImageDescriptor {
17
+ url: string;
18
+ alt?: string;
19
+ title?: string;
20
+ }
21
+ export interface ImagePickContext {
22
+ /**
23
+ * Insert an image at the position the cursor was in when **Insert Image**
24
+ * was clicked. Safe to call multiple times (e.g. when the user selects
25
+ * several gallery images before closing the modal) — each call inserts at
26
+ * the current cursor, which advances past the previous insertion.
27
+ */
28
+ insertImage: (image: ImageDescriptor) => void;
29
+ /**
30
+ * Text selected in the editor when the picker was invoked. Empty string if
31
+ * the selection was collapsed. Useful as a default `alt` value.
32
+ */
33
+ selectedText: string;
34
+ }
35
+ /**
36
+ * Consumer-supplied image picker. Invoked when the **Insert Image** toolbar
37
+ * button is clicked (replacing the built-in URL dialog). Open your own UI,
38
+ * then call `context.insertImage(...)`. There is no return value — insertion
39
+ * happens through the context, so the picker can be async, stay open, and
40
+ * insert more than once.
41
+ */
42
+ export type ImagePicker = (context: ImagePickContext) => void;
43
+ //# sourceMappingURL=pickImage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pickImage.d.ts","sourceRoot":"","sources":["../../src/image/pickImage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,WAAW,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC9C;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC"}
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- .coar-md-code-host{border-radius:var(--coar-radius-s);border:1px solid var(--coar-code-block-border,var(--coar-border-neutral));background:var(--coar-code-block-bg,var(--coar-background-neutral-secondary));margin:.75em 0;position:relative;overflow:hidden}.coar-md-code-host--editing{border-color:var(--coar-background-accent-primary)}.coar-md-code-render{position:relative}.coar-md-code-edit-btn{color:var(--coar-text-neutral-secondary);background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);cursor:pointer;opacity:0;z-index:1;align-items:center;gap:.25rem;padding:.25rem .5rem;font-size:.75rem;font-weight:500;transition:opacity .12s ease-out;display:inline-flex;position:absolute;top:.5rem;right:.5rem}.coar-md-code-render:hover .coar-md-code-edit-btn,.coar-md-code-edit-btn:focus-visible{opacity:1}.coar-md-code-edit-btn:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-code-lang-row{align-items:center;gap:var(--coar-spacing-s);padding:var(--coar-spacing-s) .75rem;border-bottom:1px solid var(--coar-code-block-border,var(--coar-border-neutral));background:var(--coar-code-block-header-bg,var(--coar-background-neutral-tertiary));min-height:36px;display:flex}.coar-md-code-lang-select{--coar-select-bg:transparent;--coar-select-border:transparent}.coar-md-code-content{padding:var(--coar-spacing-s) .75rem;font-family:var(--coar-font-family-code,"Cascadia Code", Consolas, Monaco, monospace);font-size:var(--coar-component-s-font-size,.85em);line-height:1.5}.coar-md-code-content>pre{white-space:pre-wrap;font-family:inherit;font-size:inherit;background:0 0;margin:0;padding:0}.coar-md-code-content>pre>code{white-space:inherit;outline:none;font-family:inherit;display:block}.coar-md-color-picker{gap:var(--coar-spacing-s);width:224px;padding:var(--coar-spacing-s);background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-xl);box-shadow:var(--coar-shadow-m,0 4px 12px #0000001f);flex-direction:column;display:flex}.coar-md-color-grid{grid-template-columns:repeat(5,1fr);gap:4px;display:grid}.coar-md-color-swatch{aspect-ratio:1;border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);background:var(--coar-md-swatch,transparent);width:100%;color:var(--coar-text-neutral-secondary);cursor:pointer;justify-content:center;align-items:center;padding:0;transition:transform 80ms ease-out;display:inline-flex}.coar-md-color-swatch:hover{transform:scale(1.08)}.coar-md-color-swatch--active{outline:2px solid var(--coar-text-accent-primary);outline-offset:1px}.coar-md-color-swatch--clear{background:var(--coar-background-neutral-secondary)}.coar-md-color-custom{align-items:center;gap:var(--coar-spacing-s);padding-top:var(--coar-spacing-xs);border-top:1px solid var(--coar-border-neutral);display:flex}.coar-md-color-custom-label{color:var(--coar-text-neutral-secondary);flex-shrink:0;font-size:12px}.coar-md-color-custom-input{border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);cursor:pointer;background:0 0;flex:1;height:28px;padding:0}.coar-md-color-custom-input::-webkit-color-swatch-wrapper{padding:2px}.coar-md-color-custom-input::-webkit-color-swatch{border:none;border-radius:2px}.coar-markdown{--coar-markdown-text:var(--coar-text-neutral-primary);--coar-markdown-link:var(--coar-text-brand-primary,var(--coar-text-neutral-primary));--coar-markdown-muted-text:var(--coar-text-neutral-tertiary);--coar-markdown-border:var(--coar-border-neutral-tertiary);--coar-markdown-surface:var(--coar-background-neutral-primary);--coar-markdown-surface-muted:var(--coar-background-neutral-tertiary,var(--coar-background-neutral-primary));--coar-markdown-radius:var(--coar-radius-xs);--coar-markdown-space-1:var(--coar-spacing-s,.5rem);--coar-markdown-space-2:var(--coar-spacing-m,1rem);--coar-markdown-heading-block-start:var(--coar-spacing-xl,2rem);color:var(--coar-markdown-text);display:block}.coar-markdown :where(h1,h2,h3,h4,h5,h6){font-family:var(--coar-font-family-title,inherit);color:var(--coar-markdown-text)}.coar-markdown h1{font-size:var(--coar-font-size-xl);font-weight:var(--coar-font-weight-bold);line-height:var(--coar-line-height-tight)}.coar-markdown h2{font-size:var(--coar-font-size-l);font-weight:var(--coar-font-weight-bold);line-height:1.25}.coar-markdown h3{font-size:var(--coar-font-size-m);font-weight:var(--coar-font-weight-semi-bold);line-height:var(--coar-line-height-snug)}.coar-markdown h4{font-size:var(--coar-font-size-s);font-weight:var(--coar-font-weight-semi-bold);line-height:1.35}.coar-markdown h5{font-size:var(--coar-font-size-xs);font-weight:var(--coar-font-weight-semi-bold);line-height:var(--coar-line-height-normal)}.coar-markdown h6{font-size:var(--coar-font-size-xxs);font-weight:var(--coar-font-weight-medium);line-height:1.45}.coar-markdown-heading,.coar-markdown-paragraph,.coar-markdown-blockquote,.coar-markdown-list,.coar-markdown-code-block,.coar-markdown-table,.coar-markdown-hr,.coar-markdown :where(p,blockquote,ul,ol,pre,table,hr){margin:0}.coar-markdown>:where(h1,h2,h3,h4,h5,h6,p,blockquote,ul,ol,pre,table,hr,.coar-code-block-host,.coar-table-host,.coar-markdown-frontmatter),.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6,p,blockquote,ul,ol,pre,table,hr,.coar-code-block-host,.coar-table-host,.coar-markdown-frontmatter){margin-block:0 var(--coar-markdown-space-2)}.coar-markdown>:where(h1,h2,h3,h4,h5,h6),.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6){margin-block-start:var(--coar-markdown-heading-block-start)}.coar-markdown>:where(h1,h2,h3,h4,h5,h6)+:where(h1,h2,h3,h4,h5,h6),.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6)+:where(h1,h2,h3,h4,h5,h6){margin-block-start:var(--coar-markdown-space-1)}.coar-markdown>:where(h1,h2,h3,h4,h5,h6):first-child,.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6):first-child{margin-block-start:0}.coar-markdown :where(blockquote),.coar-markdown-blockquote{padding-inline:var(--coar-markdown-space-2);border-left:2px solid var(--coar-markdown-border);color:var(--coar-text-neutral-secondary)}.coar-markdown :where(ul,ol),.coar-markdown-list{padding-inline-start:var(--coar-spacing-l,1.5rem);list-style-position:outside}.coar-markdown :where(ul),.coar-markdown-list--unordered{list-style-type:disc}.coar-markdown :where(ol),.coar-markdown-list--ordered{list-style-type:decimal}.coar-markdown :where(li),.coar-markdown-list-item{margin-block:.25em;display:list-item}.coar-markdown :where(li,td,th)>:where(p){margin-block:0}.coar-markdown :where(li[data-item-type=task]){margin-left:-1.25em;padding-left:1.5em;list-style:none;position:relative}.coar-markdown :where(li[data-item-type=task]):before{content:"";border:1.5px solid var(--coar-border-neutral-secondary,var(--coar-border-neutral));border-radius:var(--coar-radius-xs,2px);background:var(--coar-background-neutral-primary);cursor:pointer;box-sizing:border-box;width:14px;height:14px;transition:background-color .1s,border-color .1s;position:absolute;top:.45em;left:0}.coar-markdown :where(li[data-item-type=task][data-checked=true]):before{background:var(--coar-background-accent-primary);border-color:var(--coar-background-accent-primary)}.coar-markdown :where(li[data-item-type=task][data-checked=true]):after{content:"";border-left:2px solid var(--coar-text-on-bold,#fff);border-bottom:2px solid var(--coar-text-on-bold,#fff);pointer-events:none;width:8px;height:5px;position:absolute;top:calc(.45em + 2px);left:3px;transform:rotate(-45deg)}.coar-markdown :where(li[data-item-type=task][data-checked=true])>:where(p){color:var(--coar-text-neutral-tertiary);text-decoration:line-through}.coar-markdown :where(li[data-item-type=task]) input[type=checkbox]{display:none}.coar-markdown-list-item--task{align-items:flex-start;gap:var(--coar-spacing-s,.5rem);list-style:none;display:flex}.coar-markdown-list-item-content{min-width:0}.coar-markdown-task-checkbox{margin-top:.15em}.coar-markdown-code-block,.coar-markdown-code{display:block}.coar-markdown :where(:not(pre)>code),.coar-markdown-inline-code{color:var(--coar-text-accent-secondary,var(--coar-markdown-link));background:0 0;border:0;border-radius:0;padding:0}.coar-markdown :where(a),.coar-markdown-link{color:var(--coar-markdown-link);text-decoration:underline}.coar-markdown-image{vertical-align:middle;max-width:100%;height:auto}.coar-markdown :where(table),.coar-markdown-table{border-collapse:collapse;border-spacing:0;width:100%;font-size:var(--coar-body-small-base-size,.9rem);line-height:var(--coar-line-height-relaxed,1.5);display:table}.coar-markdown :where(table thead,table tr[data-is-header]),.coar-markdown-table>thead{background:var(--coar-markdown-surface-muted)}.coar-markdown :where(table th),.coar-markdown-table>thead th{padding:.625rem var(--coar-markdown-space-2);text-align:left;vertical-align:top;font-weight:var(--coar-font-weight-semi-bold,600);font-size:var(--coar-component-s-font-size,.85em);color:var(--coar-markdown-text);border-bottom:1px solid var(--coar-markdown-border);text-transform:uppercase;letter-spacing:.025em}.coar-markdown :where(table td),.coar-markdown-table>tbody td{padding:.625rem var(--coar-markdown-space-2);text-align:left;vertical-align:top;color:var(--coar-text-neutral-secondary,var(--coar-markdown-text));border-bottom:1px solid var(--coar-markdown-border)}.coar-markdown-table>tbody tr:nth-child(odd of :not([data-is-header])),.coar-markdown :where(table>tbody tr:nth-child(odd of :not([data-is-header]))){background:var(--coar-markdown-surface)}.coar-markdown-table>tbody tr:nth-child(2n of :not([data-is-header])),.coar-markdown :where(table>tbody tr:nth-child(2n of :not([data-is-header]))){background:var(--coar-markdown-surface-muted)}.coar-markdown-table>tbody tr:last-child td,.coar-markdown :where(table>tbody tr:last-child:not([data-is-header]) td){border-bottom:0}.coar-markdown-table-cell{padding:var(--coar-markdown-space-1);vertical-align:top;border-right:1px solid var(--coar-markdown-border);border-bottom:1px solid var(--coar-markdown-border)}.coar-markdown-hr{border:0;border-top:1px solid var(--coar-markdown-border)}.coar-markdown-unsupported,.coar-markdown-unsupported-inline{color:var(--coar-markdown-muted-text);font-style:italic}.coar-markdown-unsupported{padding:var(--coar-markdown-space-1);border:1px dashed var(--coar-markdown-border);border-radius:var(--coar-markdown-radius);background:var(--coar-markdown-surface)}.coar-markdown-frontmatter{color:var(--coar-color-gray-400,silver);font-style:italic}.coar-markdown-frontmatter__entry{overflow-wrap:anywhere}.coar-markdown-frontmatter__raw{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;color:inherit;margin:0;font-style:italic}.coar-md-root{background:var(--coar-background-neutral-primary);height:100%;color:var(--coar-text-neutral-primary);flex-direction:row;display:flex;overflow:hidden}.coar-md-root--toolbar-top,.coar-md-root--toolbar-bottom{flex-direction:column}.coar-md-root--disabled{opacity:.55;cursor:not-allowed}.coar-md-root--disabled .coar-md-area .milkdown{pointer-events:none}.coar-md-root--error{outline:1px solid var(--coar-text-semantic-error-bold,#b91c1c);outline-offset:-1px}.coar-md-area--source .milkdown{display:none}.coar-md-source-area{box-sizing:border-box;resize:none;width:100%;height:100%;padding:var(--coar-spacing-s) var(--coar-spacing-m);font-family:var(--coar-font-family-mono,monospace);font-size:var(--coar-font-size-s,.875rem);tab-size:2;background:var(--coar-background-neutral-primary);color:var(--coar-text-neutral-primary);border:none;outline:none;margin:0;line-height:1.6;position:absolute;inset:0}.coar-md-source-area:disabled{opacity:.55;cursor:not-allowed}.coar-md-source-corner{top:var(--coar-spacing-xs);right:var(--coar-spacing-xs);z-index:5;border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);background:var(--coar-background-neutral-primary);width:28px;height:28px;color:var(--coar-text-neutral-secondary);cursor:pointer;justify-content:center;align-items:center;padding:0;display:flex;position:absolute}.coar-md-source-corner:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-sidebar-wrap{--coar-sidebar-collapsed-width:2.25rem;--coar-sidebar-collapsed-height:2.25rem;--coar-sidebar-item-padding:.25rem .375rem;flex-shrink:0}.coar-md-root--toolbar-left .coar-md-sidebar-wrap{border-right:1px solid var(--coar-border-neutral)}.coar-md-root--toolbar-right .coar-md-sidebar-wrap{border-left:1px solid var(--coar-border-neutral)}.coar-md-root--toolbar-top .coar-md-sidebar-wrap{border-bottom:1px solid var(--coar-border-neutral)}.coar-md-root--toolbar-bottom .coar-md-sidebar-wrap{border-top:1px solid var(--coar-border-neutral)}.coar-md-area{padding:var(--coar-spacing-s) var(--coar-spacing-m);cursor:text;flex:1;position:relative;overflow:auto}.coar-md-area .milkdown,.coar-md-area .milkdown .editor,.coar-md-area .milkdown [contenteditable]{outline:none}.coar-md-area .milkdown pre{background:var(--coar-background-neutral-secondary);padding:var(--coar-spacing-s) var(--coar-spacing-m);border-radius:var(--coar-radius-xl);margin:.5em 0;overflow-x:auto}.coar-md-area .milkdown pre code{background:0 0;padding:0}.coar-md-area .milkdown hr{border:none;border-top:1px solid var(--coar-border-neutral);margin:1em 0}.coar-md-placeholder{padding:var(--coar-spacing-s) var(--coar-spacing-m);pointer-events:none;-webkit-user-select:none;user-select:none;position:absolute;inset:0;overflow:hidden}.coar-md-placeholder,.coar-md-placeholder *{color:var(--coar-text-placeholder)}.coar-md-placeholder .coar-markdown>:first-child{margin-top:0}.coar-md-floating-toolbar{padding:var(--coar-spacing-xs) 6px;background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-xl);box-shadow:var(--coar-shadow-m,0 4px 12px #0000001f);z-index:10000;gap:2px;animation:.12s ease-out coar-md-float-in;display:flex;position:fixed;transform:translate(-50%,-100%)}.coar-md-float-btn{border-radius:var(--coar-radius-s);width:30px;height:30px;color:var(--coar-text-neutral-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;justify-content:center;align-items:center;padding:0;display:flex}.coar-md-float-btn:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-float-btn:active,.coar-md-float-btn--active{background:var(--coar-background-accent-tertiary);color:var(--coar-text-accent-primary)}.coar-md-float-btn--disabled,.coar-md-float-btn:disabled{opacity:.4;cursor:not-allowed}.coar-md-float-btn--disabled:hover,.coar-md-float-btn:disabled:hover{color:var(--coar-text-neutral-secondary);background:0 0}.coar-md-float-sep{background:var(--coar-border-neutral);align-self:center;width:1px;height:18px;margin:0 2px}.coar-md-float-dropdown{position:relative}.coar-md-float-submenu{padding:var(--coar-spacing-xs);background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-xl);box-shadow:var(--coar-shadow-m,0 4px 12px #0000001f);z-index:10001;flex-direction:column;min-width:140px;animation:.1s ease-out coar-md-float-in;display:flex;position:absolute;top:calc(100% + 6px);left:50%;transform:translate(-50%)}.coar-md-float-submenu-item{align-items:center;gap:var(--coar-spacing-s);border-radius:var(--coar-radius-m);width:100%;color:var(--coar-text-neutral-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;text-align:left;background:0 0;border:none;padding:6px 10px;font-size:13px;display:flex}.coar-md-float-submenu-item:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-float-submenu-item:active,.coar-md-float-submenu-item--active{background:var(--coar-background-accent-tertiary);color:var(--coar-text-accent-primary)}@keyframes coar-md-float-in{0%{opacity:0;transform:translate(-50%,-100%)translateY(4px)}to{opacity:1;transform:translate(-50%,-100%)translateY(0)}}.coar-md-float-btn[style*=--coar-md-color-indicator]:after{content:"";background:var(--coar-md-color-indicator);border-radius:1px;height:2px;position:absolute;bottom:3px;left:4px;right:4px}.coar-md-float-btn[style*=--coar-md-color-indicator]{position:relative}
1
+ .coar-md-code-host{border-radius:var(--coar-radius-s);border:1px solid var(--coar-code-block-border,var(--coar-border-neutral));background:var(--coar-code-block-bg,var(--coar-background-neutral-secondary));margin:.75em 0;position:relative;overflow:hidden}.coar-md-code-host--editing{border-color:var(--coar-background-accent-primary)}.coar-md-code-render{position:relative}.coar-md-code-edit-btn{color:var(--coar-text-neutral-secondary);background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);cursor:pointer;opacity:0;z-index:1;align-items:center;gap:.25rem;padding:.25rem .5rem;font-size:.75rem;font-weight:500;transition:opacity .12s ease-out;display:inline-flex;position:absolute;top:.5rem;right:.5rem}.coar-md-code-render:hover .coar-md-code-edit-btn,.coar-md-code-edit-btn:focus-visible{opacity:1}.coar-md-code-edit-btn:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-code-lang-row{align-items:center;gap:var(--coar-spacing-s);padding:var(--coar-spacing-s) .75rem;border-bottom:1px solid var(--coar-code-block-border,var(--coar-border-neutral));background:var(--coar-code-block-header-bg,var(--coar-background-neutral-tertiary));min-height:36px;display:flex}.coar-md-code-lang-select{--coar-select-bg:transparent;--coar-select-border:transparent}.coar-md-code-content{padding:var(--coar-spacing-s) .75rem;font-family:var(--coar-font-family-code,"Cascadia Code", Consolas, Monaco, monospace);font-size:var(--coar-component-s-font-size,.85em);line-height:1.5}.coar-md-code-content>pre{white-space:pre-wrap;font-family:inherit;font-size:inherit;background:0 0;margin:0;padding:0}.coar-md-code-content>pre>code{white-space:inherit;outline:none;font-family:inherit;display:block}.coar-md-color-picker{gap:var(--coar-spacing-s);width:224px;padding:var(--coar-spacing-s);background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-xl);box-shadow:var(--coar-shadow-m,0 4px 12px #0000001f);flex-direction:column;display:flex}.coar-md-color-grid{grid-template-columns:repeat(5,1fr);gap:4px;display:grid}.coar-md-color-swatch{aspect-ratio:1;border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);background:var(--coar-md-swatch,transparent);width:100%;color:var(--coar-text-neutral-secondary);cursor:pointer;justify-content:center;align-items:center;padding:0;transition:transform 80ms ease-out;display:inline-flex}.coar-md-color-swatch:hover{transform:scale(1.08)}.coar-md-color-swatch--active{outline:2px solid var(--coar-text-accent-primary);outline-offset:1px}.coar-md-color-swatch--clear{background:var(--coar-background-neutral-secondary)}.coar-md-color-custom{align-items:center;gap:var(--coar-spacing-s);padding-top:var(--coar-spacing-xs);border-top:1px solid var(--coar-border-neutral);display:flex}.coar-md-color-custom-label{color:var(--coar-text-neutral-secondary);flex-shrink:0;font-size:12px}.coar-md-color-custom-input{border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);cursor:pointer;background:0 0;flex:1;height:28px;padding:0}.coar-md-color-custom-input::-webkit-color-swatch-wrapper{padding:2px}.coar-md-color-custom-input::-webkit-color-swatch{border:none;border-radius:2px}.coar-md-table-picker[data-v-68fa1760]{padding:var(--coar-spacing-s,8px);flex-direction:column;gap:6px;display:flex}.coar-md-table-picker__grid[data-v-68fa1760]{gap:3px;display:grid}.coar-md-table-picker__cell[data-v-68fa1760]{border:1px solid var(--coar-border-neutral);background:var(--coar-background-neutral-primary);cursor:pointer;border-radius:2px;width:18px;height:18px;padding:0}.coar-md-table-picker__cell--on[data-v-68fa1760]{background:var(--coar-background-accent-primary,#2563eb);border-color:var(--coar-background-accent-primary,#2563eb)}.coar-md-table-picker__label[data-v-68fa1760]{text-align:center;color:var(--coar-text-neutral-secondary);font-size:12px;font-weight:600}.coar-md-table-picker__hint[data-v-68fa1760]{text-align:center;color:var(--coar-text-neutral-tertiary);font-size:11px}.coar-md-table-picker__hint code[data-v-68fa1760]{background:var(--coar-background-neutral-secondary);border-radius:3px;padding:1px 4px}.coar-md-th[data-v-24e26df4]{pointer-events:none;z-index:40;position:fixed;inset:0}.coar-md-th__hl[data-v-24e26df4]{background:color-mix(in srgb, var(--coar-background-accent-primary,#2563eb) 12%, transparent);outline:1px solid color-mix(in srgb, var(--coar-background-accent-primary,#2563eb) 40%, transparent);pointer-events:none;position:fixed}.coar-md-th__bar[data-v-24e26df4]{pointer-events:none;position:fixed}.coar-md-th__grip[data-v-24e26df4]{cursor:pointer;pointer-events:auto;background:var(--coar-background-neutral-secondary,#e5e7eb);border:none;border-radius:3px;padding:0;position:absolute}.coar-md-th__bar--col .coar-md-th__grip[data-v-24e26df4]{top:2px;bottom:2px}.coar-md-th__bar--row .coar-md-th__grip[data-v-24e26df4]{left:2px;right:2px}.coar-md-th__grip[data-v-24e26df4]:hover,.coar-md-th__grip--active[data-v-24e26df4]{background:var(--coar-background-accent-primary,#2563eb)}.coar-md-th__drop[data-v-24e26df4]{background:var(--coar-background-accent-primary,#2563eb);pointer-events:none;border-radius:1px;position:fixed}.coar-md-image-dialog[data-v-a0456b93]{gap:var(--coar-spacing-m,12px);flex-direction:column;min-width:22rem;display:flex}.coar-md-image-dialog__actions[data-v-a0456b93]{justify-content:flex-end;gap:var(--coar-spacing-s,8px);margin-top:var(--coar-spacing-s,8px);display:flex}.coar-markdown{--coar-markdown-text:var(--coar-text-neutral-primary);--coar-markdown-link:var(--coar-text-brand-primary,var(--coar-text-neutral-primary));--coar-markdown-muted-text:var(--coar-text-neutral-tertiary);--coar-markdown-border:var(--coar-border-neutral-tertiary);--coar-markdown-surface:var(--coar-background-neutral-primary);--coar-markdown-surface-muted:var(--coar-background-neutral-tertiary,var(--coar-background-neutral-primary));--coar-markdown-radius:var(--coar-radius-xs);--coar-markdown-space-1:var(--coar-spacing-s,.5rem);--coar-markdown-space-2:var(--coar-spacing-m,1rem);--coar-markdown-heading-block-start:var(--coar-spacing-xl,2rem);color:var(--coar-markdown-text);display:block}.coar-markdown :where(h1,h2,h3,h4,h5,h6){font-family:var(--coar-font-family-title,inherit);color:var(--coar-markdown-text)}.coar-markdown h1{font-size:var(--coar-font-size-xl);font-weight:var(--coar-font-weight-bold);line-height:var(--coar-line-height-tight)}.coar-markdown h2{font-size:var(--coar-font-size-l);font-weight:var(--coar-font-weight-bold);line-height:1.25}.coar-markdown h3{font-size:var(--coar-font-size-m);font-weight:var(--coar-font-weight-semi-bold);line-height:var(--coar-line-height-snug)}.coar-markdown h4{font-size:var(--coar-font-size-s);font-weight:var(--coar-font-weight-semi-bold);line-height:1.35}.coar-markdown h5{font-size:var(--coar-font-size-xs);font-weight:var(--coar-font-weight-semi-bold);line-height:var(--coar-line-height-normal)}.coar-markdown h6{font-size:var(--coar-font-size-xxs);font-weight:var(--coar-font-weight-medium);line-height:1.45}.coar-markdown-heading,.coar-markdown-paragraph,.coar-markdown-blockquote,.coar-markdown-list,.coar-markdown-code-block,.coar-markdown-table,.coar-markdown-hr,.coar-markdown :where(p,blockquote,ul,ol,pre,table,hr){margin:0}.coar-markdown>:where(h1,h2,h3,h4,h5,h6,p,blockquote,ul,ol,pre,table,hr,.coar-code-block-host,.coar-table-host,.coar-markdown-frontmatter),.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6,p,blockquote,ul,ol,pre,table,hr,.coar-code-block-host,.coar-table-host,.coar-markdown-frontmatter){margin-block:0 var(--coar-markdown-space-2)}.coar-markdown>:where(h1,h2,h3,h4,h5,h6),.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6){margin-block-start:var(--coar-markdown-heading-block-start)}.coar-markdown>:where(h1,h2,h3,h4,h5,h6)+:where(h1,h2,h3,h4,h5,h6),.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6)+:where(h1,h2,h3,h4,h5,h6){margin-block-start:var(--coar-markdown-space-1)}.coar-markdown>:where(h1,h2,h3,h4,h5,h6):first-child,.coar-markdown .ProseMirror>:where(h1,h2,h3,h4,h5,h6):first-child{margin-block-start:0}.coar-markdown :where(blockquote),.coar-markdown-blockquote{padding-inline:var(--coar-markdown-space-2);border-left:2px solid var(--coar-markdown-border);color:var(--coar-text-neutral-secondary)}.coar-markdown :where(ul,ol),.coar-markdown-list{padding-inline-start:var(--coar-spacing-l,1.5rem);list-style-position:outside}.coar-markdown :where(ul),.coar-markdown-list--unordered{list-style-type:disc}.coar-markdown :where(ol),.coar-markdown-list--ordered{list-style-type:decimal}.coar-markdown :where(li),.coar-markdown-list-item{margin-block:.25em;display:list-item}.coar-markdown :where(li,td,th)>:where(p){margin-block:0}.coar-markdown :where(li[data-item-type=task]){margin-left:-1.25em;padding-left:1.5em;list-style:none;position:relative}.coar-markdown :where(li[data-item-type=task]):before{content:"";border:1.5px solid var(--coar-border-neutral-secondary,var(--coar-border-neutral));border-radius:var(--coar-radius-xs,2px);background:var(--coar-background-neutral-primary);cursor:pointer;box-sizing:border-box;width:14px;height:14px;transition:background-color .1s,border-color .1s;position:absolute;top:.45em;left:0}.coar-markdown :where(li[data-item-type=task][data-checked=true]):before{background:var(--coar-background-accent-primary);border-color:var(--coar-background-accent-primary)}.coar-markdown :where(li[data-item-type=task][data-checked=true]):after{content:"";border-left:2px solid var(--coar-text-on-bold,#fff);border-bottom:2px solid var(--coar-text-on-bold,#fff);pointer-events:none;width:8px;height:5px;position:absolute;top:calc(.45em + 2px);left:3px;transform:rotate(-45deg)}.coar-markdown :where(li[data-item-type=task][data-checked=true])>:where(p){color:var(--coar-text-neutral-tertiary);text-decoration:line-through}.coar-markdown :where(li[data-item-type=task]) input[type=checkbox]{display:none}.coar-markdown-list-item--task{align-items:flex-start;gap:var(--coar-spacing-s,.5rem);list-style:none;display:flex}.coar-markdown-list-item-content{min-width:0}.coar-markdown-task-checkbox{margin-top:.15em}.coar-markdown-code-block,.coar-markdown-code{display:block}.coar-markdown :where(:not(pre)>code),.coar-markdown-inline-code{color:var(--coar-text-accent-secondary,var(--coar-markdown-link));background:0 0;border:0;border-radius:0;padding:0}.coar-markdown :where(a),.coar-markdown-link{color:var(--coar-markdown-link);text-decoration:underline}.coar-markdown-image{vertical-align:middle;max-width:100%;height:auto}.coar-markdown :where(table),.coar-markdown-table{border-collapse:collapse;border-spacing:0;width:100%;font-size:var(--coar-body-small-base-size,.9rem);line-height:var(--coar-line-height-relaxed,1.5);display:table}.coar-markdown :where(table thead,table tr[data-is-header]),.coar-markdown-table>thead{background:var(--coar-markdown-surface-muted)}.coar-markdown :where(table th),.coar-markdown-table>thead th{padding:.625rem var(--coar-markdown-space-2);text-align:left;vertical-align:top;font-weight:var(--coar-font-weight-semi-bold,600);font-size:var(--coar-component-s-font-size,.85em);color:var(--coar-markdown-text);border-bottom:1px solid var(--coar-markdown-border);text-transform:uppercase;letter-spacing:.025em}.coar-markdown :where(table td),.coar-markdown-table>tbody td{padding:.625rem var(--coar-markdown-space-2);text-align:left;vertical-align:top;color:var(--coar-text-neutral-secondary,var(--coar-markdown-text));border-bottom:1px solid var(--coar-markdown-border)}.coar-markdown-table>tbody tr:nth-child(odd of :not([data-is-header])),.coar-markdown :where(table>tbody tr:nth-child(odd of :not([data-is-header]))){background:var(--coar-markdown-surface)}.coar-markdown-table>tbody tr:nth-child(2n of :not([data-is-header])),.coar-markdown :where(table>tbody tr:nth-child(2n of :not([data-is-header]))){background:var(--coar-markdown-surface-muted)}.coar-markdown-table>tbody tr:last-child td,.coar-markdown :where(table>tbody tr:last-child:not([data-is-header]) td){border-bottom:0}.coar-markdown-table-cell{padding:var(--coar-markdown-space-1);vertical-align:top;border-right:1px solid var(--coar-markdown-border);border-bottom:1px solid var(--coar-markdown-border)}.coar-markdown-hr{border:0;border-top:1px solid var(--coar-markdown-border)}.coar-markdown-unsupported,.coar-markdown-unsupported-inline{color:var(--coar-markdown-muted-text);font-style:italic}.coar-markdown-unsupported{padding:var(--coar-markdown-space-1);border:1px dashed var(--coar-markdown-border);border-radius:var(--coar-markdown-radius);background:var(--coar-markdown-surface)}.coar-markdown-frontmatter{color:var(--coar-color-gray-400,silver);font-style:italic}.coar-markdown-frontmatter__entry{overflow-wrap:anywhere}.coar-markdown-frontmatter__raw{font:inherit;white-space:pre-wrap;overflow-wrap:anywhere;color:inherit;margin:0;font-style:italic}.coar-md-root{background:var(--coar-background-neutral-primary);height:100%;color:var(--coar-text-neutral-primary);flex-direction:row;display:flex;overflow:hidden}.coar-md-root--toolbar-top,.coar-md-root--toolbar-bottom{flex-direction:column}.coar-md-root--disabled{opacity:.55;cursor:not-allowed}.coar-md-root--disabled .coar-md-area .milkdown{pointer-events:none}.coar-md-root--error{outline:1px solid var(--coar-text-semantic-error-bold,#b91c1c);outline-offset:-1px}.coar-md-area--source .milkdown{display:none}.coar-md-source-area{box-sizing:border-box;resize:none;width:100%;height:100%;padding:var(--coar-spacing-s) var(--coar-spacing-m);font-family:var(--coar-font-family-mono,monospace);font-size:var(--coar-font-size-s,.875rem);tab-size:2;background:var(--coar-background-neutral-primary);color:var(--coar-text-neutral-primary);border:none;outline:none;margin:0;line-height:1.6;position:absolute;inset:0}.coar-md-source-area:disabled{opacity:.55;cursor:not-allowed}.coar-md-source-corner{top:var(--coar-spacing-xs);right:var(--coar-spacing-xs);z-index:5;border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-s);background:var(--coar-background-neutral-primary);width:28px;height:28px;color:var(--coar-text-neutral-secondary);cursor:pointer;justify-content:center;align-items:center;padding:0;display:flex;position:absolute}.coar-md-source-corner:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-sidebar-wrap{--coar-sidebar-collapsed-width:2.25rem;--coar-sidebar-collapsed-height:2.25rem;--coar-sidebar-item-padding:.25rem .375rem;flex-shrink:0}.coar-md-root--toolbar-left .coar-md-sidebar-wrap{border-right:1px solid var(--coar-border-neutral)}.coar-md-root--toolbar-right .coar-md-sidebar-wrap{border-left:1px solid var(--coar-border-neutral)}.coar-md-root--toolbar-top .coar-md-sidebar-wrap{border-bottom:1px solid var(--coar-border-neutral)}.coar-md-root--toolbar-bottom .coar-md-sidebar-wrap{border-top:1px solid var(--coar-border-neutral)}.coar-md-area{padding:var(--coar-spacing-s) var(--coar-spacing-m);cursor:text;flex:1;position:relative;overflow:auto}.coar-md-area .milkdown,.coar-md-area .milkdown .editor,.coar-md-area .milkdown [contenteditable]{outline:none}.coar-md-area .milkdown pre{background:var(--coar-background-neutral-secondary);padding:var(--coar-spacing-s) var(--coar-spacing-m);border-radius:var(--coar-radius-xl);margin:.5em 0;overflow-x:auto}.coar-md-area .milkdown pre code{background:0 0;padding:0}.coar-md-area .milkdown hr{border:none;border-top:1px solid var(--coar-border-neutral);margin:1em 0}.coar-md-area .milkdown img{max-width:100%;height:auto}.coar-md-image-uploading{vertical-align:text-bottom;border:2px solid var(--coar-border-neutral);border-top-color:var(--coar-text-neutral-secondary,currentColor);border-radius:50%;width:1.25em;height:1.25em;animation:.7s linear infinite coar-md-image-spin;display:inline-block}@keyframes coar-md-image-spin{to{transform:rotate(360deg)}}.coar-md-placeholder{padding:var(--coar-spacing-s) var(--coar-spacing-m);pointer-events:none;-webkit-user-select:none;user-select:none;position:absolute;inset:0;overflow:hidden}.coar-md-placeholder,.coar-md-placeholder *{color:var(--coar-text-placeholder)}.coar-md-placeholder .coar-markdown>:first-child{margin-top:0}.coar-md-floating-toolbar{padding:var(--coar-spacing-xs) 6px;background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-xl);box-shadow:var(--coar-shadow-m,0 4px 12px #0000001f);z-index:10000;gap:2px;animation:.12s ease-out coar-md-float-in;display:flex;position:fixed;transform:translate(-50%,-100%)}.coar-md-float-btn{border-radius:var(--coar-radius-s);width:30px;height:30px;color:var(--coar-text-neutral-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:none;justify-content:center;align-items:center;padding:0;display:flex}.coar-md-float-btn:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-float-btn:active,.coar-md-float-btn--active{background:var(--coar-background-accent-tertiary);color:var(--coar-text-accent-primary)}.coar-md-float-btn--disabled,.coar-md-float-btn:disabled{opacity:.4;cursor:not-allowed}.coar-md-float-btn--disabled:hover,.coar-md-float-btn:disabled:hover{color:var(--coar-text-neutral-secondary);background:0 0}.coar-md-float-sep{background:var(--coar-border-neutral);align-self:center;width:1px;height:18px;margin:0 2px}.coar-md-float-dropdown{position:relative}.coar-md-float-submenu{padding:var(--coar-spacing-xs);background:var(--coar-background-neutral-primary);border:1px solid var(--coar-border-neutral);border-radius:var(--coar-radius-xl);box-shadow:var(--coar-shadow-m,0 4px 12px #0000001f);z-index:10001;flex-direction:column;min-width:140px;animation:.1s ease-out coar-md-float-in;display:flex;position:absolute;top:calc(100% + 6px);left:50%;transform:translate(-50%)}.coar-md-float-submenu-item{align-items:center;gap:var(--coar-spacing-s);border-radius:var(--coar-radius-m);width:100%;color:var(--coar-text-neutral-secondary);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap;text-align:left;background:0 0;border:none;padding:6px 10px;font-size:13px;display:flex}.coar-md-float-submenu-item:hover{background:var(--coar-background-neutral-tertiary);color:var(--coar-text-neutral-primary)}.coar-md-float-submenu-item:active,.coar-md-float-submenu-item--active{background:var(--coar-background-accent-tertiary);color:var(--coar-text-accent-primary)}@keyframes coar-md-float-in{0%{opacity:0;transform:translate(-50%,-100%)translateY(4px)}to{opacity:1;transform:translate(-50%,-100%)translateY(0)}}.coar-md-float-btn[style*=--coar-md-color-indicator]:after{content:"";background:var(--coar-md-color-indicator);border-radius:1px;height:2px;position:absolute;bottom:3px;left:4px;right:4px}.coar-md-float-btn[style*=--coar-md-color-indicator]{position:relative}
2
2
  /*$vite$:1*/
package/dist/index.d.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  export { default as CoarMarkdownEditor } from './CoarMarkdownEditor.vue';
2
2
  export { COAR_MARKDOWN_EDITOR_ALL_TOOLS } from './CoarMarkdownEditor.vue';
3
3
  export type { CoarMarkdownEditorProps, CoarMarkdownEditorToolbarMode, CoarMarkdownEditorToolbarPosition, CoarMarkdownEditorTool, } from './CoarMarkdownEditor.vue';
4
+ export type { ImageUploader, ImageUploadOptions } from './image/imageUpload';
5
+ export type { ImageInsertResult } from './image/ImageInsertDialog.vue';
6
+ export type { ImagePicker, ImagePickContext, ImageDescriptor } from './image/pickImage';
7
+ export { resolveCapabilities } from './flavor';
8
+ export type { CoarMarkdownFlavor, CoarMarkdownFlavorInput, CoarMarkdownCapabilities } from './flavor';
4
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC1E,YAAY,EACV,uBAAuB,EACvB,6BAA6B,EAC7B,iCAAiC,EACjC,sBAAsB,GACvB,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC1E,YAAY,EACV,uBAAuB,EACvB,6BAA6B,EAC7B,iCAAiC,EACjC,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC"}