@rtif-sdk/web 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/block-drag-handler.d.ts +189 -0
  4. package/dist/block-drag-handler.d.ts.map +1 -0
  5. package/dist/block-drag-handler.js +745 -0
  6. package/dist/block-drag-handler.js.map +1 -0
  7. package/dist/block-renderer.d.ts +402 -0
  8. package/dist/block-renderer.d.ts.map +1 -0
  9. package/dist/block-renderer.js +424 -0
  10. package/dist/block-renderer.js.map +1 -0
  11. package/dist/clipboard.d.ts +178 -0
  12. package/dist/clipboard.d.ts.map +1 -0
  13. package/dist/clipboard.js +432 -0
  14. package/dist/clipboard.js.map +1 -0
  15. package/dist/command-bus.d.ts +113 -0
  16. package/dist/command-bus.d.ts.map +1 -0
  17. package/dist/command-bus.js +70 -0
  18. package/dist/command-bus.js.map +1 -0
  19. package/dist/composition.d.ts +220 -0
  20. package/dist/composition.d.ts.map +1 -0
  21. package/dist/composition.js +271 -0
  22. package/dist/composition.js.map +1 -0
  23. package/dist/content-extraction.d.ts +69 -0
  24. package/dist/content-extraction.d.ts.map +1 -0
  25. package/dist/content-extraction.js +228 -0
  26. package/dist/content-extraction.js.map +1 -0
  27. package/dist/content-handler-file.d.ts +40 -0
  28. package/dist/content-handler-file.d.ts.map +1 -0
  29. package/dist/content-handler-file.js +91 -0
  30. package/dist/content-handler-file.js.map +1 -0
  31. package/dist/content-handler-image.d.ts +82 -0
  32. package/dist/content-handler-image.d.ts.map +1 -0
  33. package/dist/content-handler-image.js +120 -0
  34. package/dist/content-handler-image.js.map +1 -0
  35. package/dist/content-handler-url.d.ts +129 -0
  36. package/dist/content-handler-url.d.ts.map +1 -0
  37. package/dist/content-handler-url.js +244 -0
  38. package/dist/content-handler-url.js.map +1 -0
  39. package/dist/content-handlers.d.ts +67 -0
  40. package/dist/content-handlers.d.ts.map +1 -0
  41. package/dist/content-handlers.js +263 -0
  42. package/dist/content-handlers.js.map +1 -0
  43. package/dist/content-pipeline.d.ts +383 -0
  44. package/dist/content-pipeline.d.ts.map +1 -0
  45. package/dist/content-pipeline.js +232 -0
  46. package/dist/content-pipeline.js.map +1 -0
  47. package/dist/cursor-nav.d.ts +149 -0
  48. package/dist/cursor-nav.d.ts.map +1 -0
  49. package/dist/cursor-nav.js +230 -0
  50. package/dist/cursor-nav.js.map +1 -0
  51. package/dist/cursor-rect.d.ts +65 -0
  52. package/dist/cursor-rect.d.ts.map +1 -0
  53. package/dist/cursor-rect.js +98 -0
  54. package/dist/cursor-rect.js.map +1 -0
  55. package/dist/drop-indicator.d.ts +108 -0
  56. package/dist/drop-indicator.d.ts.map +1 -0
  57. package/dist/drop-indicator.js +236 -0
  58. package/dist/drop-indicator.js.map +1 -0
  59. package/dist/editor.d.ts +41 -0
  60. package/dist/editor.d.ts.map +1 -0
  61. package/dist/editor.js +710 -0
  62. package/dist/editor.js.map +1 -0
  63. package/dist/floating-toolbar.d.ts +93 -0
  64. package/dist/floating-toolbar.d.ts.map +1 -0
  65. package/dist/floating-toolbar.js +159 -0
  66. package/dist/floating-toolbar.js.map +1 -0
  67. package/dist/index.d.ts +62 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +119 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/input-bridge.d.ts +273 -0
  72. package/dist/input-bridge.d.ts.map +1 -0
  73. package/dist/input-bridge.js +884 -0
  74. package/dist/input-bridge.js.map +1 -0
  75. package/dist/link-popover.d.ts +38 -0
  76. package/dist/link-popover.d.ts.map +1 -0
  77. package/dist/link-popover.js +278 -0
  78. package/dist/link-popover.js.map +1 -0
  79. package/dist/mark-renderer.d.ts +275 -0
  80. package/dist/mark-renderer.d.ts.map +1 -0
  81. package/dist/mark-renderer.js +210 -0
  82. package/dist/mark-renderer.js.map +1 -0
  83. package/dist/perf.d.ts +145 -0
  84. package/dist/perf.d.ts.map +1 -0
  85. package/dist/perf.js +260 -0
  86. package/dist/perf.js.map +1 -0
  87. package/dist/plugin-kit.d.ts +265 -0
  88. package/dist/plugin-kit.d.ts.map +1 -0
  89. package/dist/plugin-kit.js +234 -0
  90. package/dist/plugin-kit.js.map +1 -0
  91. package/dist/plugins/alignment-plugin.d.ts +68 -0
  92. package/dist/plugins/alignment-plugin.d.ts.map +1 -0
  93. package/dist/plugins/alignment-plugin.js +98 -0
  94. package/dist/plugins/alignment-plugin.js.map +1 -0
  95. package/dist/plugins/block-utils.d.ts +113 -0
  96. package/dist/plugins/block-utils.d.ts.map +1 -0
  97. package/dist/plugins/block-utils.js +191 -0
  98. package/dist/plugins/block-utils.js.map +1 -0
  99. package/dist/plugins/blockquote-plugin.d.ts +39 -0
  100. package/dist/plugins/blockquote-plugin.d.ts.map +1 -0
  101. package/dist/plugins/blockquote-plugin.js +88 -0
  102. package/dist/plugins/blockquote-plugin.js.map +1 -0
  103. package/dist/plugins/bold-plugin.d.ts +37 -0
  104. package/dist/plugins/bold-plugin.d.ts.map +1 -0
  105. package/dist/plugins/bold-plugin.js +48 -0
  106. package/dist/plugins/bold-plugin.js.map +1 -0
  107. package/dist/plugins/callout-plugin.d.ts +100 -0
  108. package/dist/plugins/callout-plugin.d.ts.map +1 -0
  109. package/dist/plugins/callout-plugin.js +200 -0
  110. package/dist/plugins/callout-plugin.js.map +1 -0
  111. package/dist/plugins/code-block-plugin.d.ts +62 -0
  112. package/dist/plugins/code-block-plugin.d.ts.map +1 -0
  113. package/dist/plugins/code-block-plugin.js +176 -0
  114. package/dist/plugins/code-block-plugin.js.map +1 -0
  115. package/dist/plugins/code-plugin.d.ts +37 -0
  116. package/dist/plugins/code-plugin.d.ts.map +1 -0
  117. package/dist/plugins/code-plugin.js +48 -0
  118. package/dist/plugins/code-plugin.js.map +1 -0
  119. package/dist/plugins/embed-plugin.d.ts +90 -0
  120. package/dist/plugins/embed-plugin.d.ts.map +1 -0
  121. package/dist/plugins/embed-plugin.js +147 -0
  122. package/dist/plugins/embed-plugin.js.map +1 -0
  123. package/dist/plugins/font-family-plugin.d.ts +58 -0
  124. package/dist/plugins/font-family-plugin.d.ts.map +1 -0
  125. package/dist/plugins/font-family-plugin.js +57 -0
  126. package/dist/plugins/font-family-plugin.js.map +1 -0
  127. package/dist/plugins/font-size-plugin.d.ts +57 -0
  128. package/dist/plugins/font-size-plugin.d.ts.map +1 -0
  129. package/dist/plugins/font-size-plugin.js +56 -0
  130. package/dist/plugins/font-size-plugin.js.map +1 -0
  131. package/dist/plugins/heading-plugin.d.ts +52 -0
  132. package/dist/plugins/heading-plugin.d.ts.map +1 -0
  133. package/dist/plugins/heading-plugin.js +114 -0
  134. package/dist/plugins/heading-plugin.js.map +1 -0
  135. package/dist/plugins/hr-plugin.d.ts +33 -0
  136. package/dist/plugins/hr-plugin.d.ts.map +1 -0
  137. package/dist/plugins/hr-plugin.js +75 -0
  138. package/dist/plugins/hr-plugin.js.map +1 -0
  139. package/dist/plugins/image-plugin.d.ts +115 -0
  140. package/dist/plugins/image-plugin.d.ts.map +1 -0
  141. package/dist/plugins/image-plugin.js +199 -0
  142. package/dist/plugins/image-plugin.js.map +1 -0
  143. package/dist/plugins/indent-plugin.d.ts +62 -0
  144. package/dist/plugins/indent-plugin.d.ts.map +1 -0
  145. package/dist/plugins/indent-plugin.js +128 -0
  146. package/dist/plugins/indent-plugin.js.map +1 -0
  147. package/dist/plugins/index.d.ts +45 -0
  148. package/dist/plugins/index.d.ts.map +1 -0
  149. package/dist/plugins/index.js +42 -0
  150. package/dist/plugins/index.js.map +1 -0
  151. package/dist/plugins/italic-plugin.d.ts +37 -0
  152. package/dist/plugins/italic-plugin.d.ts.map +1 -0
  153. package/dist/plugins/italic-plugin.js +48 -0
  154. package/dist/plugins/italic-plugin.js.map +1 -0
  155. package/dist/plugins/link-plugin.d.ts +129 -0
  156. package/dist/plugins/link-plugin.d.ts.map +1 -0
  157. package/dist/plugins/link-plugin.js +212 -0
  158. package/dist/plugins/link-plugin.js.map +1 -0
  159. package/dist/plugins/list-plugin.d.ts +53 -0
  160. package/dist/plugins/list-plugin.d.ts.map +1 -0
  161. package/dist/plugins/list-plugin.js +309 -0
  162. package/dist/plugins/list-plugin.js.map +1 -0
  163. package/dist/plugins/mark-utils.d.ts +173 -0
  164. package/dist/plugins/mark-utils.d.ts.map +1 -0
  165. package/dist/plugins/mark-utils.js +425 -0
  166. package/dist/plugins/mark-utils.js.map +1 -0
  167. package/dist/plugins/mention-plugin.d.ts +191 -0
  168. package/dist/plugins/mention-plugin.d.ts.map +1 -0
  169. package/dist/plugins/mention-plugin.js +295 -0
  170. package/dist/plugins/mention-plugin.js.map +1 -0
  171. package/dist/plugins/strikethrough-plugin.d.ts +37 -0
  172. package/dist/plugins/strikethrough-plugin.d.ts.map +1 -0
  173. package/dist/plugins/strikethrough-plugin.js +48 -0
  174. package/dist/plugins/strikethrough-plugin.js.map +1 -0
  175. package/dist/plugins/text-color-plugin.d.ts +57 -0
  176. package/dist/plugins/text-color-plugin.d.ts.map +1 -0
  177. package/dist/plugins/text-color-plugin.js +56 -0
  178. package/dist/plugins/text-color-plugin.js.map +1 -0
  179. package/dist/plugins/underline-plugin.d.ts +37 -0
  180. package/dist/plugins/underline-plugin.d.ts.map +1 -0
  181. package/dist/plugins/underline-plugin.js +48 -0
  182. package/dist/plugins/underline-plugin.js.map +1 -0
  183. package/dist/presets.d.ts +95 -0
  184. package/dist/presets.d.ts.map +1 -0
  185. package/dist/presets.js +159 -0
  186. package/dist/presets.js.map +1 -0
  187. package/dist/renderer.d.ts +125 -0
  188. package/dist/renderer.d.ts.map +1 -0
  189. package/dist/renderer.js +415 -0
  190. package/dist/renderer.js.map +1 -0
  191. package/dist/scroll-to-cursor.d.ts +25 -0
  192. package/dist/scroll-to-cursor.d.ts.map +1 -0
  193. package/dist/scroll-to-cursor.js +59 -0
  194. package/dist/scroll-to-cursor.js.map +1 -0
  195. package/dist/selection-sync.d.ts +159 -0
  196. package/dist/selection-sync.d.ts.map +1 -0
  197. package/dist/selection-sync.js +527 -0
  198. package/dist/selection-sync.js.map +1 -0
  199. package/dist/shortcut-handler.d.ts +98 -0
  200. package/dist/shortcut-handler.d.ts.map +1 -0
  201. package/dist/shortcut-handler.js +155 -0
  202. package/dist/shortcut-handler.js.map +1 -0
  203. package/dist/toolbar.d.ts +103 -0
  204. package/dist/toolbar.d.ts.map +1 -0
  205. package/dist/toolbar.js +134 -0
  206. package/dist/toolbar.js.map +1 -0
  207. package/dist/trigger-manager.d.ts +205 -0
  208. package/dist/trigger-manager.d.ts.map +1 -0
  209. package/dist/trigger-manager.js +466 -0
  210. package/dist/trigger-manager.js.map +1 -0
  211. package/dist/types.d.ts +216 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +2 -0
  214. package/dist/types.js.map +1 -0
  215. package/package.json +30 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Horizontal rule block type plugin — registers the `hr` block type and
