edytor 0.0.7 → 0.0.9

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 (109) hide show
  1. package/README.md +225 -5
  2. package/dist/block/block.svelte.d.ts +123 -0
  3. package/dist/block/block.svelte.js +430 -0
  4. package/dist/block/block.utils.d.ts +82 -0
  5. package/dist/block/block.utils.js +499 -0
  6. package/dist/block/content.svelte.d.ts +14 -0
  7. package/dist/block/content.svelte.js +40 -0
  8. package/dist/block/inlineBlock.svelte.d.ts +30 -0
  9. package/dist/block/inlineBlock.svelte.js +53 -0
  10. package/dist/components/Block.svelte +27 -0
  11. package/dist/components/Block.svelte.d.ts +7 -0
  12. package/dist/components/Content.svelte +44 -0
  13. package/dist/components/Content.svelte.d.ts +7 -0
  14. package/dist/components/Edytor.svelte +165 -0
  15. package/dist/components/Edytor.svelte.d.ts +33 -0
  16. package/dist/components/InlineBlock.svelte +17 -0
  17. package/dist/components/InlineBlock.svelte.d.ts +7 -0
  18. package/dist/components/Mark.svelte +38 -0
  19. package/dist/components/Mark.svelte.d.ts +11 -0
  20. package/dist/components/ReadonlyEditor.svelte +46 -0
  21. package/dist/components/ReadonlyEditor.svelte.d.ts +4 -0
  22. package/dist/components/Text.svelte +37 -0
  23. package/dist/components/Text.svelte.d.ts +7 -0
  24. package/dist/components/readonlyElements.svelte.d.ts +82 -0
  25. package/dist/components/readonlyElements.svelte.js +144 -0
  26. package/dist/constants.d.ts +4 -0
  27. package/dist/constants.js +4 -0
  28. package/dist/dnd.svelte.d.ts +17 -0
  29. package/dist/dnd.svelte.js +125 -0
  30. package/dist/edytor.svelte.d.ts +94 -0
  31. package/dist/edytor.svelte.js +262 -0
  32. package/dist/edytor.utils.d.ts +3 -0
  33. package/dist/edytor.utils.js +78 -0
  34. package/dist/events/onBeforeInput.d.ts +2 -2
  35. package/dist/events/onBeforeInput.js +338 -0
  36. package/dist/events/onKeyDown.d.ts +2 -69
  37. package/dist/events/onKeyDown.js +18 -0
  38. package/dist/hotkeys.d.ts +27 -0
  39. package/dist/hotkeys.js +282 -0
  40. package/dist/index.d.ts +7 -5
  41. package/dist/index.js +7 -8
  42. package/dist/localProvider.d.ts +82 -0
  43. package/dist/localProvider.js +267 -0
  44. package/dist/plugins/arrowMove/arrowMove.d.ts +2 -0
  45. package/dist/plugins/arrowMove/arrowMove.js +66 -0
  46. package/dist/plugins/code/CodePlugin.svelte +218 -0
  47. package/dist/plugins/code/CodePlugin.svelte.d.ts +23 -0
  48. package/dist/plugins/code/prism.css +141 -0
  49. package/dist/plugins/image/ImagePlugin.svelte +22 -0
  50. package/dist/plugins/image/ImagePlugin.svelte.d.ts +20 -0
  51. package/dist/plugins/index.d.ts +3 -0
  52. package/dist/plugins/index.js +3 -0
  53. package/dist/plugins/mention/MentionPlugin.svelte +40 -0
  54. package/dist/plugins/mention/MentionPlugin.svelte.d.ts +20 -0
  55. package/dist/plugins/richtext/RichTextPlugin.svelte +241 -0
  56. package/dist/plugins/richtext/RichTextPlugin.svelte.d.ts +26 -0
  57. package/dist/plugins.d.ts +202 -0
  58. package/dist/plugins.js +19 -0
  59. package/dist/selection/selection.svelte.d.ts +68 -0
  60. package/dist/selection/selection.svelte.js +391 -0
  61. package/dist/selection/selection.utils.d.ts +14 -0
  62. package/dist/selection/selection.utils.js +153 -0
  63. package/dist/text/deltas.d.ts +11 -0
  64. package/dist/text/deltas.js +109 -0
  65. package/dist/text/text.svelte.d.ts +70 -0
  66. package/dist/text/text.svelte.js +119 -0
  67. package/dist/text/text.utils.d.ts +40 -0
  68. package/dist/text/text.utils.js +174 -0
  69. package/dist/utils/json.d.ts +32 -0
  70. package/dist/utils/json.js +2 -0
  71. package/dist/utils/jsx.d.ts +25 -0
  72. package/dist/utils/jsx.js +66 -0
  73. package/dist/utils/serialize.d.ts +1 -0
  74. package/dist/utils/serialize.js +1 -0
  75. package/dist/utils.d.ts +6 -0
  76. package/dist/utils.js +19 -0
  77. package/package.json +81 -33
  78. package/dist/edytor.cjs.development.js +0 -1762
  79. package/dist/edytor.cjs.development.js.map +0 -1
  80. package/dist/edytor.cjs.production.min.js +0 -2
  81. package/dist/edytor.cjs.production.min.js.map +0 -1
  82. package/dist/edytor.esm.js +0 -1691
  83. package/dist/edytor.esm.js.map +0 -1
  84. package/dist/events/index.d.ts +0 -3
  85. package/dist/events/onDrop.d.ts +0 -3
  86. package/dist/operations/deleteText.d.ts +0 -7
  87. package/dist/operations/formatText.d.ts +0 -20
  88. package/dist/operations/index.d.ts +0 -9
  89. package/dist/operations/insertText.d.ts +0 -5
  90. package/dist/operations/merge.d.ts +0 -3
  91. package/dist/operations/moveNode.d.ts +0 -12
  92. package/dist/operations/nestNode.d.ts +0 -2
  93. package/dist/operations/removeEmptyText.d.ts +0 -2
  94. package/dist/operations/splitLeaf.d.ts +0 -2
  95. package/dist/operations/splitNode.d.ts +0 -9
  96. package/dist/types.d.ts +0 -140
  97. package/dist/utils/common.d.ts +0 -17
  98. package/dist/utils/dropper.d.ts +0 -26
  99. package/dist/utils/index.d.ts +0 -6
  100. package/dist/utils/leaves.d.ts +0 -34
  101. package/dist/utils/nodes.d.ts +0 -14
  102. package/dist/utils/selection.d.ts +0 -51
  103. package/dist/utils/yClasses/EdytorDoc.d.ts +0 -16
  104. package/dist/utils/yClasses/index.d.ts +0 -3
  105. package/dist/utils/yClasses/yLeaf.d.ts +0 -7
  106. package/dist/utils/yClasses/yNode.d.ts +0 -12
  107. package/dist/yjs/index.d.ts +0 -1
  108. package/dist/yjs/wsProvider.d.ts +0 -1
  109. package/index.ts +0 -1
