@blankdotpage/cake 0.1.15 → 0.1.17

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 (69) hide show
  1. package/README.md +4 -0
  2. package/dist/cake/core/runtime.d.ts +32 -72
  3. package/dist/cake/core/runtime.d.ts.map +1 -1
  4. package/dist/cake/core/runtime.js +149 -85
  5. package/dist/cake/dom/dom-map.d.ts.map +1 -1
  6. package/dist/cake/dom/dom-map.js +3 -1
  7. package/dist/cake/dom/render.d.ts +3 -3
  8. package/dist/cake/dom/render.d.ts.map +1 -1
  9. package/dist/cake/dom/render.js +12 -27
  10. package/dist/cake/editor/cake-editor.d.ts +57 -5
  11. package/dist/cake/editor/cake-editor.d.ts.map +1 -1
  12. package/dist/cake/editor/cake-editor.js +306 -69
  13. package/dist/cake/editor/extension-types.d.ts +7 -0
  14. package/dist/cake/editor/extension-types.d.ts.map +1 -0
  15. package/dist/cake/editor/extension-types.js +1 -0
  16. package/dist/cake/editor/selection/selection-geometry-dom.d.ts.map +1 -1
  17. package/dist/cake/editor/selection/selection-geometry-dom.js +2 -1
  18. package/dist/cake/editor/selection/selection-layout-dom.d.ts.map +1 -1
  19. package/dist/cake/editor/selection/selection-layout-dom.js +2 -2
  20. package/dist/cake/editor/selection/selection-navigation.d.ts.map +1 -1
  21. package/dist/cake/editor/selection/selection-navigation.js +5 -1
  22. package/dist/cake/extensions/blockquote/blockquote.d.ts +2 -1
  23. package/dist/cake/extensions/blockquote/blockquote.d.ts.map +1 -1
  24. package/dist/cake/extensions/blockquote/blockquote.js +15 -12
  25. package/dist/cake/extensions/bold/bold.d.ts +2 -1
  26. package/dist/cake/extensions/bold/bold.d.ts.map +1 -1
  27. package/dist/cake/extensions/bold/bold.js +23 -18
  28. package/dist/cake/extensions/combined-emphasis/combined-emphasis.d.ts +2 -1
  29. package/dist/cake/extensions/combined-emphasis/combined-emphasis.d.ts.map +1 -1
  30. package/dist/cake/extensions/combined-emphasis/combined-emphasis.js +5 -6
  31. package/dist/cake/extensions/heading/heading.d.ts +2 -1
  32. package/dist/cake/extensions/heading/heading.d.ts.map +1 -1
  33. package/dist/cake/extensions/heading/heading.js +21 -15
  34. package/dist/cake/extensions/image/image.d.ts +2 -1
  35. package/dist/cake/extensions/image/image.d.ts.map +1 -1
  36. package/dist/cake/extensions/image/image.js +15 -12
  37. package/dist/cake/extensions/italic/italic.d.ts +2 -1
  38. package/dist/cake/extensions/italic/italic.d.ts.map +1 -1
  39. package/dist/cake/extensions/italic/italic.js +23 -18
  40. package/dist/cake/extensions/link/link-popover.d.ts +3 -15
  41. package/dist/cake/extensions/link/link-popover.d.ts.map +1 -1
  42. package/dist/cake/extensions/link/link-popover.js +30 -3
  43. package/dist/cake/extensions/link/link.d.ts +2 -1
  44. package/dist/cake/extensions/link/link.d.ts.map +1 -1
  45. package/dist/cake/extensions/link/link.js +23 -26
  46. package/dist/cake/extensions/list/list.d.ts +2 -1
  47. package/dist/cake/extensions/list/list.d.ts.map +1 -1
  48. package/dist/cake/extensions/list/list.js +13 -10
  49. package/dist/cake/extensions/scrollbar/index.d.ts +2 -1
  50. package/dist/cake/extensions/scrollbar/index.d.ts.map +1 -1
  51. package/dist/cake/extensions/scrollbar/index.js +10 -8
  52. package/dist/cake/extensions/strikethrough/strikethrough.d.ts +2 -1
  53. package/dist/cake/extensions/strikethrough/strikethrough.d.ts.map +1 -1
  54. package/dist/cake/extensions/strikethrough/strikethrough.js +23 -18
  55. package/dist/cake/extensions/types.d.ts +1 -1
  56. package/dist/cake/extensions/types.d.ts.map +1 -1
  57. package/dist/cake/extensions/underline/underline.d.ts +2 -1
  58. package/dist/cake/extensions/underline/underline.d.ts.map +1 -1
  59. package/dist/cake/extensions/underline/underline.js +40 -21
  60. package/dist/cake/index.d.ts +1 -1
  61. package/dist/cake/index.d.ts.map +1 -1
  62. package/dist/cake/react/index.d.ts.map +1 -1
  63. package/dist/cake/react/index.js +7 -49
  64. package/dist/cake/test/harness.d.ts +1 -1
  65. package/dist/cake/test/harness.d.ts.map +1 -1
  66. package/dist/cake/test/harness.js +4 -50
  67. package/dist/index.d.ts +2 -1
  68. package/dist/index.d.ts.map +1 -1
  69. package/package.json +4 -1