3
+ * an input rule for `---` at the start of an empty block.
4
+ *
5
+ * The HR plugin does not register any commands — horizontal rules are
6
+ * created exclusively via the input rule or programmatic operation dispatch.
7
+ *
8
+ * @module
9
+ */
10
+ import { blockTextLength } from '@rtif-sdk/core';
11
+ import { getBlockStartOffset } from './block-utils.js';
12
+ /**
13
+ * Create the horizontal rule block type plugin.
14
+ *
15
+ * Registers:
16
+ * - Block type: `hr` (no default attrs)
17
+ * - Input rule: `---` at the start of an empty block converts to an HR
18
+ * and inserts a new empty text block below it
19
+ *
20
+ * @returns A plugin instance ready for `engine.use()`
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const engine = createEngine(initialDoc);
25
+ * engine.use(hrPlugin());
26
+ *
27
+ * // Type "---" then the input rule fires:
28
+ * // 1. Deletes the "---" text
29
+ * // 2. Sets block type to 'hr'
30
+ * // 3. Splits block to create a new empty text block below
31
+ * ```
32
+ */
33
+ export function hrPlugin() {
34
+ return {
35
+ id: 'block-hr',
36
+ init(ctx) {
37
+ // ---------------------------------------------------------------
38
+ // Block type registration
39
+ // ---------------------------------------------------------------
40
+ ctx.registerBlockType('hr', {});
41
+ // ---------------------------------------------------------------
42
+ // Input rule: --- at block start in an otherwise empty-after-delete block
43
+ // ---------------------------------------------------------------
44
+ ctx.registerInputRule({
45
+ pattern: /^---$/,
46
+ exclusive: true,
47
+ handler(engine, match, blockId) {
48
+ const blockStart = getBlockStartOffset(engine.state.doc, blockId);
49
+ const prefixLength = match[0].length;
50
+ // Delete the "---" text, set to hr, then split to create an empty
51
+ // text block below the HR for continued editing.
52
+ engine.dispatch([
53
+ { type: 'delete_text', offset: blockStart, count: prefixLength },
54
+ { type: 'set_block_type', blockId, blockType: 'hr' },
55
+ ]);
56
+ // After the first dispatch, the block is now an empty hr block.
57
+ // Split at the end of the hr block to create a new text block below.
58
+ // Note: split_block inherits the source block's type, so the new
59
+ // block will also be 'hr'. We must set it back to 'text'.
60
+ const updatedDoc = engine.state.doc;
61
+ const hrBlockStart = getBlockStartOffset(updatedDoc, blockId);
62
+ const hrBlock = updatedDoc.blocks.find((b) => b.id === blockId);
63
+ const hrLength = hrBlock ? blockTextLength(hrBlock) : 0;
64
+ const splitOffset = hrBlockStart + hrLength;
65
+ const newBlockId = `${blockId}_after`;
66
+ engine.dispatch([
67
+ { type: 'split_block', offset: splitOffset, newBlockId },
68
+ { type: 'set_block_type', blockId: newBlockId, blockType: 'text' },
69
+ ]);
70
+ },
71
+ });
72
+ },
73
+ };
74
+ }
75
+ //# sourceMappingURL=hr-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hr-plugin.js","sourceRoot":"","sources":["../../src/plugins/hr-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO;QACL,EAAE,EAAE,UAAU;QACd,IAAI,CAAC,GAAG;YACN,kEAAkE;YAClE,0BAA0B;YAC1B,kEAAkE;YAElE,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAEhC,kEAAkE;YAClE,0EAA0E;YAC1E,kEAAkE;YAElE,GAAG,CAAC,iBAAiB,CAAC;gBACpB,OAAO,EAAE,OAAO;gBAChB,SAAS,EAAE,IAAI;gBACf,OAAO,CAAC,MAAqB,EAAE,KAAuB,EAAE,OAAe;oBACrE,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;oBAClE,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;oBAEtC,kEAAkE;oBAClE,iDAAiD;oBACjD,MAAM,CAAC,QAAQ,CAAC;wBACd,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE;wBAChE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;qBACrD,CAAC,CAAC;oBAEH,gEAAgE;oBAChE,qEAAqE;oBACrE,iEAAiE;oBACjE,0DAA0D;oBAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;oBACpC,MAAM,YAAY,GAAG,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;oBAC9D,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;oBAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACxD,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;oBAC5C,MAAM,UAAU,GAAG,GAAG,OAAO,QAAQ,CAAC;oBAEtC,MAAM,CAAC,QAAQ,CAAC;wBACd,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE;wBACxD,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE;qBACnE,CAAC,CAAC;gBACL,CAAC;aACF,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Image block type plugin — registers the `image` block type, `insertImage`,
3
+ * `updateImage`, and `removeImage` commands.
4
+ *
5
+ * Image blocks are atomic (non-editable) blocks that display an image.
6
+ * They store `src`, `alt`, `width`, and `height` in block attrs.
7
+ * Like all RTIF blocks, image blocks still contain at least one span
8
+ * (a single empty span `[{ text: '' }]`) to satisfy the document invariant.
9
+ *
10
+ * @module
11
+ */
12
+ import type { Plugin } from '@rtif-sdk/engine';
13
+ /**
14
+ * Command name constants for the image plugin.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * engine.exec(ImageCommands.INSERT, { src: 'https://example.com/photo.jpg' });
19
+ * engine.exec(ImageCommands.UPDATE, { blockId: 'img-1', attrs: { alt: 'Photo' } });
20
+ * engine.exec(ImageCommands.REMOVE, { blockId: 'img-1' });
21
+ * ```
22
+ */
23
+ export declare const ImageCommands: {
24
+ readonly INSERT: "insertImage";
25
+ readonly UPDATE: "updateImage";
26
+ readonly REMOVE: "removeImage";
27
+ };
28
+ /**
29
+ * Payload for the `insertImage` command.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * engine.exec('insertImage', {
34
+ * src: 'https://example.com/photo.jpg',
35
+ * alt: 'A scenic mountain view',
36
+ * width: 800,
37
+ * height: 600,
38
+ * });
39
+ * ```
40
+ */
41
+ export interface InsertImagePayload {
42
+ /** The image source URL (required) */
43
+ readonly src: string;
44
+ /** Alternative text for accessibility */
45
+ readonly alt?: string;
46
+ /** Image display width in pixels */
47
+ readonly width?: number;
48
+ /** Image display height in pixels */
49
+ readonly height?: number;
50
+ }
51
+ /**
52
+ * Payload for the `updateImage` command.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * engine.exec('updateImage', {
57
+ * blockId: 'img-1',
58
+ * attrs: { alt: 'Updated description', width: 640 },
59
+ * });
60
+ * ```
61
+ */
62
+ export interface UpdateImagePayload {
63
+ /** The ID of the image block to update */
64
+ readonly blockId: string;
65
+ /** Partial attributes to merge onto the image block */
66
+ readonly attrs: Partial<{
67
+ readonly src: string;
68
+ readonly alt: string;
69
+ readonly width: number;
70
+ readonly height: number;
71
+ }>;
72
+ }
73
+ /**
74
+ * Payload for the `removeImage` command.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * engine.exec('removeImage', { blockId: 'img-1' });
79
+ * ```
80
+ */
81
+ export interface RemoveImagePayload {
82
+ /** The ID of the image block to remove */
83
+ readonly blockId: string;
84
+ }
85
+ /**
86
+ * Create the image block type plugin.
87
+ *
88
+ * Registers:
89
+ * - Block type: `image` (attrs must have `src` as a non-empty string)
90
+ * - Command: `insertImage` — inserts a new image block after the current block
91
+ * - Command: `updateImage` — updates an image block's attributes
92
+ * - Command: `removeImage` — converts an image block back to an empty text block
93
+ *
94
+ * No input rules or keyboard shortcuts are registered — image insertion is
95
+ * driven by toolbar buttons, drag-and-drop, or programmatic calls.
96
+ *
97
+ * @returns A plugin instance ready for `engine.use()`
98
+ *
99
+ * @example
100
+ * ```ts
101
+ * const engine = createEngine(initialDoc);
102
+ * engine.use(imagePlugin());
103
+ *
104
+ * // Insert an image after the current block
105
+ * engine.exec(ImageCommands.INSERT, { src: 'https://example.com/photo.jpg' });
106
+ *
107
+ * // Update an existing image block
108
+ * engine.exec(ImageCommands.UPDATE, { blockId: 'b2', attrs: { alt: 'Photo' } });
109
+ *
110
+ * // Remove an image block (converts to empty text block)
111
+ * engine.exec(ImageCommands.REMOVE, { blockId: 'b2' });
112
+ * ```
113
+ */
114
+ export declare function imagePlugin(): Plugin;
115
+ //# sourceMappingURL=image-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/image-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,kBAAkB,CAAC;AAK9D;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAEX;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;CACJ;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAkKpC"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * Image block type plugin — registers the `image` block type, `insertImage`,
3
+ * `updateImage`, and `removeImage` commands.
4
+ *
5
+ * Image blocks are atomic (non-editable) blocks that display an image.
6
+ * They store `src`, `alt`, `width`, and `height` in block attrs.
7
+ * Like all RTIF blocks, image blocks still contain at least one span
8
+ * (a single empty span `[{ text: '' }]`) to satisfy the document invariant.
9
+ *
10
+ * @module
11
+ */
12
+ import { blockTextLength } from '@rtif-sdk/core';
13
+ import { getBlockAtCursor, getBlockStartOffset } from './block-utils.js';
14
+ /**
15
+ * Command name constants for the image plugin.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * engine.exec(ImageCommands.INSERT, { src: 'https://example.com/photo.jpg' });
20
+ * engine.exec(ImageCommands.UPDATE, { blockId: 'img-1', attrs: { alt: 'Photo' } });
21
+ * engine.exec(ImageCommands.REMOVE, { blockId: 'img-1' });
22
+ * ```
23
+ */
24
+ export const ImageCommands = {
25
+ INSERT: 'insertImage',
26
+ UPDATE: 'updateImage',
27
+ REMOVE: 'removeImage',
28
+ };
29
+ /**
30
+ * Create the image block type plugin.
31
+ *
32
+ * Registers:
33
+ * - Block type: `image` (attrs must have `src` as a non-empty string)
34
+ * - Command: `insertImage` — inserts a new image block after the current block
35
+ * - Command: `updateImage` — updates an image block's attributes
36
+ * - Command: `removeImage` — converts an image block back to an empty text block
37
+ *
38
+ * No input rules or keyboard shortcuts are registered — image insertion is
39
+ * driven by toolbar buttons, drag-and-drop, or programmatic calls.
40
+ *
41
+ * @returns A plugin instance ready for `engine.use()`
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * const engine = createEngine(initialDoc);
46
+ * engine.use(imagePlugin());
47
+ *
48
+ * // Insert an image after the current block
49
+ * engine.exec(ImageCommands.INSERT, { src: 'https://example.com/photo.jpg' });
50
+ *
51
+ * // Update an existing image block
52
+ * engine.exec(ImageCommands.UPDATE, { blockId: 'b2', attrs: { alt: 'Photo' } });
53
+ *
54
+ * // Remove an image block (converts to empty text block)
55
+ * engine.exec(ImageCommands.REMOVE, { blockId: 'b2' });
56
+ * ```
57
+ */
58
+ export function imagePlugin() {
59
+ return {
60
+ id: 'block-image',
61
+ init(ctx) {
62
+ // ---------------------------------------------------------------
63
+ // Block type registration
64
+ // ---------------------------------------------------------------
65
+ ctx.registerBlockType('image', {
66
+ validate: (attrs) => {
67
+ return typeof attrs.src === 'string' && attrs.src.length > 0;
68
+ },
69
+ });
70
+ // ---------------------------------------------------------------
71
+ // insertImage command
72
+ // ---------------------------------------------------------------
73
+ ctx.registerCommand(ImageCommands.INSERT, {
74
+ execute(engine, payload) {
75
+ const p = payload;
76
+ if (!p || typeof p.src !== 'string' || p.src.length === 0)
77
+ return;
78
+ const block = getBlockAtCursor(engine);
79
+ const blockStart = getBlockStartOffset(engine.state.doc, block.id);
80
+ const blockLen = blockTextLength(block);
81
+ const splitOffset = blockStart + blockLen;
82
+ // Generate a deterministic new block ID
83
+ const newBlockId = `${block.id}_img`;
84
+ // Build the attrs object for the new image block
85
+ const attrs = { src: p.src };
86
+ if (p.alt !== undefined)
87
+ attrs.alt = p.alt;
88
+ if (p.width !== undefined)
89
+ attrs.width = p.width;
90
+ if (p.height !== undefined)
91
+ attrs.height = p.height;
92
+ // Split at end of current block, then configure the new block
93
+ // as an image. split_block inherits the parent block type, so
94
+ // we must explicitly set the new block to 'image'.
95
+ engine.dispatch([
96
+ { type: 'split_block', offset: splitOffset, newBlockId },
97
+ { type: 'set_block_type', blockId: newBlockId, blockType: 'image' },
98
+ { type: 'set_block_attrs', blockId: newBlockId, attrs },
99
+ ]);
100
+ },
101
+ canExecute(_engine) {
102
+ return true;
103
+ },
104
+ isActive(engine) {
105
+ const block = getBlockAtCursor(engine);
106
+ return block.type === 'image';
107
+ },
108
+ });
109
+ // ---------------------------------------------------------------
110
+ // updateImage command
111
+ // ---------------------------------------------------------------
112
+ ctx.registerCommand(ImageCommands.UPDATE, {
113
+ execute(engine, payload) {
114
+ const p = payload;
115
+ if (!p || typeof p.blockId !== 'string')
116
+ return;
117
+ if (!p.attrs || typeof p.attrs !== 'object')
118
+ return;
119
+ // Verify the target block exists and is an image
120
+ const block = engine.state.doc.blocks.find((b) => b.id === p.blockId);
121
+ if (!block || block.type !== 'image')
122
+ return;
123
+ // Build the attrs update, only including defined keys
124
+ const attrs = {};
125
+ if (p.attrs.src !== undefined)
126
+ attrs.src = p.attrs.src;
127
+ if (p.attrs.alt !== undefined)
128
+ attrs.alt = p.attrs.alt;
129
+ if (p.attrs.width !== undefined)
130
+ attrs.width = p.attrs.width;
131
+ if (p.attrs.height !== undefined)
132
+ attrs.height = p.attrs.height;
133
+ if (Object.keys(attrs).length === 0)
134
+ return;
135
+ engine.dispatch({
136
+ type: 'set_block_attrs',
137
+ blockId: p.blockId,
138
+ attrs,
139
+ });
140
+ },
141
+ canExecute(engine, payload) {
142
+ const p = payload;
143
+ if (!p || typeof p.blockId !== 'string')
144
+ return false;
145
+ const block = engine.state.doc.blocks.find((b) => b.id === p.blockId);
146
+ return block !== undefined && block.type === 'image';
147
+ },
148
+ });
149
+ // ---------------------------------------------------------------
150
+ // removeImage command
151
+ // ---------------------------------------------------------------
152
+ ctx.registerCommand(ImageCommands.REMOVE, {
153
+ execute(engine, payload) {
154
+ const p = payload;
155
+ if (!p || typeof p.blockId !== 'string')
156
+ return;
157
+ // Verify the target block exists and is an image
158
+ const block = engine.state.doc.blocks.find((b) => b.id === p.blockId);
159
+ if (!block || block.type !== 'image')
160
+ return;
161
+ // Convert the image block to an empty text block:
162
+ // 1. Delete any text content (image blocks should be empty, but
163
+ // handle defensively)
164
+ // 2. Set block type back to 'text'
165
+ // 3. Clear image-specific attrs
166
+ const ops = [];
167
+ const textLen = blockTextLength(block);
168
+ if (textLen > 0) {
169
+ const blockStart = getBlockStartOffset(engine.state.doc, p.blockId);
170
+ ops.push({
171
+ type: 'delete_text',
172
+ offset: blockStart,
173
+ count: textLen,
174
+ });
175
+ }
176
+ ops.push({
177
+ type: 'set_block_type',
178
+ blockId: p.blockId,
179
+ blockType: 'text',
180
+ });
181
+ ops.push({
182
+ type: 'set_block_attrs',
183
+ blockId: p.blockId,
184
+ attrs: { src: null, alt: null, width: null, height: null },
185
+ });
186
+ engine.dispatch(ops);
187
+ },
188
+ canExecute(engine, payload) {
189
+ const p = payload;
190
+ if (!p || typeof p.blockId !== 'string')
191
+ return false;
192
+ const block = engine.state.doc.blocks.find((b) => b.id === p.blockId);
193
+ return block !== undefined && block.type === 'image';
194
+ },
195
+ });
196
+ },
197
+ };
198
+ }
199
+ //# sourceMappingURL=image-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-plugin.js","sourceRoot":"","sources":["../../src/plugins/image-plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Indent paragraph formatting plugin — registers `indent` and `outdent`
3
+ * commands that increment or decrement the `indent` block attr.
4
+ *
5
+ * Unlike block type plugins, the indent plugin does NOT change the block's
6
+ * `type`. It works on any block type by setting `attrs.indent` via
7
+ * `set_block_attrs`.
8
+ *
9
+ * @module
10
+ */
11
+ import type { Plugin } from '@rtif-sdk/engine';
12
+ /**
13
+ * Command name constants for the indent plugin.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * engine.exec(IndentCommands.INDENT);
18
+ * engine.exec(IndentCommands.OUTDENT);
19
+ * ```
20
+ */
21
+ export declare const IndentCommands: {
22
+ readonly INDENT: "indent";
23
+ readonly OUTDENT: "outdent";
24
+ };
25
+ /**
26
+ * Maximum indent level. `indent` command stops incrementing at this value.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { MAX_INDENT } from './indent-plugin.js';
31
+ * console.log(MAX_INDENT); // 8
32
+ * ```
33
+ */
34
+ export declare const MAX_INDENT = 8;
35
+ /**
36
+ * Create the indent paragraph formatting plugin.
37
+ *
38
+ * Registers two commands:
39
+ * - `indent` — increments the `indent` attr by 1 (max {@link MAX_INDENT}).
40
+ * `canExecute()` returns `false` when already at the maximum.
41
+ * - `outdent` — decrements the `indent` attr by 1. At 0 or undefined,
42
+ * removes the attr. `canExecute()` returns `false` when indent is 0
43
+ * or undefined.
44
+ *
45
+ * No input rules, no keyboard shortcuts, no block type registrations.
46
+ *
47
+ * @returns A plugin instance ready for `engine.use()`
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * const engine = createEngine(initialDoc);
52
+ * engine.use(indentPlugin());
53
+ *
54
+ * // Indent the block at the cursor
55
+ * engine.exec(IndentCommands.INDENT);
56
+ *
57
+ * // Outdent the block at the cursor
58
+ * engine.exec(IndentCommands.OUTDENT);
59
+ * ```
60
+ */
61
+ export declare function indentPlugin(): Plugin;
62
+ //# sourceMappingURL=indent-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent-plugin.d.ts","sourceRoot":"","sources":["../../src/plugins/indent-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,kBAAkB,CAAC;AAG9D;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,IAAI,CAAC;AAe5B;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,IAAI,MAAM,CA0DrC"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Indent paragraph formatting plugin — registers `indent` and `outdent`
3
+ * commands that increment or decrement the `indent` block attr.
4
+ *
5
+ * Unlike block type plugins, the indent plugin does NOT change the block's
6
+ * `type`. It works on any block type by setting `attrs.indent` via
7
+ * `set_block_attrs`.
8
+ *
9
+ * @module
10
+ */
11
+ import { getBlockAtCursor } from './block-utils.js';
12
+ /**
13
+ * Command name constants for the indent plugin.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * engine.exec(IndentCommands.INDENT);
18
+ * engine.exec(IndentCommands.OUTDENT);
19
+ * ```
20
+ */
21
+ export const IndentCommands = {
22
+ INDENT: 'indent',
23
+ OUTDENT: 'outdent',
24
+ };
25
+ /**
26
+ * Maximum indent level. `indent` command stops incrementing at this value.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { MAX_INDENT } from './indent-plugin.js';
31
+ * console.log(MAX_INDENT); // 8
32
+ * ```
33
+ */
34
+ export const MAX_INDENT = 8;
35
+ /**
36
+ * Read the current indent level of the cursor block, defaulting to 0 when
37
+ * no `indent` attr is present.
38
+ *
39
+ * @param engine - The editor engine instance
40
+ * @returns The current indent level (0 when unset)
41
+ */
42
+ function getCurrentIndent(engine) {
43
+ const block = getBlockAtCursor(engine);
44
+ const indent = block.attrs?.indent;
45
+ return typeof indent === 'number' ? indent : 0;
46
+ }
47
+ /**
48
+ * Create the indent paragraph formatting plugin.
49
+ *
50
+ * Registers two commands:
51
+ * - `indent` — increments the `indent` attr by 1 (max {@link MAX_INDENT}).
52
+ * `canExecute()` returns `false` when already at the maximum.
53
+ * - `outdent` — decrements the `indent` attr by 1. At 0 or undefined,
54
+ * removes the attr. `canExecute()` returns `false` when indent is 0
55
+ * or undefined.
56
+ *
57
+ * No input rules, no keyboard shortcuts, no block type registrations.
58
+ *
59
+ * @returns A plugin instance ready for `engine.use()`
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const engine = createEngine(initialDoc);
64
+ * engine.use(indentPlugin());
65
+ *
66
+ * // Indent the block at the cursor
67
+ * engine.exec(IndentCommands.INDENT);
68
+ *
69
+ * // Outdent the block at the cursor
70
+ * engine.exec(IndentCommands.OUTDENT);
71
+ * ```
72
+ */
73
+ export function indentPlugin() {
74
+ return {
75
+ id: 'attr-indent',
76
+ init(ctx) {
77
+ // ---------------------------------------------------------------
78
+ // indent command
79
+ // ---------------------------------------------------------------
80
+ ctx.registerCommand(IndentCommands.INDENT, {
81
+ execute(engine) {
82
+ const block = getBlockAtCursor(engine);
83
+ const current = getCurrentIndent(engine);
84
+ if (current >= MAX_INDENT)
85
+ return;
86
+ engine.dispatch({
87
+ type: 'set_block_attrs',
88
+ blockId: block.id,
89
+ attrs: { indent: current + 1 },
90
+ });
91
+ },
92
+ canExecute(engine) {
93
+ return getCurrentIndent(engine) < MAX_INDENT;
94
+ },
95
+ });
96
+ // ---------------------------------------------------------------
97
+ // outdent command
98
+ // ---------------------------------------------------------------
99
+ ctx.registerCommand(IndentCommands.OUTDENT, {
100
+ execute(engine) {
101
+ const block = getBlockAtCursor(engine);
102
+ const current = getCurrentIndent(engine);
103
+ if (current <= 0)
104
+ return;
105
+ if (current === 1) {
106
+ // Going to 0 — remove the attr entirely
107
+ engine.dispatch({
108
+ type: 'set_block_attrs',
109
+ blockId: block.id,
110
+ attrs: { indent: null },
111
+ });
112
+ }
113
+ else {
114
+ engine.dispatch({
115
+ type: 'set_block_attrs',
116
+ blockId: block.id,
117
+ attrs: { indent: current - 1 },
118
+ });
119
+ }
120
+ },
121
+ canExecute(engine) {
122
+ return getCurrentIndent(engine) > 0;
123
+ },
124
+ });
125
+ },
126
+ };
127
+ }
128
+ //# sourceMappingURL=indent-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indent-plugin.js","sourceRoot":"","sources":["../../src/plugins/indent-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;CACV,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC;AAE5B;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,MAAqB;IAC7C,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC;IACnC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO;QACL,EAAE,EAAE,aAAa;QACjB,IAAI,CAAC,GAAG;YACN,kEAAkE;YAClE,iBAAiB;YACjB,kEAAkE;YAElE,GAAG,CAAC,eAAe,CAAC,cAAc,CAAC,MAAM,EAAE;gBACzC,OAAO,CAAC,MAAqB;oBAC3B,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;oBACzC,IAAI,OAAO,IAAI,UAAU;wBAAE,OAAO;oBAElC,MAAM,CAAC,QAAQ,CAAC;wBACd,IAAI,EAAE,iBAAiB;wBACvB,OAAO,EAAE,KAAK,CAAC,EAAE;wBACjB,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE;qBAC/B,CAAC,CAAC;gBACL,CAAC;gBAED,UAAU,CAAC,MAAqB;oBAC9B,OAAO,gBAAgB,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC;gBAC/C,CAAC;aACF,CAAC,CAAC;YAEH,kEAAkE;YAClE,kBAAkB;YAClB,kEAAkE;YAElE,GAAG,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,EAAE;gBAC1C,OAAO,CAAC,MAAqB;oBAC3B,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;oBACvC,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;oBACzC,IAAI,OAAO,IAAI,CAAC;wBAAE,OAAO;oBAEzB,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;wBAClB,wCAAwC;wBACxC,MAAM,CAAC,QAAQ,CAAC;4BACd,IAAI,EAAE,iBAAiB;4BACvB,OAAO,EAAE,KAAK,CAAC,EAAE;4BACjB,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;yBACxB,CAAC,CAAC;oBACL,CAAC;yBAAM,CAAC;wBACN,MAAM,CAAC,QAAQ,CAAC;4BACd,IAAI,EAAE,iBAAiB;4BACvB,OAAO,EAAE,KAAK,CAAC,EAAE;4BACjB,KAAK,EAAE,EAAE,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE;yBAC/B,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAED,UAAU,CAAC,MAAqB;oBAC9B,OAAO,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACtC,CAAC;aACF,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Plugins and shared utilities for the RTIF web editor.
3
+ *
4
+ * Mark plugins register mark types, toggle commands, and keyboard shortcuts.
5
+ * Block utilities provide shared helpers for block type plugins.
6
+ * Load only the plugins you need.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ export { createToggleMarkCommand, toggleMark, isMarkActiveAtSelection, createSetMarkCommand, createRemoveMarkCommand, findContiguousMarkRange, adjustOffsetAroundAtomicMarks, adjustOffsetAroundAtomicBlocks, } from './mark-utils.js';
11
+ export { getBlockStartOffset, getBlockAtCursor, isBlockType, createToggleBlockTypeCommand, setBlockType, } from './block-utils.js';
12
+ export { boldPlugin, BoldCommands } from './bold-plugin.js';
13
+ export { italicPlugin, ItalicCommands } from './italic-plugin.js';
14
+ export { underlinePlugin, UnderlineCommands } from './underline-plugin.js';
15
+ export { strikethroughPlugin, StrikethroughCommands } from './strikethrough-plugin.js';
16
+ export { codePlugin, CodeMarkCommands } from './code-plugin.js';
17
+ export { linkPlugin, createLinkPlugin, LinkCommands } from './link-plugin.js';
18
+ export type { InsertLinkPayload, UpdateLinkPayload, ShowLinkUICallback, LinkPluginResult, } from './link-plugin.js';
19
+ export { textColorPlugin, TextColorCommands } from './text-color-plugin.js';
20
+ export type { SetTextColorPayload } from './text-color-plugin.js';
21
+ export { fontSizePlugin, FontSizeCommands } from './font-size-plugin.js';
22
+ export type { SetFontSizePayload } from './font-size-plugin.js';
23
+ export { fontFamilyPlugin, FontFamilyCommands } from './font-family-plugin.js';
24
+ export type { SetFontFamilyPayload } from './font-family-plugin.js';
25
+ export { headingPlugin, HeadingCommands } from './heading-plugin.js';
26
+ export type { ToggleHeadingPayload } from './heading-plugin.js';
27
+ export { listPlugin, ListCommands } from './list-plugin.js';
28
+ export { blockquotePlugin, BlockquoteCommands } from './blockquote-plugin.js';
29
+ export { codeBlockPlugin, CodeBlockCommands } from './code-block-plugin.js';
30
+ export type { SetCodeLanguagePayload } from './code-block-plugin.js';
31
+ export { hrPlugin } from './hr-plugin.js';
32
+ export { calloutPlugin, CalloutCommands } from './callout-plugin.js';
33
+ export type { CalloutVariant, InsertCalloutPayload, SetCalloutVariantPayload, } from './callout-plugin.js';
34
+ export { embedPlugin, EmbedCommands } from './embed-plugin.js';
35
+ export type { EmbedType, InsertEmbedPayload, RemoveEmbedPayload, } from './embed-plugin.js';
36
+ export { alignmentPlugin, AlignmentCommands } from './alignment-plugin.js';
37
+ export type { Alignment } from './alignment-plugin.js';
38
+ export { indentPlugin, IndentCommands, MAX_INDENT } from './indent-plugin.js';
39
+ export { imagePlugin, ImageCommands } from './image-plugin.js';
40
+ export type { InsertImagePayload, UpdateImagePayload, RemoveImagePayload, } from './image-plugin.js';
41
+ export { defineBooleanMark, defineParameterizedMark, defineBlockType, installWebPlugins, } from '../plugin-kit.js';
42
+ export type { WebPlugin, BooleanMarkDef, ParameterizedMarkDef, SetMarkCommandDef, BlockTypeDef, BlockInputRuleDef, BlockShortcutDef, } from '../plugin-kit.js';
43
+ export { createMentionPlugin, MentionCommands, mentionPlaintextSerializer, mentionMarkdownSerializer, mentionHtmlSerializer, } from './mention-plugin.js';
44
+ export type { MentionMark, MentionSession, MentionPluginConfig, MentionPluginResult, } from './mention-plugin.js';
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,4BAA4B,EAC5B,YAAY,GACb,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGhE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzE,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACrE,YAAY,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACrE,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EACV,SAAS,EACT,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,SAAS,EACT,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC"}