@@ -0,0 +1,70 @@
1
+ import { Edytor } from '../edytor.svelte.js';
2
+ import * as Y from 'yjs';
3
+ import { type JSONText, type SerializableContent } from '../utils/json.js';
4
+ import { Block } from '../block/block.svelte.js';
5
+ import { type JSONDelta } from './deltas.js';
6
+ export declare class Text {
7
+ #private;
8
+ readonly: boolean;
9
+ parent: Block;
10
+ yText: Y.Text;
11
+ edytor: Edytor;
12
+ stringContent: string;
13
+ index: number;
14
+ node: HTMLElement | undefined;
15
+ isEmpty: boolean;
16
+ endsWithNewline: boolean;
17
+ markOnNextInsert: undefined | Record<string, SerializableContent | null>;
18
+ id: string;
19
+ get value(): JSONText[];
20
+ get length(): number;
21
+ get children(): JSONDelta[];
22
+ set children(value: JSONDelta[]);
23
+ private setChildren;
24
+ private observeText;
25
+ constructor({ parent, content, yText }: {
26
+ parent: Block;
27
+ } & ({
28
+ yText?: undefined;
29
+ content: string | JSONText[];
30
+ } | {
31
+ yText: Y.Text;
32
+ content?: undefined;
33
+ }));
34
+ private batch;
35
+ getMarksAtRange: (yStart: number, yEnd: number) => JSONText[];
36
+ insertText: (args_0: {
37
+ value: string;
38
+ isAutoDot?: boolean;
39
+ start?: number;
40
+ end?: number;
41
+ marks?: Record<string, SerializableContent | null>;
42
+ }) => void;
43
+ deleteText: (args_0: {
44
+ direction: "BACKWARD" | "FORWARD";
45
+ length: number;
46
+ }) => void;
47
+ splitText: (args_0: {
48
+ index?: number;
49
+ }) => JSONText[];
50
+ setText: (args_0: {
51
+ value: JSONText[];
52
+ }) => void;
53
+ markText: (args_0: {
54
+ mark: string;
55
+ start?: number;
56
+ end?: number;
57
+ value?: SerializableContent | null;
58
+ toggle?: boolean;
59
+ }) => void;
60
+ removeMarksFromText: (args_0: {
61
+ mark: string;
62
+ start?: number;
63
+ end?: number;
64
+ value?: SerializableContent | null;
65
+ toggle?: boolean;
66
+ }) => void;
67
+ attach: (node: HTMLElement) => {
68
+ destroy: () => void;
69
+ };
70
+ }
@@ -0,0 +1,119 @@
1
+ import { Edytor } from '../edytor.svelte.js';
2
+ import * as Y from 'yjs';
3
+ import {} from '../utils/json.js';
4
+ import { Block } from '../block/block.svelte.js';
5
+ import { batch, deleteText, removeMarksFromText, getMarksAtRange, insertText, markText, setText, splitText } from './text.utils.js';
6
+ import { deltaToJson, jsonToDelta, toDeltas } from './deltas.js';
7
+ import { id } from '../utils.js';
8
+ import { climb } from '../selection/selection.utils.js';
9
+ export class Text {
10
+ readonly = false;
11
+ parent;
12
+ yText;
13
+ edytor;
14
+ stringContent = $state('');
15
+ index = $state(0);
16
+ node;
17
+ // Used to add en empty string in the DOM if the text is empty in order to be abble to focus on it.
18
+ isEmpty = $state(false);
19
+ // Used to add en empty string at the end of the text if it ends with a newline in order to visually render the newline.
20
+ endsWithNewline = $state(false);
21
+ // Used when user toggles mark without selection range.
22
+ markOnNextInsert = undefined;
23
+ id;
24
+ #children = $state([]);
25
+ get value() {
26
+ return deltaToJson(this.#children);
27
+ }
28
+ get length() {
29
+ return this.yText.length;
30
+ }
31
+ get children() {
32
+ const transformer = this.parent.definition.transformText;
33
+ return transformer
34
+ ? jsonToDelta(transformer({ text: this, block: this.parent, content: this.value }))
35
+ : this.#children;
36
+ }
37
+ set children(value) {
38
+ this.#children = value;
39
+ }
40
+ setChildren = (text) => {
41
+ this.stringContent = this.yText.toJSON();
42
+ [this.children, this.isEmpty] = toDeltas(text || this.yText);
43
+ this.endsWithNewline = this.stringContent.endsWith('\n');
44
+ };
45
+ observeText = (event, transaction) => {
46
+ if (transaction.origin !== this.edytor.transaction) {
47
+ // If the transaction is not from the edytor, we need to restore the selection
48
+ // If the current text is not focused, this action will be ignored
49
+ this.edytor.selection.restoreRelativePosition(this);
50
+ }
51
+ this.setChildren(event.target);
52
+ };
53
+ constructor({ parent, content, yText }) {
54
+ this.parent = parent;
55
+ this.edytor = parent.edytor;
56
+ this.yText = yText || new Y.Text();
57
+ this.id = this.yText.doc ? this.yText.getAttribute('id') : id('t');
58
+ if (content !== undefined) {
59
+ // If content is provided we need to initialize the text with the content
60
+ this.yText._pending?.push(() => {
61
+ this.yText.setAttribute('id', this.id);
62
+ if (typeof content === 'string') {
63
+ this.yText.insert(0, content);
64
+ }
65
+ else {
66
+ this.yText.applyDelta(content.map((part) => ({
67
+ insert: part.text,
68
+ attributes: part.marks
69
+ })));
70
+ }
71
+ this.setChildren();
72
+ });
73
+ }
74
+ else {
75
+ this.setChildren();
76
+ }
77
+ this.edytor.idToText.set(this.id, this);
78
+ if (!this.edytor.readonly) {
79
+ this.yText.observe(this.observeText);
80
+ }
81
+ }
82
+ batch = batch.bind(this);
83
+ getMarksAtRange = getMarksAtRange.bind(this);
84
+ insertText = this.batch('insertText', insertText.bind(this));
85
+ deleteText = this.batch('deleteText', deleteText.bind(this));
86
+ splitText = this.batch('splitText', splitText.bind(this));
87
+ setText = this.batch('setText', setText.bind(this));
88
+ markText = this.batch('markText', markText.bind(this));
89
+ removeMarksFromText = this.batch('removeMarksFromText', removeMarksFromText.bind(this));
90
+ attach = (node) => {
91
+ this.node = node;
92
+ this.edytor.nodeToText.set(node, this);
93
+ node.setAttribute('data-edytor-id', `${this.id}`);
94
+ node.setAttribute('data-edytor-text', `true`);
95
+ let pluginDestroy = this.edytor.plugins.reduce((acc, plugin) => {
96
+ const action = plugin.onTextAttached?.({ node, text: this });
97
+ action && acc.push(action);
98
+ return acc;
99
+ }, []);
100
+ let insideVoid = this.parent.definition.void;
101
+ climb(this.parent, (block) => {
102
+ if (block instanceof Block && block.definition.void) {
103
+ insideVoid = true;
104
+ return true;
105
+ }
106
+ });
107
+ if (insideVoid) {
108
+ node.contentEditable = 'true';
109
+ node.style.outline = 'none';
110
+ }
111
+ return {
112
+ destroy: () => {
113
+ this.yText?.unobserve(this.observeText);
114
+ this.edytor.idToText.delete(this.id);
115
+ pluginDestroy.forEach((destroy) => destroy());
116
+ }
117
+ };
118
+ };
119
+ }
@@ -0,0 +1,40 @@
1
+ import type { JSONText, SerializableContent } from '../utils/json.js';
2
+ import type { Text } from './text.svelte.js';
3
+ export type TextOperations = {
4
+ insertText: {
5
+ value: string;
6
+ isAutoDot?: boolean;
7
+ start?: number;
8
+ end?: number;
9
+ marks?: Record<string, SerializableContent | null>;
10
+ };
11
+ deleteText: {
12
+ direction: 'BACKWARD' | 'FORWARD';
13
+ length: number;
14
+ };
15
+ splitText: {
16
+ index?: number;
17
+ };
18
+ setText: {
19
+ value: JSONText[];
20
+ };
21
+ markText: {
22
+ mark: string;
23
+ start?: number;
24
+ end?: number;
25
+ value?: SerializableContent | null;
26
+ toggle?: boolean;
27
+ };
28
+ removeMarksFromText: {
29
+ start?: number;
30
+ end?: number;
31
+ };
32
+ };
33
+ export declare function batch<T extends (...args: any[]) => any, O extends keyof TextOperations>(operation: O, func: T): T;
34
+ export declare function insertText(this: Text, { value, isAutoDot, start, end, marks }: TextOperations['insertText']): void;
35
+ export declare function getMarksAtRange(this: Text, yStart: number, yEnd: number): JSONText[];
36
+ export declare function deleteText(this: Text, { direction, length }: TextOperations['deleteText']): void;
37
+ export declare function removeMarksFromText(this: Text, { start, end }: TextOperations['markText']): void;
38
+ export declare function markText(this: Text, { mark, value, toggle, start, end }: TextOperations['markText']): void;
39
+ export declare function splitText(this: Text, { index }: TextOperations['splitText']): JSONText[];
40
+ export declare function setText(this: Text, { value }: TextOperations['setText']): void;
@@ -0,0 +1,174 @@
1
+ import { prevent } from '../utils.js';
2
+ export function batch(operation, func) {
3
+ return function (payload) {
4
+ let finalPayload = payload;
5
+ for (const plugin of this.edytor.plugins) {
6
+ // @ts-expect-error
7
+ const normalizedPayload = plugin.onBeforeOperation?.({
8
+ operation,
9
+ payload,
10
+ text: this,
11
+ block: this.parent,
12
+ prevent
13
+ });
14
+ if (normalizedPayload) {
15
+ finalPayload = normalizedPayload;
16
+ break;
17
+ }
18
+ }
19
+ const result = this.edytor.transact(() => func.bind(this)(finalPayload));
20
+ for (const plugin of this.edytor.plugins) {
21
+ plugin.onAfterOperation?.({
22
+ operation,
23
+ payload,
24
+ text: this,
25
+ block: this.parent
26
+ });
27
+ }
28
+ return result;
29
+ };
30
+ }
31
+ export function insertText({ value, isAutoDot, start = this.edytor.selection.state.yStart, end = this.edytor.selection.state.yEnd, marks = this.markOnNextInsert }) {
32
+ const isCollapsed = start === end || !end;
33
+ // const attributes = this.getAttributesAtPosition(yStart);
34
+ const deltas = [{ retain: start }, { insert: value, attributes: marks }];
35
+ if (isAutoDot) {
36
+ deltas[0].retain = start - 1;
37
+ deltas.splice(1, 0, { delete: 1 });
38
+ }
39
+ if (!isCollapsed) {
40
+ deltas.splice(1, 0, { delete: end - start });
41
+ }
42
+ this.edytor.doc.transact(() => {
43
+ if (isAutoDot || !isCollapsed) {
44
+ this.yText.applyDelta(deltas);
45
+ }
46
+ else {
47
+ this.yText.insert(start, value, marks);
48
+ }
49
+ });
50
+ if (this.markOnNextInsert) {
51
+ this.markOnNextInsert = undefined;
52
+ }
53
+ }
54
+ export function getMarksAtRange(yStart, yEnd) {
55
+ const result = [];
56
+ let offset = 0;
57
+ let entered = false;
58
+ for (let i = 0; i < this.children.length; i++) {
59
+ const { text, marks } = this.children[i];
60
+ const length = text.length;
61
+ const end = offset + length;
62
+ if (yStart >= offset && yStart < end) {
63
+ // Found start of range
64
+ entered = true;
65
+ const startOffset = yStart - offset;
66
+ const endOffset = Math.min(length, yEnd - offset);
67
+ result.push({
68
+ text: text.slice(startOffset, endOffset),
69
+ marks: Object.fromEntries(marks)
70
+ });
71
+ }
72
+ else if (entered && end <= yEnd) {
73
+ // Middle of range
74
+ result.push({
75
+ text,
76
+ marks: Object.fromEntries(marks)
77
+ });
78
+ }
79
+ else if (entered && offset < yEnd && yEnd <= end) {
80
+ // End of range
81
+ const endOffset = yEnd - offset;
82
+ result.push({
83
+ text: text.slice(0, endOffset),
84
+ marks: Object.fromEntries(marks)
85
+ });
86
+ break;
87
+ }
88
+ offset += length;
89
+ }
90
+ return result;
91
+ }
92
+ export function deleteText({ direction, length = 1 }) {
93
+ const { yStart, isCollapsed } = this.edytor.selection.state;
94
+ const deltas = direction === 'BACKWARD'
95
+ ? [{ retain: isCollapsed ? yStart - 1 : yStart }, { delete: isCollapsed ? 1 : length }]
96
+ : [{ retain: isCollapsed ? yStart : yStart }, { delete: isCollapsed ? 1 : length }];
97
+ this.yText.applyDelta(deltas);
98
+ }
99
+ export function removeMarksFromText({ start = this.edytor.selection.state.yStart || 0, end = this.edytor.selection.state.yEnd || this.yText.length }) {
100
+ const marksAtRange = this.getMarksAtRange(start, end);
101
+ const attributes = marksAtRange.reduce((acc, { marks }) => {
102
+ Object.entries(marks || {}).forEach(([key, value]) => {
103
+ if (value === null) {
104
+ Object.assign({ key: null });
105
+ }
106
+ });
107
+ return acc;
108
+ }, {});
109
+ this.yText.format(start, end, attributes);
110
+ }
111
+ export function markText({ mark, value = true, toggle = false, start = this.edytor.selection.state.yStart, end = this.edytor.selection.state.yEnd }) {
112
+ const length = end - start;
113
+ const isCollasped = end - start === 0;
114
+ const marksAtRange = this.getMarksAtRange(isCollasped ? start - 1 : start, end);
115
+ const isNextActiveMark = isCollasped && this.markOnNextInsert && mark in this.markOnNextInsert;
116
+ const spreadOnAllRange = marksAtRange.every(({ marks }) => marks && mark in marks);
117
+ const markValue = (spreadOnAllRange || isNextActiveMark) && toggle ? null : value;
118
+ if (isCollasped) {
119
+ const activeMarks = marksAtRange.reduce((acc, { marks }) => {
120
+ Object.entries(marks || {}).forEach(([key, value]) => {
121
+ if (value === true) {
122
+ Object.assign(acc, { [key]: true });
123
+ }
124
+ });
125
+ return acc;
126
+ }, {});
127
+ if (isNextActiveMark && markValue === null) {
128
+ delete this.markOnNextInsert[mark];
129
+ }
130
+ else {
131
+ this.markOnNextInsert = {
132
+ ...(this.markOnNextInsert || {}),
133
+ ...activeMarks,
134
+ [mark]: markValue
135
+ };
136
+ }
137
+ }
138
+ else {
139
+ this.yText.format(start, length, {
140
+ [mark]: markValue
141
+ });
142
+ }
143
+ }
144
+ // This function split a Y.Text at an index, delete what is after the index and returns the deleted content as a JSONText[]
145
+ export function splitText({ index = this.edytor.selection.state.yStart }) {
146
+ let offset = 0;
147
+ let content = [];
148
+ for (const child of this.value) {
149
+ const textLength = child.text.length;
150
+ const nextOffset = offset + textLength;
151
+ if (offset < index) {
152
+ content.push({
153
+ text: child.text.slice(index - offset),
154
+ marks: child.marks
155
+ });
156
+ }
157
+ else {
158
+ // Text fully after split point
159
+ content.push({
160
+ text: child.text,
161
+ marks: child.marks
162
+ });
163
+ }
164
+ offset = nextOffset;
165
+ }
166
+ this.yText.delete(index, this.yText.length - index);
167
+ return content;
168
+ }
169
+ export function setText({ value }) {
170
+ this.yText.applyDelta([
171
+ { delete: this.yText.length },
172
+ ...value.map((part) => ({ insert: part.text, attributes: part.marks }))
173
+ ]);
174
+ }
@@ -0,0 +1,32 @@
1
+ import { Map } from 'yjs';
2
+ export type YBlock = Map<any>;
3
+ export type Mark = [string, Record<string, unknown> | boolean | string];
4
+ export type SerializableContent = {
5
+ [key: string]: SerializableContent;
6
+ } | string | boolean | number | null;
7
+ export type JSONText = {
8
+ text: string;
9
+ marks?: Record<string, SerializableContent>;
10
+ };
11
+ export type JSONInlineBlock = {
12
+ id?: string;
13
+ data?: any;
14
+ type: string;
15
+ };
16
+ export type JSONBlock = {
17
+ type: string;
18
+ id?: string;
19
+ data?: Record<string, SerializableContent>;
20
+ children?: JSONBlock[];
21
+ content?: (JSONText | JSONInlineBlock)[];
22
+ };
23
+ export type PartialJSONBlock = Omit<JSONBlock, 'children' | 'content'>;
24
+ export type JSONDoc = {
25
+ children: JSONBlock[];
26
+ } & Partial<Record<string, unknown>>;
27
+ export type Delta = {
28
+ insert?: string;
29
+ retain?: number;
30
+ delete?: number;
31
+ attributes?: SerializableContent;
32
+ };
@@ -0,0 +1,2 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Text, AbstractType, Array as YArray, Map, Doc } from 'yjs';
@@ -0,0 +1,25 @@
1
+ import type { JSONBlock, SerializableContent } from './json.js';
2
+ type JSXAttributes = {
3
+ children?: JSXChild | JSXChild[];
4
+ data?: any;
5
+ } & {
6
+ [key: string]: string | number | boolean | SerializableContent | JSXChild | JSXChild[] | undefined;
7
+ };
8
+ type JSXChild = string | number | boolean | JSXElement | null | undefined;
9
+ interface JSXElement {
10
+ type: string;
11
+ props: JSXAttributes;
12
+ }
13
+ declare global {
14
+ namespace JSX {
15
+ interface Element extends JSXElement {
16
+ }
17
+ interface IntrinsicElements {
18
+ [elemName: string]: JSXAttributes;
19
+ }
20
+ }
21
+ }
22
+ declare function jsx(type: string, props: JSXAttributes): JSXElement;
23
+ declare function jsxs(type: string, props: JSXAttributes): JSXElement;
24
+ declare function convertJSXToJSONBlock(element: JSXElement): JSONBlock;
25
+ export { jsx, jsxs, convertJSXToJSONBlock };
@@ -0,0 +1,66 @@
1
+ function jsx(type, props) {
2
+ return { type, props };
3
+ }
4
+ function jsxs(type, props) {
5
+ return jsx(type, props);
6
+ }
7
+ const MARK_ELEMENTS = new Set(['bold', 'italic', 'underline', 'strike', 'code']);
8
+ function convertJSXToJSONBlock(element) {
9
+ const { type, props } = element;
10
+ const { children, data, ...rest } = props;
11
+ // Handle mark wrapper elements (bold, italic, etc)
12
+ if (MARK_ELEMENTS.has(type)) {
13
+ const textContent = convertChildrenToTextContent(children);
14
+ return {
15
+ type: 'text',
16
+ content: [
17
+ {
18
+ text: textContent,
19
+ marks: { [type]: true }
20
+ }
21
+ ]
22
+ };
23
+ }
24
+ // Handle inline blocks
25
+ if (type === 'inline') {
26
+ const inlineContent = {
27
+ type: props.blockType || 'inline',
28
+ ...(data && { data })
29
+ };
30
+ return {
31
+ type: 'inline',
32
+ content: [inlineContent],
33
+ ...rest
34
+ };
35
+ }
36
+ // Convert children
37
+ const convertedChildren = children
38
+ ? (Array.isArray(children) ? children : [children])
39
+ .filter((child) => child != null &&
40
+ (typeof child === 'object' || typeof child === 'string' || typeof child === 'number'))
41
+ .map((child) => {
42
+ if (typeof child === 'string' || typeof child === 'number') {
43
+ return {
44
+ type: 'text',
45
+ content: [{ text: child.toString() }]
46
+ };
47
+ }
48
+ return convertJSXToJSONBlock(child);
49
+ })
50
+ : undefined;
51
+ return {
52
+ type,
53
+ ...(convertedChildren && { children: convertedChildren }),
54
+ ...rest
55
+ };
56
+ }
57
+ function convertChildrenToTextContent(children) {
58
+ if (!children)
59
+ return '';
60
+ const childArray = Array.isArray(children) ? children : [children];
61
+ return childArray
62
+ .filter((child) => typeof child === 'string' || typeof child === 'number')
63
+ .map((child) => child.toString())
64
+ .join('');
65
+ }
66
+ export { jsx, jsxs, convertJSXToJSONBlock };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,6 @@
1
+ export declare const id: (prefix: "t" | "b" | "i") => string;
2
+ export declare class PreventionError extends Error {
3
+ cb?: () => void;
4
+ constructor(cb?: () => void);
5
+ }
6
+ export declare const prevent: (cb?: () => void) => void;
package/dist/utils.js ADDED
@@ -0,0 +1,19 @@
1
+ let alphabet = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict';
2
+ export const id = (prefix) => {
3
+ const e = 10;
4
+ let t = '', r = crypto.getRandomValues(new Uint8Array(e));
5
+ for (let n = 0; n < e; n++)
6
+ t += alphabet[61 & r[n]];
7
+ return `${prefix}_${t}`;
8
+ };
9
+ export class PreventionError extends Error {
10
+ cb;
11
+ constructor(cb) {
12
+ super('Prevent');
13
+ this.name = 'PreventionError';
14
+ this.cb = cb;
15
+ }
16
+ }
17
+ export const prevent = (cb) => {
18
+ throw new PreventionError(cb);
19
+ };