@@ -1,15 +1,13 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { defineExtension, } from "../../core/runtime";
3
1
  import { CursorSourceBuilder } from "../../core/mapping/cursor-source-map";
4
2
  import { CakeLinkPopover } from "./link-popover";
5
3
  import { getDocLines } from "../../editor/selection/selection-layout";
6
4
  import { cursorOffsetToVisibleOffset, getVisibleText, } from "../../editor/selection/visible-text";
7
5
  import { ensureHttpsProtocol, isUrl } from "../../shared/url";
8
6
  const LINK_KIND = "link";
9
- export const linkExtension = defineExtension({
10
- name: "link",
11
- inlineWrapperAffinity: [{ kind: LINK_KIND, inclusive: false }],
12
- keybindings: [
7
+ export const linkExtension = (editor) => {
8
+ const disposers = [];
9
+ disposers.push(editor.registerInlineWrapperAffinity([{ kind: LINK_KIND, inclusive: false }]));
10
+ disposers.push(editor.registerKeybindings([
13
11
  {
14
12
  key: "u",
15
13
  meta: true,
@@ -32,8 +30,8 @@ export const linkExtension = defineExtension({
32
30
  return { type: "wrap-link", openPopover: true };
33
31
  },
34
32
  },
35
- ],
36
- onEdit(command, state) {
33
+ ]));
34
+ disposers.push(editor.registerOnEdit((command, state) => {
37
35
  if (command.type === "unlink") {
38
36
  // Find the link at the given cursor position and remove the link markup
39
37
  const cursorPos = command.start;
@@ -100,8 +98,8 @@ export const linkExtension = defineExtension({
100
98
  affinity: "backward",
101
99
  },
102
100
  };
103
- },
104
- onPasteText(text, state) {
101
+ }));
102
+ disposers.push(editor.registerOnPasteText((text, state) => {
105
103
  if (!isUrl(text)) {
106
104
  return null;
107
105
  }
@@ -120,8 +118,8 @@ export const linkExtension = defineExtension({
120
118
  }
121
119
  const linkMarkdown = `[${url}](${url})`;
122
120
  return { type: "insert", text: linkMarkdown };
123
- },
124
- parseInline(source, start, end, context) {
121
+ }));
122
+ disposers.push(editor.registerParseInline((source, start, end, context) => {
125
123
  if (source[start] !== "[") {
126
124
  return null;
127
125
  }
@@ -152,8 +150,8 @@ export const linkExtension = defineExtension({
152
150
  },
153
151
  nextPos: urlClose + 1,
154
152
  };
155
- },
156
- serializeInline(inline, context) {
153
+ }));
154
+ disposers.push(editor.registerSerializeInline((inline, context) => {
157
155
  if (inline.type !== "inline-wrapper" || inline.kind !== LINK_KIND) {
158
156
  return null;
159
157
  }
@@ -168,8 +166,8 @@ export const linkExtension = defineExtension({
168
166
  builder.appendSourceOnly(url);
169
167
  builder.appendSourceOnly(")");
170
168
  return builder.build();
171
- },
172
- normalizeInline(inline) {
169
+ }));
170
+ disposers.push(editor.registerNormalizeInline((inline) => {
173
171
  if (inline.type !== "inline-wrapper" || inline.kind !== LINK_KIND) {
174
172
  return inline;
175
173
  }
@@ -177,8 +175,8 @@ export const linkExtension = defineExtension({
177
175
  return null;
178
176
  }
179
177
  return inline;
180
- },
181
- renderInline(inline, context) {
178
+ }));
179
+ disposers.push(editor.registerInlineRenderer((inline, context) => {
182
180
  if (inline.type !== "inline-wrapper" || inline.kind !== LINK_KIND) {
183
181
  return null;
184
182
  }
@@ -192,11 +190,10 @@ export const linkExtension = defineExtension({
192
190
  }
193
191
  }
194
192
  return element;
195
- },
196
- renderOverlay(context) {
197
- if (!context.contentRoot || !context.toOverlayRect) {
198
- return null;
199
- }
200
- return (_jsx(CakeLinkPopover, { container: context.container, contentRoot: context.contentRoot, toOverlayRect: context.toOverlayRect, getSelection: context.getSelection, executeCommand: context.executeCommand }));
201
- },
202
- });
193
+ }));
194
+ disposers.push(editor.registerUI(CakeLinkPopover));
195
+ return () => disposers
196
+ .splice(0)
197
+ .reverse()
198
+ .forEach((d) => d());
199
+ };
@@ -1,3 +1,4 @@
1
+ import { type CakeExtension } from "../../core/runtime";
1
2
  /** Command to toggle bullet list formatting */
2
3
  export type ToggleBulletListCommand = {
3
4
  type: "toggle-bullet-list";
@@ -8,5 +9,5 @@ export type ToggleNumberedListCommand = {
8
9
  };
9
10
  /** All list extension commands */
10
11
  export type ListCommand = ToggleBulletListCommand | ToggleNumberedListCommand;
11
- export declare const plainTextListExtension: import("../../..").CakeExtension;
12
+ export declare const plainTextListExtension: CakeExtension;
12
13
  //# sourceMappingURL=list.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/list/list.ts"],"names":[],"mappings":"AAygCA,+CAA+C;AAC/C,MAAM,MAAM,uBAAuB,GAAG;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAErE,iDAAiD;AACjD,MAAM,MAAM,yBAAyB,GAAG;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAEzE,kCAAkC;AAClC,MAAM,MAAM,WAAW,GAAG,uBAAuB,GAAG,yBAAyB,CAAC;AAE9E,eAAO,MAAM,sBAAsB,kCAmGjC,CAAC"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/list/list.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,oBAAoB,CAAC;AAqgC5B,+CAA+C;AAC/C,MAAM,MAAM,uBAAuB,GAAG;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAC;AAErE,iDAAiD;AACjD,MAAM,MAAM,yBAAyB,GAAG;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAEzE,kCAAkC;AAClC,MAAM,MAAM,WAAW,GAAG,uBAAuB,GAAG,yBAAyB,CAAC;AAE9E,eAAO,MAAM,sBAAsB,EAAE,aA0HpC,CAAC"}
@@ -1,4 +1,3 @@
1
- import { defineExtension, } from "../../core/runtime";
2
1
  import { mergeInlineForRender } from "../../dom/render";
3
2
  import { parseListRange, serializeListRange, convertToPlainText, getLineInfo, getListPrefixLength, isListLine, parseListItem, countNumberedItemsBefore, } from "./list-ast";
4
3
  // Match list lines - capture exactly one space after marker, rest goes to content
@@ -763,9 +762,9 @@ function getParagraphText(block) {
763
762
  }
764
763
  return text;
765
764
  }
766
- export const plainTextListExtension = defineExtension({
767
- name: "plain-text-list",
768
- keybindings: [
765
+ export const plainTextListExtension = (editor) => {
766
+ const disposers = [];
767
+ disposers.push(editor.registerKeybindings([
769
768
  {
770
769
  key: "8",
771
770
  meta: true,
@@ -790,8 +789,8 @@ export const plainTextListExtension = defineExtension({
790
789
  shift: true,
791
790
  command: { type: "toggle-numbered-list" },
792
791
  },
793
- ],
794
- onEdit(command, state) {
792
+ ]));
793
+ disposers.push(editor.registerOnEdit((command, state) => {
795
794
  if (command.type === "insert-line-break") {
796
795
  return handleInsertLineBreak(state);
797
796
  }
@@ -817,8 +816,8 @@ export const plainTextListExtension = defineExtension({
817
816
  return handleMarkerSwitch(state, command.text);
818
817
  }
819
818
  return null;
820
- },
821
- renderBlock(block, context) {
819
+ }));
820
+ disposers.push(editor.registerBlockRenderer((block, context) => {
822
821
  if (block.type !== "paragraph") {
823
822
  return null;
824
823
  }
@@ -855,5 +854,9 @@ export const plainTextListExtension = defineExtension({
855
854
  }
856
855
  }
857
856
  return element;
858
- },
859
- });
857
+ }));
858
+ return () => disposers
859
+ .splice(0)
860
+ .reverse()
861
+ .forEach((d) => d());
862
+ };
@@ -1,2 +1,3 @@
1
- export declare const scrollbarExtension: import("../../..").CakeExtension;
1
+ import type { CakeExtension } from "../../core/runtime";
2
+ export declare const scrollbarExtension: CakeExtension;
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/scrollbar/index.tsx"],"names":[],"mappings":"AA2RA,eAAO,MAAM,kBAAkB,kCAK7B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/scrollbar/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAiSxD,eAAO,MAAM,kBAAkB,EAAE,aAGhC,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState } from "react";
3
- import { defineExtension } from "../../core/runtime";
4
3
  const THUMB_MIN_HEIGHT = 30;
5
4
  const SCROLL_HIDE_DELAY = 500;
6
5
  const TRACK_PADDING = 8;
@@ -190,7 +189,9 @@ function ScrollbarOverlay({ container }) {
190
189
  };
191
190
  const getThumbColor = () => {
192
191
  if (isDarkMode) {
193
- return isDragging ? "rgba(255, 255, 255, 0.5)" : "rgba(255, 255, 255, 0.3)";
192
+ return isDragging
193
+ ? "rgba(255, 255, 255, 0.5)"
194
+ : "rgba(255, 255, 255, 0.3)";
194
195
  }
195
196
  return isDragging ? "rgba(0, 0, 0, 0.5)" : "rgba(0, 0, 0, 0.3)";
196
197
  };
@@ -208,9 +209,10 @@ function ScrollbarOverlay({ container }) {
208
209
  };
209
210
  return (_jsx("div", { style: wrapperStyle, children: _jsx("div", { "data-testid": "custom-scrollbar", "aria-hidden": "true", style: trackStyle, onClick: handleTrackClick, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: _jsx("div", { "data-testid": "scrollbar-thumb", style: thumbStyle, onMouseDown: handleThumbMouseDown }) }) }));
210
211
  }
211
- export const scrollbarExtension = defineExtension({
212
- name: "scrollbar",
213
- renderOverlay(context) {
214
- return _jsx(ScrollbarOverlay, { container: context.container });
215
- },
216
- });
212
+ function ScrollbarUI({ editor }) {
213
+ return _jsx(ScrollbarOverlay, { container: editor.getContainer() });
214
+ }
215
+ export const scrollbarExtension = (editor) => {
216
+ const unmount = editor.registerUI(ScrollbarUI);
217
+ return () => unmount();
218
+ };
@@ -1,2 +1,3 @@
1
- export declare const strikethroughExtension: import("../../..").CakeExtension;
1
+ import { type CakeExtension } from "../../core/runtime";
2
+ export declare const strikethroughExtension: CakeExtension;
2
3
  //# sourceMappingURL=strikethrough.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"strikethrough.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/strikethrough/strikethrough.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,sBAAsB,kCAuFjC,CAAC"}
1
+ {"version":3,"file":"strikethrough.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/strikethrough/strikethrough.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,oBAAoB,CAAC;AAS5B,eAAO,MAAM,sBAAsB,EAAE,aAoHpC,CAAC"}
@@ -1,10 +1,9 @@
1
- import { defineExtension, } from "../../core/runtime";
2
1
  import { CursorSourceBuilder } from "../../core/mapping/cursor-source-map";
3
2
  const STRIKE_KIND = "strikethrough";
4
- export const strikethroughExtension = defineExtension({
5
- name: "strikethrough",
6
- toggleInline: { kind: STRIKE_KIND, markers: ["~~"] },
7
- keybindings: [
3
+ export const strikethroughExtension = (editor) => {
4
+ const disposers = [];
5
+ disposers.push(editor.registerToggleInline({ kind: STRIKE_KIND, markers: ["~~"] }));
6
+ disposers.push(editor.registerKeybindings([
8
7
  {
9
8
  key: "x",
10
9
  meta: true,
@@ -17,16 +16,18 @@ export const strikethroughExtension = defineExtension({
17
16
  shift: true,
18
17
  command: { type: "toggle-strikethrough" },
19
18
  },
20
- ],
21
- inlineWrapperAffinity: [{ kind: STRIKE_KIND, inclusive: true }],
22
- onEdit(command) {
19
+ ]));
20
+ disposers.push(editor.registerInlineWrapperAffinity([
21
+ { kind: STRIKE_KIND, inclusive: true },
22
+ ]));
23
+ disposers.push(editor.registerOnEdit((command) => {
23
24
  // Handle semantic command by delegating to toggle-inline
24
25
  if (command.type === "toggle-strikethrough") {
25
26
  return { type: "toggle-inline", marker: "~~" };
26
27
  }
27
28
  return null;
28
- },
29
- parseInline(source, start, end, context) {
29
+ }));
30
+ disposers.push(editor.registerParseInline((source, start, end, context) => {
30
31
  if (source.slice(start, start + 2) !== "~~") {
31
32
  return null;
32
33
  }
@@ -46,8 +47,8 @@ export const strikethroughExtension = defineExtension({
46
47
  },
47
48
  nextPos: close + 2,
48
49
  };
49
- },
50
- serializeInline(inline, context) {
50
+ }));
51
+ disposers.push(editor.registerSerializeInline((inline, context) => {
51
52
  if (inline.type !== "inline-wrapper" || inline.kind !== STRIKE_KIND) {
52
53
  return null;
53
54
  }
@@ -59,8 +60,8 @@ export const strikethroughExtension = defineExtension({
59
60
  }
60
61
  builder.appendSourceOnly("~~");
61
62
  return builder.build();
62
- },
63
- normalizeInline(inline) {
63
+ }));
64
+ disposers.push(editor.registerNormalizeInline((inline) => {
64
65
  if (inline.type !== "inline-wrapper" || inline.kind !== STRIKE_KIND) {
65
66
  return inline;
66
67
  }
@@ -68,8 +69,8 @@ export const strikethroughExtension = defineExtension({
68
69
  return null;
69
70
  }
70
71
  return inline;
71
- },
72
- renderInline(inline, context) {
72
+ }));
73
+ disposers.push(editor.registerInlineRenderer((inline, context) => {
73
74
  if (inline.type !== "inline-wrapper" || inline.kind !== STRIKE_KIND) {
74
75
  return null;
75
76
  }
@@ -80,5 +81,9 @@ export const strikethroughExtension = defineExtension({
80
81
  }
81
82
  }
82
83
  return element;
83
- },
84
- });
84
+ }));
85
+ return () => disposers
86
+ .splice(0)
87
+ .reverse()
88
+ .forEach((d) => d());
89
+ };
@@ -1,4 +1,4 @@
1
- import type { CakeExtension } from "../core/runtime";
1
+ import type { CakeExtension } from "../editor/extension-types";
2
2
  export type CakeExtensionBundle = {
3
3
  name: string;
4
4
  extensions: CakeExtension[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cake/extensions/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cake/extensions/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B,CAAC"}
@@ -1,2 +1,3 @@
1
- export declare const underlineExtension: import("../../..").CakeExtension;
1
+ import { type CakeExtension } from "../../core/runtime";
2
+ export declare const underlineExtension: CakeExtension;
2
3
  //# sourceMappingURL=underline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"underline.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/underline/underline.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,kBAAkB,kCAyE7B,CAAC"}
1
+ {"version":3,"file":"underline.d.ts","sourceRoot":"","sources":["../../../../src/cake/extensions/underline/underline.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAInB,MAAM,oBAAoB,CAAC;AAS5B,eAAO,MAAM,kBAAkB,EAAE,aAsHhC,CAAC"}
@@ -1,21 +1,35 @@
1
- import { defineExtension, } from "../../core/runtime";
2
1
  import { CursorSourceBuilder } from "../../core/mapping/cursor-source-map";
3
2
  const UNDERLINE_KIND = "underline";
4
- export const underlineExtension = defineExtension({
5
- name: "underline",
6
- toggleInline: { kind: UNDERLINE_KIND, markers: [{ open: "<u>", close: "</u>" }] },
7
- keybindings: [
8
- { key: "u", meta: true, shift: false, command: { type: "toggle-underline" } },
9
- { key: "u", ctrl: true, shift: false, command: { type: "toggle-underline" } },
10
- ],
11
- inlineWrapperAffinity: [{ kind: UNDERLINE_KIND, inclusive: true }],
12
- onEdit(command) {
3
+ export const underlineExtension = (editor) => {
4
+ const disposers = [];
5
+ disposers.push(editor.registerToggleInline({
6
+ kind: UNDERLINE_KIND,
7
+ markers: [{ open: "<u>", close: "</u>" }],
8
+ }));
9
+ disposers.push(editor.registerKeybindings([
10
+ {
11
+ key: "u",
12
+ meta: true,
13
+ shift: false,
14
+ command: { type: "toggle-underline" },
15
+ },
16
+ {
17
+ key: "u",
18
+ ctrl: true,
19
+ shift: false,
20
+ command: { type: "toggle-underline" },
21
+ },
22
+ ]));
23
+ disposers.push(editor.registerInlineWrapperAffinity([
24
+ { kind: UNDERLINE_KIND, inclusive: true },
25
+ ]));
26
+ disposers.push(editor.registerOnEdit((command) => {
13
27
  if (command.type === "toggle-underline") {
14
28
  return { type: "toggle-inline", marker: "<u>" };
15
29
  }
16
30
  return null;
17
- },
18
- parseInline(source, start, end, context) {
31
+ }));
32
+ disposers.push(editor.registerParseInline((source, start, end, context) => {
19
33
  if (source.slice(start, start + 3) !== "<u>") {
20
34
  return null;
21
35
  }
@@ -32,9 +46,10 @@ export const underlineExtension = defineExtension({
32
46
  },
33
47
  nextPos: close + 4,
34
48
  };
35
- },
36
- serializeInline(inline, context) {
37
- if (inline.type !== "inline-wrapper" || inline.kind !== UNDERLINE_KIND) {
49
+ }));
50
+ disposers.push(editor.registerSerializeInline((inline, context) => {
51
+ if (inline.type !== "inline-wrapper" ||
52
+ inline.kind !== UNDERLINE_KIND) {
38
53
  return null;
39
54
  }
40
55
  const builder = new CursorSourceBuilder();
@@ -45,8 +60,8 @@ export const underlineExtension = defineExtension({
45
60
  }
46
61
  builder.appendSourceOnly("</u>");
47
62
  return builder.build();
48
- },
49
- normalizeInline(inline) {
63
+ }));
64
+ disposers.push(editor.registerNormalizeInline((inline) => {
50
65
  if (inline.type !== "inline-wrapper" || inline.kind !== UNDERLINE_KIND) {
51
66
  return inline;
52
67
  }
@@ -54,8 +69,8 @@ export const underlineExtension = defineExtension({
54
69
  return null;
55
70
  }
56
71
  return inline;
57
- },
58
- renderInline(inline, context) {
72
+ }));
73
+ disposers.push(editor.registerInlineRenderer((inline, context) => {
59
74
  if (inline.type !== "inline-wrapper" || inline.kind !== UNDERLINE_KIND) {
60
75
  return null;
61
76
  }
@@ -67,5 +82,9 @@ export const underlineExtension = defineExtension({
67
82
  }
68
83
  }
69
84
  return element;
70
- },
71
- });
85
+ }));
86
+ return () => disposers
87
+ .splice(0)
88
+ .reverse()
89
+ .forEach((d) => d());
90
+ };
@@ -1,2 +1,2 @@
1
- export type { EditCommand, CoreEditCommand, ExtensionCommand } from "./core/runtime";
1
+ export type { EditCommand, CoreEditCommand, ExtensionCommand, } from "./core/runtime";
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cake/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cake/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,WAAW,EACX,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/react/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EAEZ,MAAM,iBAAiB,CAAC;AAczB,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,iBAAiB,CAAC,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,KAC9B,IAAI,CAAC;IACV,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACjD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,cAAc,EAAE,CACd,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KACjC,OAAO,CAAC;IACb,WAAW,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAChD,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AAED,eAAO,MAAM,UAAU,kHAiQrB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cake/react/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,aAAa,EAEb,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAczB,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACnC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,iBAAiB,CAAC,EAAE,CAClB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,UAAU,GAAG,SAAS,KAC9B,IAAI,CAAC;IACV,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACjD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,cAAc,EAAE,CACd,OAAO,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,OAAO,CAAA;KAAE,KACjC,OAAO,CAAC;IACb,WAAW,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAChD,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,eAAe,EAAE,MAAM,MAAM,CAAC;IAC9B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzD;AAED,eAAO,MAAM,UAAU,kHAmNtB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Fragment, forwardRef, useEffect, useImperativeHandle, useRef, useState, } from "react";
2
+ import { forwardRef, useEffect, useImperativeHandle, useRef, useState, } from "react";
3
+ import { createPortal } from "react-dom";
3
4
  import { CakeEditor as CakeEditorEngine } from "../editor/cake-editor";
4
5
  function toEngineSelection(selection) {
5
6
  if (!selection) {
@@ -18,9 +19,8 @@ export const CakeEditor = forwardRef(function CakeEditor(props, outerRef) {
18
19
  const onSelectionChangeRef = useRef(props.onSelectionChange);
19
20
  const lastEmittedValueRef = useRef(null);
20
21
  const lastEmittedSelectionRef = useRef(null);
21
- const [contentRoot, setContentRoot] = useState(null);
22
+ const [uiComponents, setUiComponents] = useState([]);
22
23
  const extensionsRef = useRef(props.extensions);
23
- const hasOverlayExtensions = extensionsRef.current.some((ext) => ext.renderOverlay);
24
24
  useEffect(() => {
25
25
  onChangeRef.current = props.onChange;
26
26
  onSelectionChangeRef.current = props.onSelectionChange;
@@ -52,11 +52,11 @@ export const CakeEditor = forwardRef(function CakeEditor(props, outerRef) {
52
52
  },
53
53
  });
54
54
  engineRef.current = engine;
55
- setContentRoot(engine.getContentRoot());
55
+ setUiComponents(engine.getUIComponents());
56
56
  return () => {
57
57
  engine.destroy();
58
58
  engineRef.current = null;
59
- setContentRoot(null);
59
+ setUiComponents([]);
60
60
  };
61
61
  }, []);
62
62
  useEffect(() => {
@@ -174,52 +174,10 @@ export const CakeEditor = forwardRef(function CakeEditor(props, outerRef) {
174
174
  const containerClassName = props.className
175
175
  ? `cake ${props.className}`
176
176
  : "cake";
177
- const overlayContext = containerRef.current && contentRoot
178
- ? {
179
- container: containerRef.current,
180
- contentRoot,
181
- toOverlayRect: (rect) => {
182
- const containerRect = containerRef.current?.getBoundingClientRect();
183
- if (!containerRect) {
184
- return {
185
- top: rect.top,
186
- left: rect.left,
187
- width: rect.width,
188
- height: rect.height,
189
- };
190
- }
191
- return {
192
- top: rect.top - containerRect.top,
193
- left: rect.left - containerRect.left,
194
- width: rect.width,
195
- height: rect.height,
196
- };
197
- },
198
- insertText: (text) => {
199
- engineRef.current?.insertText(text);
200
- },
201
- replaceText: (oldText, newText) => {
202
- engineRef.current?.replaceText(oldText, newText);
203
- },
204
- getSelection: () => {
205
- const selection = engineRef.current?.getSelection();
206
- if (!selection) {
207
- return null;
208
- }
209
- const focus = selection.start === selection.end
210
- ? selection.start
211
- : Math.max(selection.start, selection.end);
212
- return { start: focus, end: focus };
213
- },
214
- executeCommand: (command) => {
215
- return engineRef.current?.executeCommand(command) ?? false;
216
- },
217
- }
218
- : null;
219
177
  return (_jsxs("div", { style: { position: "relative", height: "100%" }, children: [_jsx("div", { ref: containerRef, className: containerClassName, style: containerStyle, "data-placeholder": props.placeholder, onBlur: (event) => {
220
178
  props.onBlur?.(event.nativeEvent);
221
- } }), overlayContext && hasOverlayExtensions
222
- ? extensionsRef.current.map((extension) => extension.renderOverlay ? (_jsx(Fragment, { children: extension.renderOverlay(overlayContext) }, extension.name)) : null)
179
+ } }), engineRef.current && uiComponents.length > 0
180
+ ? createPortal(uiComponents.map((Component, index) => (_jsx(Component, { editor: engineRef.current }, index))), engineRef.current.getOverlayRoot())
223
181
  : null] }));
224
182
  });
225
183
  CakeEditor.displayName = "CakeEditor";
@@ -1,6 +1,6 @@
1
1
  import { CakeEditor } from "../editor/cake-editor";
2
2
  import type { Selection } from "../core/types";
3
- import type { CakeExtension } from "../core/runtime";
3
+ import type { CakeExtension } from "../editor/extension-types";
4
4
  export interface SelectionRectInfo {
5
5
  top: number;
6
6
  left: number;
@@ -1 +1 @@
1
- {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../src/cake/test/harness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../src/cake/test/harness.ts"],"names":[],"mappings":"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"}
@@ -38,54 +38,10 @@ export function createTestHarness(valueOrOptions) {
38
38
  let overlayRoot = null;
39
39
  if (options.renderOverlays) {
40
40
  const overlayContainer = engine.getOverlayRoot();
41
- const contentRoot = engine.getContentRoot();
42
- if (!overlayContainer || !contentRoot) {
43
- throw new Error("Missing overlay root for extensions");
44
- }
45
- const overlayContext = {
46
- container,
47
- contentRoot,
48
- overlayRoot: overlayContainer,
49
- toOverlayRect: (rect) => {
50
- const containerRect = container.getBoundingClientRect();
51
- return {
52
- top: rect.top - containerRect.top,
53
- left: rect.left - containerRect.left,
54
- width: rect.width,
55
- height: rect.height,
56
- };
57
- },
58
- insertText: (text) => {
59
- engine.insertText(text);
60
- },
61
- replaceText: (oldText, newText) => {
62
- engine.replaceText(oldText, newText);
63
- },
64
- getSelection: () => {
65
- const selection = engine.getSelection();
66
- if (!selection) {
67
- return null;
68
- }
69
- const focus = selection.start === selection.end
70
- ? selection.start
71
- : Math.max(selection.start, selection.end);
72
- return { start: focus, end: focus };
73
- },
74
- executeCommand: (command) => {
75
- return engine.executeCommand(command);
76
- },
77
- };
78
- const overlayElements = extensions.flatMap((extension) => {
79
- if (!extension.renderOverlay) {
80
- return [];
81
- }
82
- const rendered = extension.renderOverlay(overlayContext);
83
- if (!rendered) {
84
- return [];
85
- }
86
- return [createElement(Fragment, { key: extension.name }, rendered)];
87
- });
88
41
  overlayRoot = createRoot(overlayContainer);
42
+ const overlayElements = engine
43
+ .getUIComponents()
44
+ .map((Component, index) => createElement(Component, { key: index, editor: engine }));
89
45
  overlayRoot.render(createElement(Fragment, null, ...overlayElements));
90
46
  }
91
47
  function getContentRoot() {
@@ -318,9 +274,7 @@ export function createTestHarness(valueOrOptions) {
318
274
  }
319
275
  // Note: Layout model endOffset is exclusive, but old harness used inclusive.
320
276
  // Convert to inclusive by subtracting 1 (unless it's an empty row).
321
- const inclusiveEndOffset = row.endOffset > row.startOffset
322
- ? row.endOffset - 1
323
- : row.startOffset;
277
+ const inclusiveEndOffset = row.endOffset > row.startOffset ? row.endOffset - 1 : row.startOffset;
324
278
  return {
325
279
  startOffset: lineLayout.lineStartOffset + row.startOffset,
326
280
  endOffset: lineLayout.lineStartOffset + inclusiveEndOffset,
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { CakeEditor } from "./cake/editor/cake-editor";
2
- export type { CakeExtension, EditCommand } from "./cake/core/runtime";
2
+ export type { CakeExtension } from "./cake/editor/extension-types";
3
+ export type { EditCommand } from "./cake/core/runtime";
3
4
  export * from "./cake/extensions";
4
5
  //# sourceMappingURL=index.d.ts.map