@kedataindo/docflow-core 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,491 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BlockAttributesExtension: () => BlockAttributesExtension,
34
+ FontSizeExtension: () => FontSizeExtension,
35
+ PAGE_SIZES: () => import_tiptap_pagination_plus2.PAGE_SIZES,
36
+ PaginationPlus: () => import_tiptap_pagination_plus2.PaginationPlus,
37
+ collaborationExtensions: () => collaborationExtensions,
38
+ collectExtensions: () => collectExtensions,
39
+ createActionMap: () => createActionMap,
40
+ createCollaboration: () => createCollaboration,
41
+ createEditor: () => createEditor,
42
+ definePlugin: () => definePlugin,
43
+ resolveAction: () => resolveAction
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/Editor.ts
48
+ var import_core2 = require("@tiptap/core");
49
+ var import_starter_kit = __toESM(require("@tiptap/starter-kit"), 1);
50
+ var import_extension_text_style = __toESM(require("@tiptap/extension-text-style"), 1);
51
+ var import_y_prosemirror = require("y-prosemirror");
52
+
53
+ // src/PluginSystem.ts
54
+ function definePlugin(plugin) {
55
+ return plugin;
56
+ }
57
+ function collectExtensions(plugins) {
58
+ const extensions = [];
59
+ for (const plugin of plugins) {
60
+ if (plugin.tiptapExtensions) {
61
+ extensions.push(...plugin.tiptapExtensions);
62
+ }
63
+ }
64
+ return extensions;
65
+ }
66
+ function resolveAction(editor, action, ...args) {
67
+ const commands = editor.commands;
68
+ const command = commands[action];
69
+ if (typeof command !== "function") {
70
+ return false;
71
+ }
72
+ const result = command(...args);
73
+ return result === true;
74
+ }
75
+ function createActionMap(editor, plugins) {
76
+ const map = {};
77
+ for (const plugin of plugins) {
78
+ for (const item of plugin.toolbar ?? []) {
79
+ const custom = plugin.commands?.[item.action];
80
+ map[item.action] = (...args) => {
81
+ if (typeof custom === "function") {
82
+ return custom(editor, ...args);
83
+ }
84
+ return resolveAction(editor, item.action, ...args);
85
+ };
86
+ }
87
+ for (const slash of plugin.slashCommands ?? []) {
88
+ const custom = plugin.commands?.[slash.command];
89
+ map[slash.command] = (...args) => {
90
+ if (typeof custom === "function") {
91
+ return custom(editor, ...args);
92
+ }
93
+ return resolveAction(editor, slash.command, ...args);
94
+ };
95
+ }
96
+ }
97
+ return map;
98
+ }
99
+
100
+ // src/Collaboration.ts
101
+ var import_extension_collaboration = require("@tiptap/extension-collaboration");
102
+ var import_extension_collaboration_cursor = require("@tiptap/extension-collaboration-cursor");
103
+ var import_awareness = require("y-protocols/awareness");
104
+ var import_y_webrtc = require("y-webrtc");
105
+ var import_y_websocket = require("y-websocket");
106
+ var Y = __toESM(require("yjs"), 1);
107
+ function createAwarenessStates(awareness) {
108
+ const states = [];
109
+ awareness.getStates().forEach((state, clientId) => {
110
+ const raw = state;
111
+ states.push({
112
+ clientId,
113
+ user: raw.user ?? { name: "", color: "" },
114
+ cursor: raw.cursor ?? null
115
+ });
116
+ });
117
+ return states;
118
+ }
119
+ function createCollaboration(options) {
120
+ const ydoc = new Y.Doc();
121
+ if (options.initialStorageState) {
122
+ Y.applyUpdate(ydoc, options.initialStorageState);
123
+ }
124
+ let provider = null;
125
+ if (options.provider === "webrtc") {
126
+ provider = new import_y_webrtc.WebrtcProvider(options.room, ydoc, {
127
+ signaling: options.signaling || [
128
+ "ws://localhost:4444",
129
+ "wss://signaling.yjs.dev",
130
+ "wss://y-webrtc-eu.fly.dev"
131
+ ]
132
+ });
133
+ } else if (options.provider === "websocket") {
134
+ if (!options.websocketUrl) {
135
+ throw new Error('[Collaboration] websocketUrl is required when provider is "websocket"');
136
+ }
137
+ provider = new import_y_websocket.WebsocketProvider(options.websocketUrl, options.room, ydoc);
138
+ }
139
+ const awareness = provider?.awareness ?? new import_awareness.Awareness(ydoc);
140
+ awareness.setLocalStateField("user", options.user);
141
+ let awarenessHandler;
142
+ if (options.onAwarenessChange) {
143
+ const notify = () => {
144
+ options.onAwarenessChange?.(createAwarenessStates(awareness));
145
+ };
146
+ awarenessHandler = notify;
147
+ awareness.on("change", notify);
148
+ notify();
149
+ }
150
+ const destroy = () => {
151
+ if (awarenessHandler) {
152
+ awareness.off("change", awarenessHandler);
153
+ }
154
+ awareness.setLocalState(null);
155
+ provider?.destroy?.();
156
+ awareness.destroy?.();
157
+ ydoc.destroy();
158
+ };
159
+ return { ydoc, provider, awareness, destroy };
160
+ }
161
+ function collaborationExtensions(options) {
162
+ const setup = "ydoc" in options ? options : createCollaboration(options);
163
+ const extensions = [
164
+ import_extension_collaboration.Collaboration.configure({ document: setup.ydoc })
165
+ ];
166
+ if (setup.provider) {
167
+ extensions.push(
168
+ import_extension_collaboration_cursor.CollaborationCursor.configure({
169
+ provider: setup.provider,
170
+ user: setup.awareness.getLocalState()?.user ?? { name: "", color: "" }
171
+ })
172
+ );
173
+ }
174
+ return extensions;
175
+ }
176
+
177
+ // src/BlockAttributes.ts
178
+ var import_core = require("@tiptap/core");
179
+ var import_state = require("@tiptap/pm/state");
180
+ var import_view = require("@tiptap/pm/view");
181
+ var BlockAttributesExtension = import_core.Extension.create({
182
+ name: "blockAttributes",
183
+ addOptions() {
184
+ return {
185
+ pageMap: () => /* @__PURE__ */ new Map()
186
+ };
187
+ },
188
+ addProseMirrorPlugins() {
189
+ const getPageMap = this.options.pageMap;
190
+ return [
191
+ new import_state.Plugin({
192
+ key: new import_state.PluginKey("blockAttributes"),
193
+ props: {
194
+ decorations(state) {
195
+ const decorations = [];
196
+ const pageMap = getPageMap();
197
+ if (pageMap.size === 0) return import_view.DecorationSet.create(state.doc, decorations);
198
+ const maxIdxPerPage = /* @__PURE__ */ new Map();
199
+ pageMap.forEach((info) => {
200
+ const cur = maxIdxPerPage.get(info.page) ?? -1;
201
+ if (info.blockIndex > cur) maxIdxPerPage.set(info.page, info.blockIndex);
202
+ });
203
+ state.doc.descendants((node, pos) => {
204
+ if (!node.isBlock) return;
205
+ const attrs = {
206
+ "data-from": String(pos),
207
+ "data-to": String(pos + node.nodeSize),
208
+ "data-node-type": node.type.name
209
+ };
210
+ const pageInfo = pageMap.get(pos);
211
+ if (pageInfo) {
212
+ attrs["data-page"] = String(pageInfo.page);
213
+ attrs["data-page-block-index"] = String(pageInfo.blockIndex);
214
+ const maxIdx = maxIdxPerPage.get(pageInfo.page);
215
+ const styleParts = [];
216
+ if (pageInfo.page > 1 && pageInfo.blockIndex === 0) {
217
+ styleParts.push("margin-top:72px");
218
+ }
219
+ if (maxIdx !== void 0 && pageInfo.blockIndex === maxIdx) {
220
+ styleParts.push("margin-bottom:72px");
221
+ }
222
+ if (styleParts.length > 0) {
223
+ attrs.style = styleParts.join(";");
224
+ }
225
+ }
226
+ decorations.push(
227
+ import_view.Decoration.node(pos, pos + node.nodeSize, attrs)
228
+ );
229
+ });
230
+ return import_view.DecorationSet.create(state.doc, decorations);
231
+ }
232
+ }
233
+ })
234
+ ];
235
+ }
236
+ });
237
+
238
+ // src/Editor.ts
239
+ var import_tiptap_pagination_plus = require("tiptap-pagination-plus");
240
+ function migrateContent(content) {
241
+ if (!content) return content;
242
+ if (typeof content === "string") {
243
+ try {
244
+ const parsed = JSON.parse(content);
245
+ return JSON.stringify(migrateContent(parsed));
246
+ } catch {
247
+ return content;
248
+ }
249
+ }
250
+ if (typeof content !== "object" || content === null) return content;
251
+ const obj = content;
252
+ if (obj.type === "doc" && Array.isArray(obj.content)) {
253
+ const newContentList = [];
254
+ for (const child of obj.content) {
255
+ const childObj = child;
256
+ if (childObj && childObj.type === "page" && Array.isArray(childObj.content)) {
257
+ newContentList.push(...childObj.content);
258
+ } else {
259
+ newContentList.push(child);
260
+ }
261
+ }
262
+ return { ...obj, content: newContentList };
263
+ }
264
+ if (obj.type === "tabbed-doc" && Array.isArray(obj.tabs)) {
265
+ return {
266
+ ...obj,
267
+ tabs: obj.tabs.map((tab) => ({
268
+ ...tab,
269
+ content: migrateContent(tab.content)
270
+ }))
271
+ };
272
+ }
273
+ return content;
274
+ }
275
+ function createEditor(options = {}) {
276
+ const migratedOptions = {
277
+ ...options,
278
+ content: options.content ? migrateContent(options.content) : options.content
279
+ };
280
+ const plugins = migratedOptions.plugins ?? [];
281
+ const collaborationSetup = migratedOptions.collaboration ? createCollaboration(migratedOptions.collaboration) : void 0;
282
+ let tiptapEditor = createTiptapEditor(migratedOptions, plugins, collaborationSetup);
283
+ let pluginActions = createActionMap(tiptapEditor, plugins);
284
+ for (const plugin of plugins) {
285
+ plugin.hooks?.onInit?.(tiptapEditor);
286
+ }
287
+ const rebuildEditor = () => {
288
+ const currentJSON = tiptapEditor.getJSON();
289
+ const selection = tiptapEditor.state.selection;
290
+ const target = migratedOptions.target;
291
+ tiptapEditor.destroy();
292
+ tiptapEditor = createTiptapEditor(
293
+ { ...migratedOptions, content: currentJSON },
294
+ plugins,
295
+ collaborationSetup
296
+ );
297
+ try {
298
+ const { from, to } = selection;
299
+ if (from >= 0 && to >= from && to <= tiptapEditor.state.doc.content.size) {
300
+ tiptapEditor.commands.setTextSelection({ from, to });
301
+ }
302
+ } catch {
303
+ }
304
+ if (target) {
305
+ tiptapEditor.commands.focus();
306
+ }
307
+ pluginActions = createActionMap(tiptapEditor, plugins);
308
+ };
309
+ const editor = {
310
+ get editor() {
311
+ return tiptapEditor;
312
+ },
313
+ collab: collaborationSetup,
314
+ getJSON: () => tiptapEditor.getJSON(),
315
+ getHTML: () => tiptapEditor.getHTML(),
316
+ destroy: () => {
317
+ for (const plugin of plugins) {
318
+ plugin.hooks?.onDestroy?.(tiptapEditor);
319
+ }
320
+ tiptapEditor.destroy();
321
+ collaborationSetup?.destroy();
322
+ },
323
+ use: (plugin) => {
324
+ plugins.push(plugin);
325
+ rebuildEditor();
326
+ plugin.hooks?.onInit?.(tiptapEditor);
327
+ },
328
+ get pluginActions() {
329
+ return pluginActions;
330
+ }
331
+ };
332
+ return editor;
333
+ }
334
+ function createTiptapEditor(options, plugins, collaborationSetup) {
335
+ const baseStarterKit = options.collaboration ? import_starter_kit.default.configure({ history: false }) : import_starter_kit.default;
336
+ const pluginExtensions = collectExtensions(plugins);
337
+ const blockAttrs = options.getPageMap ? BlockAttributesExtension.configure({ pageMap: options.getPageMap }) : BlockAttributesExtension;
338
+ const paginationExt = options.paginationOptions ? import_tiptap_pagination_plus.PaginationPlus.configure(options.paginationOptions) : import_tiptap_pagination_plus.PaginationPlus;
339
+ let extensions = [
340
+ baseStarterKit,
341
+ import_extension_text_style.default,
342
+ blockAttrs,
343
+ paginationExt,
344
+ ...pluginExtensions
345
+ ];
346
+ const content = options.collaboration ? void 0 : options.content;
347
+ if (options.collaboration && collaborationSetup) {
348
+ const fragment = collaborationSetup.ydoc.getXmlFragment("default");
349
+ if (fragment.length === 0 && options.content && typeof options.content === "object") {
350
+ const schema = (0, import_core2.getSchema)([baseStarterKit, import_extension_text_style.default, blockAttrs, paginationExt, ...pluginExtensions]);
351
+ (0, import_y_prosemirror.prosemirrorJSONToYXmlFragment)(schema, options.content, fragment);
352
+ }
353
+ extensions = [...extensions, ...collaborationExtensions(collaborationSetup)];
354
+ }
355
+ return new import_core2.Editor({
356
+ element: options.target,
357
+ content,
358
+ extensions,
359
+ editable: options.editable ?? true,
360
+ onUpdate: ({ editor }) => {
361
+ options.onUpdate?.(editor.getJSON());
362
+ }
363
+ });
364
+ }
365
+
366
+ // src/FontSize.ts
367
+ var import_core3 = require("@tiptap/core");
368
+ function mergeFontSize(textStyleType, existing, fontSize) {
369
+ if (fontSize === null) {
370
+ const { fontSize: _removed, ...rest } = existing?.attrs ?? {};
371
+ return textStyleType.create(rest);
372
+ }
373
+ return textStyleType.create({ ...existing?.attrs, fontSize });
374
+ }
375
+ function hasAttrs(mark) {
376
+ return Object.values(mark.attrs).some((v) => v != null);
377
+ }
378
+ var FontSizeExtension = import_core3.Extension.create({
379
+ name: "fontSize",
380
+ addGlobalAttributes() {
381
+ return [
382
+ {
383
+ types: ["textStyle"],
384
+ attributes: {
385
+ fontSize: {
386
+ default: null,
387
+ parseHTML: (el) => el.style.fontSize || null,
388
+ renderHTML: (attrs) => {
389
+ if (!attrs.fontSize) return {};
390
+ return { style: `font-size: ${attrs.fontSize}` };
391
+ }
392
+ }
393
+ }
394
+ }
395
+ ];
396
+ },
397
+ addCommands() {
398
+ return {
399
+ setFontSize: (fontSize) => ({ tr, state, dispatch }) => {
400
+ console.log("[FontSizeExt] setFontSize called, fontSize:", fontSize, "empty:", state.selection.empty);
401
+ const textStyleType = state.schema.marks.textStyle;
402
+ const { from, to, empty } = state.selection;
403
+ if (empty) {
404
+ const stored = tr.storedMarks ? [...tr.storedMarks] : [...state.storedMarks ?? []];
405
+ const idx = stored.findIndex((m) => m.type === textStyleType);
406
+ const existing = idx >= 0 ? stored[idx] : void 0;
407
+ const merged = mergeFontSize(textStyleType, existing, fontSize);
408
+ if (idx >= 0) {
409
+ if (hasAttrs(merged)) {
410
+ stored[idx] = merged;
411
+ } else {
412
+ stored.splice(idx, 1);
413
+ }
414
+ } else {
415
+ stored.push(merged);
416
+ }
417
+ tr.setStoredMarks(stored);
418
+ } else {
419
+ state.doc.nodesBetween(from, to, (node, pos) => {
420
+ if (!node.isText) return;
421
+ const fromPos = Math.max(pos, from);
422
+ const toPos = Math.min(pos + node.nodeSize, to);
423
+ const existingTextStyle = node.marks.find(
424
+ (m) => m.type === textStyleType
425
+ );
426
+ const merged = mergeFontSize(textStyleType, existingTextStyle, fontSize);
427
+ if (hasAttrs(merged)) {
428
+ tr.addMark(fromPos, toPos, merged);
429
+ } else if (existingTextStyle) {
430
+ tr.removeMark(fromPos, toPos, existingTextStyle);
431
+ }
432
+ });
433
+ }
434
+ if (dispatch) dispatch(tr);
435
+ return true;
436
+ },
437
+ unsetFontSize: () => ({ tr, state, dispatch }) => {
438
+ const textStyleType = state.schema.marks.textStyle;
439
+ const { from, to, empty } = state.selection;
440
+ if (empty) {
441
+ const stored = tr.storedMarks ? [...tr.storedMarks] : [...state.storedMarks ?? []];
442
+ const idx = stored.findIndex((m) => m.type === textStyleType);
443
+ if (idx >= 0) {
444
+ const merged = mergeFontSize(textStyleType, stored[idx], null);
445
+ if (hasAttrs(merged)) {
446
+ stored[idx] = merged;
447
+ } else {
448
+ stored.splice(idx, 1);
449
+ }
450
+ tr.setStoredMarks(stored);
451
+ }
452
+ } else {
453
+ state.doc.nodesBetween(from, to, (node, pos) => {
454
+ if (!node.isText) return;
455
+ const fromPos = Math.max(pos, from);
456
+ const toPos = Math.min(pos + node.nodeSize, to);
457
+ const existingTextStyle = node.marks.find(
458
+ (m) => m.type === textStyleType
459
+ );
460
+ if (!existingTextStyle) return;
461
+ const merged = mergeFontSize(textStyleType, existingTextStyle, null);
462
+ if (hasAttrs(merged)) {
463
+ tr.addMark(fromPos, toPos, merged);
464
+ } else {
465
+ tr.removeMark(fromPos, toPos, existingTextStyle);
466
+ }
467
+ });
468
+ }
469
+ if (dispatch) dispatch(tr);
470
+ return true;
471
+ }
472
+ };
473
+ }
474
+ });
475
+
476
+ // src/index.ts
477
+ var import_tiptap_pagination_plus2 = require("tiptap-pagination-plus");
478
+ // Annotate the CommonJS export names for ESM import in node:
479
+ 0 && (module.exports = {
480
+ BlockAttributesExtension,
481
+ FontSizeExtension,
482
+ PAGE_SIZES,
483
+ PaginationPlus,
484
+ collaborationExtensions,
485
+ collectExtensions,
486
+ createActionMap,
487
+ createCollaboration,
488
+ createEditor,
489
+ definePlugin,
490
+ resolveAction
491
+ });
@@ -0,0 +1,122 @@
1
+ import { AnyExtension, Editor, Extension } from '@tiptap/core';
2
+ import { Awareness } from 'y-protocols/awareness';
3
+ import { WebrtcProvider } from 'y-webrtc';
4
+ import { WebsocketProvider } from 'y-websocket';
5
+ import * as Y from 'yjs';
6
+ import { PaginationPlusOptions } from 'tiptap-pagination-plus';
7
+ export { PAGE_SIZES, PageSize, PaginationPlus, PaginationPlusOptions } from 'tiptap-pagination-plus';
8
+
9
+ interface ToolbarItem {
10
+ id: string;
11
+ icon?: string;
12
+ iconComponent?: string;
13
+ label?: string;
14
+ action: string;
15
+ args?: unknown[];
16
+ }
17
+ interface SlashCommand {
18
+ name: string;
19
+ description?: string;
20
+ command: string;
21
+ }
22
+ interface DocsEditorPlugin {
23
+ id: string;
24
+ tiptapExtensions?: AnyExtension[];
25
+ toolbar?: ToolbarItem[];
26
+ slashCommands?: SlashCommand[];
27
+ commands?: Record<string, (editor: Editor, ...args: unknown[]) => boolean>;
28
+ hooks?: {
29
+ onInit?: (editor: Editor) => void;
30
+ onDestroy?: (editor: Editor) => void;
31
+ };
32
+ }
33
+ declare function definePlugin(plugin: DocsEditorPlugin): DocsEditorPlugin;
34
+ declare function collectExtensions(plugins: DocsEditorPlugin[]): AnyExtension[];
35
+ declare function resolveAction(editor: Editor, action: string, ...args: unknown[]): boolean;
36
+ declare function createActionMap(editor: Editor, plugins: DocsEditorPlugin[]): Record<string, (...args: unknown[]) => boolean>;
37
+
38
+ interface AwarenessState {
39
+ clientId: number;
40
+ user: {
41
+ name: string;
42
+ color: string;
43
+ };
44
+ cursor?: {
45
+ from: number;
46
+ to: number;
47
+ } | null;
48
+ }
49
+ interface CollaborationOptions {
50
+ room: string;
51
+ provider?: 'webrtc' | 'websocket';
52
+ websocketUrl?: string;
53
+ signaling?: string[];
54
+ user: {
55
+ name: string;
56
+ color: string;
57
+ };
58
+ onAwarenessChange?: (states: AwarenessState[]) => void;
59
+ initialStorageState?: Uint8Array;
60
+ }
61
+ interface CollaborationSetup {
62
+ ydoc: Y.Doc;
63
+ provider: WebrtcProvider | WebsocketProvider | null;
64
+ awareness: Awareness;
65
+ destroy: () => void;
66
+ }
67
+ declare function createCollaboration(options: CollaborationOptions): CollaborationSetup;
68
+ declare function collaborationExtensions(options: CollaborationOptions | CollaborationSetup): AnyExtension[];
69
+
70
+ interface EditorOptions {
71
+ target?: HTMLElement;
72
+ content?: object | string;
73
+ plugins?: DocsEditorPlugin[];
74
+ editable?: boolean;
75
+ onUpdate?: (json: object) => void;
76
+ collaboration?: CollaborationOptions;
77
+ getPageMap?: () => Map<number, {
78
+ page: number;
79
+ blockIndex: number;
80
+ }>;
81
+ paginationOptions?: PaginationPlusOptions;
82
+ }
83
+ interface DocsEditor {
84
+ editor: Editor;
85
+ collab?: CollaborationSetup;
86
+ getJSON: () => object;
87
+ getHTML: () => string;
88
+ destroy: () => void;
89
+ use: (plugin: DocsEditorPlugin) => void;
90
+ pluginActions: Record<string, (...args: unknown[]) => boolean>;
91
+ }
92
+ declare function createEditor(options?: EditorOptions): DocsEditor;
93
+
94
+ interface BlockAttributesOptions {
95
+ pageMap?: () => Map<number, {
96
+ page: number;
97
+ blockIndex: number;
98
+ }>;
99
+ }
100
+ declare const BlockAttributesExtension: Extension<BlockAttributesOptions, any>;
101
+
102
+ declare module '@tiptap/core' {
103
+ interface Commands<ReturnType> {
104
+ fontSize: {
105
+ /** Set font size on the current selection, e.g. '12px'. */
106
+ setFontSize: (fontSize: string) => ReturnType;
107
+ /** Remove font size from the current selection. */
108
+ unsetFontSize: () => ReturnType;
109
+ };
110
+ }
111
+ }
112
+ /**
113
+ * FontSizeExtension — adds a `fontSize` attribute onto TextStyle marks.
114
+ * Requires TextStyle to be registered separately (done in Editor.ts).
115
+ *
116
+ * Uses direct transaction manipulation (tr.addMark / tr.addStoredMark) to:
117
+ * 1. Avoid chaining conflicts when called from toolbar via chain().setFontSize()
118
+ * 2. Properly merge font-size with existing textStyle attributes (color, etc.)
119
+ */
120
+ declare const FontSizeExtension: Extension<any, any>;
121
+
122
+ export { type AwarenessState, BlockAttributesExtension, type CollaborationOptions, type CollaborationSetup, type DocsEditor, type DocsEditorPlugin, type EditorOptions, FontSizeExtension, type SlashCommand, type ToolbarItem, collaborationExtensions, collectExtensions, createActionMap, createCollaboration, createEditor, definePlugin, resolveAction };
@@ -0,0 +1,122 @@
1
+ import { AnyExtension, Editor, Extension } from '@tiptap/core';
2
+ import { Awareness } from 'y-protocols/awareness';
3
+ import { WebrtcProvider } from 'y-webrtc';
4
+ import { WebsocketProvider } from 'y-websocket';
5
+ import * as Y from 'yjs';
6
+ import { PaginationPlusOptions } from 'tiptap-pagination-plus';
7
+ export { PAGE_SIZES, PageSize, PaginationPlus, PaginationPlusOptions } from 'tiptap-pagination-plus';
8
+
9
+ interface ToolbarItem {
10
+ id: string;
11
+ icon?: string;
12
+ iconComponent?: string;
13
+ label?: string;
14
+ action: string;
15
+ args?: unknown[];
16
+ }
17
+ interface SlashCommand {
18
+ name: string;
19
+ description?: string;
20
+ command: string;
21
+ }
22
+ interface DocsEditorPlugin {
23
+ id: string;
24
+ tiptapExtensions?: AnyExtension[];
25
+ toolbar?: ToolbarItem[];
26
+ slashCommands?: SlashCommand[];
27
+ commands?: Record<string, (editor: Editor, ...args: unknown[]) => boolean>;
28
+ hooks?: {
29
+ onInit?: (editor: Editor) => void;
30
+ onDestroy?: (editor: Editor) => void;
31
+ };
32
+ }
33
+ declare function definePlugin(plugin: DocsEditorPlugin): DocsEditorPlugin;
34
+ declare function collectExtensions(plugins: DocsEditorPlugin[]): AnyExtension[];
35
+ declare function resolveAction(editor: Editor, action: string, ...args: unknown[]): boolean;
36
+ declare function createActionMap(editor: Editor, plugins: DocsEditorPlugin[]): Record<string, (...args: unknown[]) => boolean>;
37
+
38
+ interface AwarenessState {
39
+ clientId: number;
40
+ user: {
41
+ name: string;
42
+ color: string;
43
+ };
44
+ cursor?: {
45
+ from: number;
46
+ to: number;
47
+ } | null;
48
+ }
49
+ interface CollaborationOptions {
50
+ room: string;
51
+ provider?: 'webrtc' | 'websocket';
52
+ websocketUrl?: string;
53
+ signaling?: string[];
54
+ user: {
55
+ name: string;
56
+ color: string;
57
+ };
58
+ onAwarenessChange?: (states: AwarenessState[]) => void;
59
+ initialStorageState?: Uint8Array;
60
+ }
61
+ interface CollaborationSetup {
62
+ ydoc: Y.Doc;
63
+ provider: WebrtcProvider | WebsocketProvider | null;
64
+ awareness: Awareness;
65
+ destroy: () => void;
66
+ }
67
+ declare function createCollaboration(options: CollaborationOptions): CollaborationSetup;
68
+ declare function collaborationExtensions(options: CollaborationOptions | CollaborationSetup): AnyExtension[];
69
+
70
+ interface EditorOptions {
71
+ target?: HTMLElement;
72
+ content?: object | string;
73
+ plugins?: DocsEditorPlugin[];
74
+ editable?: boolean;
75
+ onUpdate?: (json: object) => void;
76
+ collaboration?: CollaborationOptions;
77
+ getPageMap?: () => Map<number, {
78
+ page: number;
79
+ blockIndex: number;
80
+ }>;
81
+ paginationOptions?: PaginationPlusOptions;
82
+ }
83
+ interface DocsEditor {
84
+ editor: Editor;
85
+ collab?: CollaborationSetup;
86
+ getJSON: () => object;
87
+ getHTML: () => string;
88
+ destroy: () => void;
89
+ use: (plugin: DocsEditorPlugin) => void;
90
+ pluginActions: Record<string, (...args: unknown[]) => boolean>;
91
+ }
92
+ declare function createEditor(options?: EditorOptions): DocsEditor;
93
+
94
+ interface BlockAttributesOptions {
95
+ pageMap?: () => Map<number, {
96
+ page: number;
97
+ blockIndex: number;
98
+ }>;
99
+ }
100
+ declare const BlockAttributesExtension: Extension<BlockAttributesOptions, any>;
101
+
102
+ declare module '@tiptap/core' {
103
+ interface Commands<ReturnType> {
104
+ fontSize: {
105
+ /** Set font size on the current selection, e.g. '12px'. */
106
+ setFontSize: (fontSize: string) => ReturnType;
107
+ /** Remove font size from the current selection. */
108
+ unsetFontSize: () => ReturnType;
109
+ };
110
+ }
111
+ }
112
+ /**
113
+ * FontSizeExtension — adds a `fontSize` attribute onto TextStyle marks.
114
+ * Requires TextStyle to be registered separately (done in Editor.ts).
115
+ *
116
+ * Uses direct transaction manipulation (tr.addMark / tr.addStoredMark) to:
117
+ * 1. Avoid chaining conflicts when called from toolbar via chain().setFontSize()
118
+ * 2. Properly merge font-size with existing textStyle attributes (color, etc.)
119
+ */
120
+ declare const FontSizeExtension: Extension<any, any>;
121
+
122
+ export { type AwarenessState, BlockAttributesExtension, type CollaborationOptions, type CollaborationSetup, type DocsEditor, type DocsEditorPlugin, type EditorOptions, FontSizeExtension, type SlashCommand, type ToolbarItem, collaborationExtensions, collectExtensions, createActionMap, createCollaboration, createEditor, definePlugin, resolveAction };
package/dist/index.js ADDED
@@ -0,0 +1,444 @@
1
+ // src/Editor.ts
2
+ import { Editor as TiptapEditor, getSchema } from "@tiptap/core";
3
+ import StarterKit from "@tiptap/starter-kit";
4
+ import TextStyle from "@tiptap/extension-text-style";
5
+ import { prosemirrorJSONToYXmlFragment } from "y-prosemirror";
6
+
7
+ // src/PluginSystem.ts
8
+ function definePlugin(plugin) {
9
+ return plugin;
10
+ }
11
+ function collectExtensions(plugins) {
12
+ const extensions = [];
13
+ for (const plugin of plugins) {
14
+ if (plugin.tiptapExtensions) {
15
+ extensions.push(...plugin.tiptapExtensions);
16
+ }
17
+ }
18
+ return extensions;
19
+ }
20
+ function resolveAction(editor, action, ...args) {
21
+ const commands = editor.commands;
22
+ const command = commands[action];
23
+ if (typeof command !== "function") {
24
+ return false;
25
+ }
26
+ const result = command(...args);
27
+ return result === true;
28
+ }
29
+ function createActionMap(editor, plugins) {
30
+ const map = {};
31
+ for (const plugin of plugins) {
32
+ for (const item of plugin.toolbar ?? []) {
33
+ const custom = plugin.commands?.[item.action];
34
+ map[item.action] = (...args) => {
35
+ if (typeof custom === "function") {
36
+ return custom(editor, ...args);
37
+ }
38
+ return resolveAction(editor, item.action, ...args);
39
+ };
40
+ }
41
+ for (const slash of plugin.slashCommands ?? []) {
42
+ const custom = plugin.commands?.[slash.command];
43
+ map[slash.command] = (...args) => {
44
+ if (typeof custom === "function") {
45
+ return custom(editor, ...args);
46
+ }
47
+ return resolveAction(editor, slash.command, ...args);
48
+ };
49
+ }
50
+ }
51
+ return map;
52
+ }
53
+
54
+ // src/Collaboration.ts
55
+ import { Collaboration } from "@tiptap/extension-collaboration";
56
+ import { CollaborationCursor } from "@tiptap/extension-collaboration-cursor";
57
+ import { Awareness } from "y-protocols/awareness";
58
+ import { WebrtcProvider } from "y-webrtc";
59
+ import { WebsocketProvider } from "y-websocket";
60
+ import * as Y from "yjs";
61
+ function createAwarenessStates(awareness) {
62
+ const states = [];
63
+ awareness.getStates().forEach((state, clientId) => {
64
+ const raw = state;
65
+ states.push({
66
+ clientId,
67
+ user: raw.user ?? { name: "", color: "" },
68
+ cursor: raw.cursor ?? null
69
+ });
70
+ });
71
+ return states;
72
+ }
73
+ function createCollaboration(options) {
74
+ const ydoc = new Y.Doc();
75
+ if (options.initialStorageState) {
76
+ Y.applyUpdate(ydoc, options.initialStorageState);
77
+ }
78
+ let provider = null;
79
+ if (options.provider === "webrtc") {
80
+ provider = new WebrtcProvider(options.room, ydoc, {
81
+ signaling: options.signaling || [
82
+ "ws://localhost:4444",
83
+ "wss://signaling.yjs.dev",
84
+ "wss://y-webrtc-eu.fly.dev"
85
+ ]
86
+ });
87
+ } else if (options.provider === "websocket") {
88
+ if (!options.websocketUrl) {
89
+ throw new Error('[Collaboration] websocketUrl is required when provider is "websocket"');
90
+ }
91
+ provider = new WebsocketProvider(options.websocketUrl, options.room, ydoc);
92
+ }
93
+ const awareness = provider?.awareness ?? new Awareness(ydoc);
94
+ awareness.setLocalStateField("user", options.user);
95
+ let awarenessHandler;
96
+ if (options.onAwarenessChange) {
97
+ const notify = () => {
98
+ options.onAwarenessChange?.(createAwarenessStates(awareness));
99
+ };
100
+ awarenessHandler = notify;
101
+ awareness.on("change", notify);
102
+ notify();
103
+ }
104
+ const destroy = () => {
105
+ if (awarenessHandler) {
106
+ awareness.off("change", awarenessHandler);
107
+ }
108
+ awareness.setLocalState(null);
109
+ provider?.destroy?.();
110
+ awareness.destroy?.();
111
+ ydoc.destroy();
112
+ };
113
+ return { ydoc, provider, awareness, destroy };
114
+ }
115
+ function collaborationExtensions(options) {
116
+ const setup = "ydoc" in options ? options : createCollaboration(options);
117
+ const extensions = [
118
+ Collaboration.configure({ document: setup.ydoc })
119
+ ];
120
+ if (setup.provider) {
121
+ extensions.push(
122
+ CollaborationCursor.configure({
123
+ provider: setup.provider,
124
+ user: setup.awareness.getLocalState()?.user ?? { name: "", color: "" }
125
+ })
126
+ );
127
+ }
128
+ return extensions;
129
+ }
130
+
131
+ // src/BlockAttributes.ts
132
+ import { Extension } from "@tiptap/core";
133
+ import { Plugin, PluginKey } from "@tiptap/pm/state";
134
+ import { Decoration, DecorationSet } from "@tiptap/pm/view";
135
+ var BlockAttributesExtension = Extension.create({
136
+ name: "blockAttributes",
137
+ addOptions() {
138
+ return {
139
+ pageMap: () => /* @__PURE__ */ new Map()
140
+ };
141
+ },
142
+ addProseMirrorPlugins() {
143
+ const getPageMap = this.options.pageMap;
144
+ return [
145
+ new Plugin({
146
+ key: new PluginKey("blockAttributes"),
147
+ props: {
148
+ decorations(state) {
149
+ const decorations = [];
150
+ const pageMap = getPageMap();
151
+ if (pageMap.size === 0) return DecorationSet.create(state.doc, decorations);
152
+ const maxIdxPerPage = /* @__PURE__ */ new Map();
153
+ pageMap.forEach((info) => {
154
+ const cur = maxIdxPerPage.get(info.page) ?? -1;
155
+ if (info.blockIndex > cur) maxIdxPerPage.set(info.page, info.blockIndex);
156
+ });
157
+ state.doc.descendants((node, pos) => {
158
+ if (!node.isBlock) return;
159
+ const attrs = {
160
+ "data-from": String(pos),
161
+ "data-to": String(pos + node.nodeSize),
162
+ "data-node-type": node.type.name
163
+ };
164
+ const pageInfo = pageMap.get(pos);
165
+ if (pageInfo) {
166
+ attrs["data-page"] = String(pageInfo.page);
167
+ attrs["data-page-block-index"] = String(pageInfo.blockIndex);
168
+ const maxIdx = maxIdxPerPage.get(pageInfo.page);
169
+ const styleParts = [];
170
+ if (pageInfo.page > 1 && pageInfo.blockIndex === 0) {
171
+ styleParts.push("margin-top:72px");
172
+ }
173
+ if (maxIdx !== void 0 && pageInfo.blockIndex === maxIdx) {
174
+ styleParts.push("margin-bottom:72px");
175
+ }
176
+ if (styleParts.length > 0) {
177
+ attrs.style = styleParts.join(";");
178
+ }
179
+ }
180
+ decorations.push(
181
+ Decoration.node(pos, pos + node.nodeSize, attrs)
182
+ );
183
+ });
184
+ return DecorationSet.create(state.doc, decorations);
185
+ }
186
+ }
187
+ })
188
+ ];
189
+ }
190
+ });
191
+
192
+ // src/Editor.ts
193
+ import { PaginationPlus } from "tiptap-pagination-plus";
194
+ function migrateContent(content) {
195
+ if (!content) return content;
196
+ if (typeof content === "string") {
197
+ try {
198
+ const parsed = JSON.parse(content);
199
+ return JSON.stringify(migrateContent(parsed));
200
+ } catch {
201
+ return content;
202
+ }
203
+ }
204
+ if (typeof content !== "object" || content === null) return content;
205
+ const obj = content;
206
+ if (obj.type === "doc" && Array.isArray(obj.content)) {
207
+ const newContentList = [];
208
+ for (const child of obj.content) {
209
+ const childObj = child;
210
+ if (childObj && childObj.type === "page" && Array.isArray(childObj.content)) {
211
+ newContentList.push(...childObj.content);
212
+ } else {
213
+ newContentList.push(child);
214
+ }
215
+ }
216
+ return { ...obj, content: newContentList };
217
+ }
218
+ if (obj.type === "tabbed-doc" && Array.isArray(obj.tabs)) {
219
+ return {
220
+ ...obj,
221
+ tabs: obj.tabs.map((tab) => ({
222
+ ...tab,
223
+ content: migrateContent(tab.content)
224
+ }))
225
+ };
226
+ }
227
+ return content;
228
+ }
229
+ function createEditor(options = {}) {
230
+ const migratedOptions = {
231
+ ...options,
232
+ content: options.content ? migrateContent(options.content) : options.content
233
+ };
234
+ const plugins = migratedOptions.plugins ?? [];
235
+ const collaborationSetup = migratedOptions.collaboration ? createCollaboration(migratedOptions.collaboration) : void 0;
236
+ let tiptapEditor = createTiptapEditor(migratedOptions, plugins, collaborationSetup);
237
+ let pluginActions = createActionMap(tiptapEditor, plugins);
238
+ for (const plugin of plugins) {
239
+ plugin.hooks?.onInit?.(tiptapEditor);
240
+ }
241
+ const rebuildEditor = () => {
242
+ const currentJSON = tiptapEditor.getJSON();
243
+ const selection = tiptapEditor.state.selection;
244
+ const target = migratedOptions.target;
245
+ tiptapEditor.destroy();
246
+ tiptapEditor = createTiptapEditor(
247
+ { ...migratedOptions, content: currentJSON },
248
+ plugins,
249
+ collaborationSetup
250
+ );
251
+ try {
252
+ const { from, to } = selection;
253
+ if (from >= 0 && to >= from && to <= tiptapEditor.state.doc.content.size) {
254
+ tiptapEditor.commands.setTextSelection({ from, to });
255
+ }
256
+ } catch {
257
+ }
258
+ if (target) {
259
+ tiptapEditor.commands.focus();
260
+ }
261
+ pluginActions = createActionMap(tiptapEditor, plugins);
262
+ };
263
+ const editor = {
264
+ get editor() {
265
+ return tiptapEditor;
266
+ },
267
+ collab: collaborationSetup,
268
+ getJSON: () => tiptapEditor.getJSON(),
269
+ getHTML: () => tiptapEditor.getHTML(),
270
+ destroy: () => {
271
+ for (const plugin of plugins) {
272
+ plugin.hooks?.onDestroy?.(tiptapEditor);
273
+ }
274
+ tiptapEditor.destroy();
275
+ collaborationSetup?.destroy();
276
+ },
277
+ use: (plugin) => {
278
+ plugins.push(plugin);
279
+ rebuildEditor();
280
+ plugin.hooks?.onInit?.(tiptapEditor);
281
+ },
282
+ get pluginActions() {
283
+ return pluginActions;
284
+ }
285
+ };
286
+ return editor;
287
+ }
288
+ function createTiptapEditor(options, plugins, collaborationSetup) {
289
+ const baseStarterKit = options.collaboration ? StarterKit.configure({ history: false }) : StarterKit;
290
+ const pluginExtensions = collectExtensions(plugins);
291
+ const blockAttrs = options.getPageMap ? BlockAttributesExtension.configure({ pageMap: options.getPageMap }) : BlockAttributesExtension;
292
+ const paginationExt = options.paginationOptions ? PaginationPlus.configure(options.paginationOptions) : PaginationPlus;
293
+ let extensions = [
294
+ baseStarterKit,
295
+ TextStyle,
296
+ blockAttrs,
297
+ paginationExt,
298
+ ...pluginExtensions
299
+ ];
300
+ const content = options.collaboration ? void 0 : options.content;
301
+ if (options.collaboration && collaborationSetup) {
302
+ const fragment = collaborationSetup.ydoc.getXmlFragment("default");
303
+ if (fragment.length === 0 && options.content && typeof options.content === "object") {
304
+ const schema = getSchema([baseStarterKit, TextStyle, blockAttrs, paginationExt, ...pluginExtensions]);
305
+ prosemirrorJSONToYXmlFragment(schema, options.content, fragment);
306
+ }
307
+ extensions = [...extensions, ...collaborationExtensions(collaborationSetup)];
308
+ }
309
+ return new TiptapEditor({
310
+ element: options.target,
311
+ content,
312
+ extensions,
313
+ editable: options.editable ?? true,
314
+ onUpdate: ({ editor }) => {
315
+ options.onUpdate?.(editor.getJSON());
316
+ }
317
+ });
318
+ }
319
+
320
+ // src/FontSize.ts
321
+ import { Extension as Extension2 } from "@tiptap/core";
322
+ function mergeFontSize(textStyleType, existing, fontSize) {
323
+ if (fontSize === null) {
324
+ const { fontSize: _removed, ...rest } = existing?.attrs ?? {};
325
+ return textStyleType.create(rest);
326
+ }
327
+ return textStyleType.create({ ...existing?.attrs, fontSize });
328
+ }
329
+ function hasAttrs(mark) {
330
+ return Object.values(mark.attrs).some((v) => v != null);
331
+ }
332
+ var FontSizeExtension = Extension2.create({
333
+ name: "fontSize",
334
+ addGlobalAttributes() {
335
+ return [
336
+ {
337
+ types: ["textStyle"],
338
+ attributes: {
339
+ fontSize: {
340
+ default: null,
341
+ parseHTML: (el) => el.style.fontSize || null,
342
+ renderHTML: (attrs) => {
343
+ if (!attrs.fontSize) return {};
344
+ return { style: `font-size: ${attrs.fontSize}` };
345
+ }
346
+ }
347
+ }
348
+ }
349
+ ];
350
+ },
351
+ addCommands() {
352
+ return {
353
+ setFontSize: (fontSize) => ({ tr, state, dispatch }) => {
354
+ console.log("[FontSizeExt] setFontSize called, fontSize:", fontSize, "empty:", state.selection.empty);
355
+ const textStyleType = state.schema.marks.textStyle;
356
+ const { from, to, empty } = state.selection;
357
+ if (empty) {
358
+ const stored = tr.storedMarks ? [...tr.storedMarks] : [...state.storedMarks ?? []];
359
+ const idx = stored.findIndex((m) => m.type === textStyleType);
360
+ const existing = idx >= 0 ? stored[idx] : void 0;
361
+ const merged = mergeFontSize(textStyleType, existing, fontSize);
362
+ if (idx >= 0) {
363
+ if (hasAttrs(merged)) {
364
+ stored[idx] = merged;
365
+ } else {
366
+ stored.splice(idx, 1);
367
+ }
368
+ } else {
369
+ stored.push(merged);
370
+ }
371
+ tr.setStoredMarks(stored);
372
+ } else {
373
+ state.doc.nodesBetween(from, to, (node, pos) => {
374
+ if (!node.isText) return;
375
+ const fromPos = Math.max(pos, from);
376
+ const toPos = Math.min(pos + node.nodeSize, to);
377
+ const existingTextStyle = node.marks.find(
378
+ (m) => m.type === textStyleType
379
+ );
380
+ const merged = mergeFontSize(textStyleType, existingTextStyle, fontSize);
381
+ if (hasAttrs(merged)) {
382
+ tr.addMark(fromPos, toPos, merged);
383
+ } else if (existingTextStyle) {
384
+ tr.removeMark(fromPos, toPos, existingTextStyle);
385
+ }
386
+ });
387
+ }
388
+ if (dispatch) dispatch(tr);
389
+ return true;
390
+ },
391
+ unsetFontSize: () => ({ tr, state, dispatch }) => {
392
+ const textStyleType = state.schema.marks.textStyle;
393
+ const { from, to, empty } = state.selection;
394
+ if (empty) {
395
+ const stored = tr.storedMarks ? [...tr.storedMarks] : [...state.storedMarks ?? []];
396
+ const idx = stored.findIndex((m) => m.type === textStyleType);
397
+ if (idx >= 0) {
398
+ const merged = mergeFontSize(textStyleType, stored[idx], null);
399
+ if (hasAttrs(merged)) {
400
+ stored[idx] = merged;
401
+ } else {
402
+ stored.splice(idx, 1);
403
+ }
404
+ tr.setStoredMarks(stored);
405
+ }
406
+ } else {
407
+ state.doc.nodesBetween(from, to, (node, pos) => {
408
+ if (!node.isText) return;
409
+ const fromPos = Math.max(pos, from);
410
+ const toPos = Math.min(pos + node.nodeSize, to);
411
+ const existingTextStyle = node.marks.find(
412
+ (m) => m.type === textStyleType
413
+ );
414
+ if (!existingTextStyle) return;
415
+ const merged = mergeFontSize(textStyleType, existingTextStyle, null);
416
+ if (hasAttrs(merged)) {
417
+ tr.addMark(fromPos, toPos, merged);
418
+ } else {
419
+ tr.removeMark(fromPos, toPos, existingTextStyle);
420
+ }
421
+ });
422
+ }
423
+ if (dispatch) dispatch(tr);
424
+ return true;
425
+ }
426
+ };
427
+ }
428
+ });
429
+
430
+ // src/index.ts
431
+ import { PaginationPlus as PaginationPlus2, PAGE_SIZES } from "tiptap-pagination-plus";
432
+ export {
433
+ BlockAttributesExtension,
434
+ FontSizeExtension,
435
+ PAGE_SIZES,
436
+ PaginationPlus2 as PaginationPlus,
437
+ collaborationExtensions,
438
+ collectExtensions,
439
+ createActionMap,
440
+ createCollaboration,
441
+ createEditor,
442
+ definePlugin,
443
+ resolveAction
444
+ };
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@kedataindo/docflow-core",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ }
14
+ },
15
+ "publishConfig": {
16
+ "registry": "https://registry.npmjs.org",
17
+ "access": "public"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "dependencies": {
23
+ "@tiptap/core": "^2.11.0",
24
+ "@tiptap/extension-collaboration": "^2.27.2",
25
+ "@tiptap/extension-collaboration-cursor": "^2.26.2",
26
+ "@tiptap/extension-text-style": "^2.11.0",
27
+ "@tiptap/pm": "^2.11.0",
28
+ "@tiptap/starter-kit": "^2.11.0",
29
+ "tiptap-pagination-plus": "3.1.0",
30
+ "y-prosemirror": "^1.2.12",
31
+ "y-protocols": "^1.0.7",
32
+ "yjs": "^13.6.20"
33
+ },
34
+ "peerDependencies": {
35
+ "@tiptap/core": "^2.11.0",
36
+ "@tiptap/extension-collaboration": "^2.27.2",
37
+ "@tiptap/extension-collaboration-cursor": "^2.26.2",
38
+ "@tiptap/extension-text-style": "^2.11.0",
39
+ "@tiptap/starter-kit": "^2.11.0",
40
+ "tiptap-pagination-plus": "3.1.0",
41
+ "y-prosemirror": "^1.2.12",
42
+ "y-webrtc": "^10.3.0",
43
+ "y-websocket": "^2.0.4",
44
+ "yjs": "^13.6.20"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "@tiptap/extension-collaboration": {
48
+ "optional": true
49
+ },
50
+ "@tiptap/extension-collaboration-cursor": {
51
+ "optional": true
52
+ },
53
+ "y-webrtc": {
54
+ "optional": true
55
+ },
56
+ "y-websocket": {
57
+ "optional": true
58
+ }
59
+ },
60
+ "devDependencies": {
61
+ "@vitest/coverage-v8": "^2.1.3",
62
+ "happy-dom": "^20.10.6",
63
+ "tsup": "^8.3.0",
64
+ "typescript": "^5.6.3",
65
+ "vitest": "^2.1.3"
66
+ },
67
+ "scripts": {
68
+ "build": "tsup src/index.ts --format esm,cjs --dts",
69
+ "typecheck": "tsc --noEmit",
70
+ "test:unit": "vitest run"
71
+ }
72
+ }