@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.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/block-drag-handler.d.ts +189 -0
- package/dist/block-drag-handler.d.ts.map +1 -0
- package/dist/block-drag-handler.js +745 -0
- package/dist/block-drag-handler.js.map +1 -0
- package/dist/block-renderer.d.ts +402 -0
- package/dist/block-renderer.d.ts.map +1 -0
- package/dist/block-renderer.js +424 -0
- package/dist/block-renderer.js.map +1 -0
- package/dist/clipboard.d.ts +178 -0
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +432 -0
- package/dist/clipboard.js.map +1 -0
- package/dist/command-bus.d.ts +113 -0
- package/dist/command-bus.d.ts.map +1 -0
- package/dist/command-bus.js +70 -0
- package/dist/command-bus.js.map +1 -0
- package/dist/composition.d.ts +220 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +271 -0
- package/dist/composition.js.map +1 -0
- package/dist/content-extraction.d.ts +69 -0
- package/dist/content-extraction.d.ts.map +1 -0
- package/dist/content-extraction.js +228 -0
- package/dist/content-extraction.js.map +1 -0
- package/dist/content-handler-file.d.ts +40 -0
- package/dist/content-handler-file.d.ts.map +1 -0
- package/dist/content-handler-file.js +91 -0
- package/dist/content-handler-file.js.map +1 -0
- package/dist/content-handler-image.d.ts +82 -0
- package/dist/content-handler-image.d.ts.map +1 -0
- package/dist/content-handler-image.js +120 -0
- package/dist/content-handler-image.js.map +1 -0
- package/dist/content-handler-url.d.ts +129 -0
- package/dist/content-handler-url.d.ts.map +1 -0
- package/dist/content-handler-url.js +244 -0
- package/dist/content-handler-url.js.map +1 -0
- package/dist/content-handlers.d.ts +67 -0
- package/dist/content-handlers.d.ts.map +1 -0
- package/dist/content-handlers.js +263 -0
- package/dist/content-handlers.js.map +1 -0
- package/dist/content-pipeline.d.ts +383 -0
- package/dist/content-pipeline.d.ts.map +1 -0
- package/dist/content-pipeline.js +232 -0
- package/dist/content-pipeline.js.map +1 -0
- package/dist/cursor-nav.d.ts +149 -0
- package/dist/cursor-nav.d.ts.map +1 -0
- package/dist/cursor-nav.js +230 -0
- package/dist/cursor-nav.js.map +1 -0
- package/dist/cursor-rect.d.ts +65 -0
- package/dist/cursor-rect.d.ts.map +1 -0
- package/dist/cursor-rect.js +98 -0
- package/dist/cursor-rect.js.map +1 -0
- package/dist/drop-indicator.d.ts +108 -0
- package/dist/drop-indicator.d.ts.map +1 -0
- package/dist/drop-indicator.js +236 -0
- package/dist/drop-indicator.js.map +1 -0
- package/dist/editor.d.ts +41 -0
- package/dist/editor.d.ts.map +1 -0
- package/dist/editor.js +710 -0
- package/dist/editor.js.map +1 -0
- package/dist/floating-toolbar.d.ts +93 -0
- package/dist/floating-toolbar.d.ts.map +1 -0
- package/dist/floating-toolbar.js +159 -0
- package/dist/floating-toolbar.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -0
- package/dist/input-bridge.d.ts +273 -0
- package/dist/input-bridge.d.ts.map +1 -0
- package/dist/input-bridge.js +884 -0
- package/dist/input-bridge.js.map +1 -0
- package/dist/link-popover.d.ts +38 -0
- package/dist/link-popover.d.ts.map +1 -0
- package/dist/link-popover.js +278 -0
- package/dist/link-popover.js.map +1 -0
- package/dist/mark-renderer.d.ts +275 -0
- package/dist/mark-renderer.d.ts.map +1 -0
- package/dist/mark-renderer.js +210 -0
- package/dist/mark-renderer.js.map +1 -0
- package/dist/perf.d.ts +145 -0
- package/dist/perf.d.ts.map +1 -0
- package/dist/perf.js +260 -0
- package/dist/perf.js.map +1 -0
- package/dist/plugin-kit.d.ts +265 -0
- package/dist/plugin-kit.d.ts.map +1 -0
- package/dist/plugin-kit.js +234 -0
- package/dist/plugin-kit.js.map +1 -0
- package/dist/plugins/alignment-plugin.d.ts +68 -0
- package/dist/plugins/alignment-plugin.d.ts.map +1 -0
- package/dist/plugins/alignment-plugin.js +98 -0
- package/dist/plugins/alignment-plugin.js.map +1 -0
- package/dist/plugins/block-utils.d.ts +113 -0
- package/dist/plugins/block-utils.d.ts.map +1 -0
- package/dist/plugins/block-utils.js +191 -0
- package/dist/plugins/block-utils.js.map +1 -0
- package/dist/plugins/blockquote-plugin.d.ts +39 -0
- package/dist/plugins/blockquote-plugin.d.ts.map +1 -0
- package/dist/plugins/blockquote-plugin.js +88 -0
- package/dist/plugins/blockquote-plugin.js.map +1 -0
- package/dist/plugins/bold-plugin.d.ts +37 -0
- package/dist/plugins/bold-plugin.d.ts.map +1 -0
- package/dist/plugins/bold-plugin.js +48 -0
- package/dist/plugins/bold-plugin.js.map +1 -0
- package/dist/plugins/callout-plugin.d.ts +100 -0
- package/dist/plugins/callout-plugin.d.ts.map +1 -0
- package/dist/plugins/callout-plugin.js +200 -0
- package/dist/plugins/callout-plugin.js.map +1 -0
- package/dist/plugins/code-block-plugin.d.ts +62 -0
- package/dist/plugins/code-block-plugin.d.ts.map +1 -0
- package/dist/plugins/code-block-plugin.js +176 -0
- package/dist/plugins/code-block-plugin.js.map +1 -0
- package/dist/plugins/code-plugin.d.ts +37 -0
- package/dist/plugins/code-plugin.d.ts.map +1 -0
- package/dist/plugins/code-plugin.js +48 -0
- package/dist/plugins/code-plugin.js.map +1 -0
- package/dist/plugins/embed-plugin.d.ts +90 -0
- package/dist/plugins/embed-plugin.d.ts.map +1 -0
- package/dist/plugins/embed-plugin.js +147 -0
- package/dist/plugins/embed-plugin.js.map +1 -0
- package/dist/plugins/font-family-plugin.d.ts +58 -0
- package/dist/plugins/font-family-plugin.d.ts.map +1 -0
- package/dist/plugins/font-family-plugin.js +57 -0
- package/dist/plugins/font-family-plugin.js.map +1 -0
- package/dist/plugins/font-size-plugin.d.ts +57 -0
- package/dist/plugins/font-size-plugin.d.ts.map +1 -0
- package/dist/plugins/font-size-plugin.js +56 -0
- package/dist/plugins/font-size-plugin.js.map +1 -0
- package/dist/plugins/heading-plugin.d.ts +52 -0
- package/dist/plugins/heading-plugin.d.ts.map +1 -0
- package/dist/plugins/heading-plugin.js +114 -0
- package/dist/plugins/heading-plugin.js.map +1 -0
- package/dist/plugins/hr-plugin.d.ts +33 -0
- package/dist/plugins/hr-plugin.d.ts.map +1 -0
- package/dist/plugins/hr-plugin.js +75 -0
- package/dist/plugins/hr-plugin.js.map +1 -0
- package/dist/plugins/image-plugin.d.ts +115 -0
- package/dist/plugins/image-plugin.d.ts.map +1 -0
- package/dist/plugins/image-plugin.js +199 -0
- package/dist/plugins/image-plugin.js.map +1 -0
- package/dist/plugins/indent-plugin.d.ts +62 -0
- package/dist/plugins/indent-plugin.d.ts.map +1 -0
- package/dist/plugins/indent-plugin.js +128 -0
- package/dist/plugins/indent-plugin.js.map +1 -0
- package/dist/plugins/index.d.ts +45 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +42 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/italic-plugin.d.ts +37 -0
- package/dist/plugins/italic-plugin.d.ts.map +1 -0
- package/dist/plugins/italic-plugin.js +48 -0
- package/dist/plugins/italic-plugin.js.map +1 -0
- package/dist/plugins/link-plugin.d.ts +129 -0
- package/dist/plugins/link-plugin.d.ts.map +1 -0
- package/dist/plugins/link-plugin.js +212 -0
- package/dist/plugins/link-plugin.js.map +1 -0
- package/dist/plugins/list-plugin.d.ts +53 -0
- package/dist/plugins/list-plugin.d.ts.map +1 -0
- package/dist/plugins/list-plugin.js +309 -0
- package/dist/plugins/list-plugin.js.map +1 -0
- package/dist/plugins/mark-utils.d.ts +173 -0
- package/dist/plugins/mark-utils.d.ts.map +1 -0
- package/dist/plugins/mark-utils.js +425 -0
- package/dist/plugins/mark-utils.js.map +1 -0
- package/dist/plugins/mention-plugin.d.ts +191 -0
- package/dist/plugins/mention-plugin.d.ts.map +1 -0
- package/dist/plugins/mention-plugin.js +295 -0
- package/dist/plugins/mention-plugin.js.map +1 -0
- package/dist/plugins/strikethrough-plugin.d.ts +37 -0
- package/dist/plugins/strikethrough-plugin.d.ts.map +1 -0
- package/dist/plugins/strikethrough-plugin.js +48 -0
- package/dist/plugins/strikethrough-plugin.js.map +1 -0
- package/dist/plugins/text-color-plugin.d.ts +57 -0
- package/dist/plugins/text-color-plugin.d.ts.map +1 -0
- package/dist/plugins/text-color-plugin.js +56 -0
- package/dist/plugins/text-color-plugin.js.map +1 -0
- package/dist/plugins/underline-plugin.d.ts +37 -0
- package/dist/plugins/underline-plugin.d.ts.map +1 -0
- package/dist/plugins/underline-plugin.js +48 -0
- package/dist/plugins/underline-plugin.js.map +1 -0
- package/dist/presets.d.ts +95 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +159 -0
- package/dist/presets.js.map +1 -0
- package/dist/renderer.d.ts +125 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +415 -0
- package/dist/renderer.js.map +1 -0
- package/dist/scroll-to-cursor.d.ts +25 -0
- package/dist/scroll-to-cursor.d.ts.map +1 -0
- package/dist/scroll-to-cursor.js +59 -0
- package/dist/scroll-to-cursor.js.map +1 -0
- package/dist/selection-sync.d.ts +159 -0
- package/dist/selection-sync.d.ts.map +1 -0
- package/dist/selection-sync.js +527 -0
- package/dist/selection-sync.js.map +1 -0
- package/dist/shortcut-handler.d.ts +98 -0
- package/dist/shortcut-handler.d.ts.map +1 -0
- package/dist/shortcut-handler.js +155 -0
- package/dist/shortcut-handler.js.map +1 -0
- package/dist/toolbar.d.ts +103 -0
- package/dist/toolbar.d.ts.map +1 -0
- package/dist/toolbar.js +134 -0
- package/dist/toolbar.js.map +1 -0
- package/dist/trigger-manager.d.ts +205 -0
- package/dist/trigger-manager.d.ts.map +1 -0
- package/dist/trigger-manager.js +466 -0
- package/dist/trigger-manager.js.map +1 -0
- package/dist/types.d.ts +216 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- 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":"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"}
|