@kedataindo/docflow-core 0.0.2 → 0.0.4

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.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // src/Editor.ts
2
- import { Editor as TiptapEditor, getSchema } from "@tiptap/core";
2
+ import { Extension as Extension5, Editor as TiptapEditor } from "@tiptap/core";
3
+ import { Plugin as Plugin4, PluginKey as PluginKey4 } from "@tiptap/pm/state";
3
4
  import StarterKit from "@tiptap/starter-kit";
4
5
  import TextStyle from "@tiptap/extension-text-style";
5
- import { prosemirrorJSONToYXmlFragment } from "y-prosemirror";
6
6
 
7
7
  // src/PluginSystem.ts
8
8
  function definePlugin(plugin) {
@@ -55,9 +55,23 @@ function createActionMap(editor, plugins) {
55
55
  import { Collaboration } from "@tiptap/extension-collaboration";
56
56
  import { CollaborationCursor } from "@tiptap/extension-collaboration-cursor";
57
57
  import { Awareness } from "y-protocols/awareness";
58
+ import { IndexeddbPersistence } from "y-indexeddb";
58
59
  import { WebrtcProvider } from "y-webrtc";
59
60
  import { WebsocketProvider } from "y-websocket";
60
61
  import * as Y from "yjs";
62
+ var LOCAL_SIGNALING = ["ws://localhost:4444"];
63
+ var warnedLocalSignaling = false;
64
+ function resolveSignalingUrls(signaling) {
65
+ if (signaling && signaling.length > 0) return signaling;
66
+ if (!warnedLocalSignaling) {
67
+ warnedLocalSignaling = true;
68
+ console.warn(
69
+ '[docflow] webrtc provider has no `signaling` configured \u2014 falling back to localhost-only sync (ws://localhost:4444 + same-browser tabs). For production self-host, run your own signaling server and pass `signaling`, or use `provider: "websocket"` with your own websocketUrl.'
70
+ );
71
+ }
72
+ return LOCAL_SIGNALING;
73
+ }
74
+ var LOCAL_PRESENT_DEFAULT = true;
61
75
  function createAwarenessStates(awareness) {
62
76
  const states = [];
63
77
  awareness.getStates().forEach((state, clientId) => {
@@ -65,7 +79,11 @@ function createAwarenessStates(awareness) {
65
79
  states.push({
66
80
  clientId,
67
81
  user: raw.user ?? { name: "", color: "" },
68
- cursor: raw.cursor ?? null
82
+ cursor: raw.cursor ?? null,
83
+ // `present` defaults to true for backwards compat (legacy states
84
+ // don't set it) and for the local user (always considered present
85
+ // until PR2 toggles it off).
86
+ present: raw.present ?? LOCAL_PRESENT_DEFAULT
69
87
  });
70
88
  });
71
89
  return states;
@@ -75,14 +93,14 @@ function createCollaboration(options) {
75
93
  if (options.initialStorageState) {
76
94
  Y.applyUpdate(ydoc, options.initialStorageState);
77
95
  }
96
+ let persistence;
97
+ if (options.offline) {
98
+ persistence = new IndexeddbPersistence(`docflow-${options.room}`, ydoc);
99
+ }
78
100
  let provider = null;
79
101
  if (options.provider === "webrtc") {
80
102
  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
- ]
103
+ signaling: resolveSignalingUrls(options.signaling)
86
104
  });
87
105
  } else if (options.provider === "websocket") {
88
106
  if (!options.websocketUrl) {
@@ -92,6 +110,16 @@ function createCollaboration(options) {
92
110
  }
93
111
  const awareness = provider?.awareness ?? new Awareness(ydoc);
94
112
  awareness.setLocalStateField("user", options.user);
113
+ let emitCursor = options.emitCursor ?? true;
114
+ const setLocalCursorEnabled = (enabled) => {
115
+ if (emitCursor === enabled) return;
116
+ emitCursor = enabled;
117
+ if (!enabled) {
118
+ awareness.setLocalStateField("cursor", null);
119
+ }
120
+ awareness.setLocalStateField("present", enabled);
121
+ };
122
+ awareness.setLocalStateField("present", emitCursor);
95
123
  let awarenessHandler;
96
124
  if (options.onAwarenessChange) {
97
125
  const notify = () => {
@@ -108,9 +136,10 @@ function createCollaboration(options) {
108
136
  awareness.setLocalState(null);
109
137
  provider?.destroy?.();
110
138
  awareness.destroy?.();
139
+ void persistence?.destroy();
111
140
  ydoc.destroy();
112
141
  };
113
- return { ydoc, provider, awareness, destroy };
142
+ return { ydoc, provider, awareness, persistence, destroy, setLocalCursorEnabled };
114
143
  }
115
144
  function collaborationExtensions(options) {
116
145
  const setup = "ydoc" in options ? options : createCollaboration(options);
@@ -189,8 +218,1016 @@ var BlockAttributesExtension = Extension.create({
189
218
  }
190
219
  });
191
220
 
221
+ // src/EditorContext.ts
222
+ import { Extension as Extension2 } from "@tiptap/core";
223
+ var EditorContextExtension = Extension2.create({
224
+ name: "editorContext",
225
+ addOptions() {
226
+ return {
227
+ onImageUpload: void 0,
228
+ citation: void 0,
229
+ aiStream: void 0,
230
+ aiDraft: void 0
231
+ };
232
+ },
233
+ addStorage() {
234
+ return {
235
+ onImageUpload: this.options.onImageUpload,
236
+ citation: this.options.citation,
237
+ aiStream: this.options.aiStream,
238
+ aiDraft: this.options.aiDraft
239
+ };
240
+ }
241
+ });
242
+
243
+ // src/SearchAndReplace.ts
244
+ import { Extension as Extension3 } from "@tiptap/core";
245
+ import { Plugin as Plugin2, PluginKey as PluginKey2, TextSelection } from "@tiptap/pm/state";
246
+ import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "@tiptap/pm/view";
247
+ var searchAndReplaceKey = new PluginKey2("searchAndReplace");
248
+ var EMPTY_STATE = { query: "", matches: [], activeIndex: 0 };
249
+ function findMatches(doc, query) {
250
+ const matches = [];
251
+ if (!query) return matches;
252
+ const needle = query.toLowerCase();
253
+ doc.descendants((node, pos) => {
254
+ if (!node.isText || !node.text) return;
255
+ const hay = node.text.toLowerCase();
256
+ let idx = hay.indexOf(needle);
257
+ while (idx !== -1) {
258
+ matches.push({ from: pos + idx, to: pos + idx + needle.length });
259
+ idx = hay.indexOf(needle, idx + needle.length);
260
+ }
261
+ });
262
+ return matches;
263
+ }
264
+ function clampIndex(index, matches) {
265
+ if (matches.length === 0) return 0;
266
+ return Math.min(Math.max(index, 0), matches.length - 1);
267
+ }
268
+ function computeState(doc, query, activeIndex = 0) {
269
+ const matches = findMatches(doc, query);
270
+ return { query, matches, activeIndex: clampIndex(activeIndex, matches) };
271
+ }
272
+ var searchPlugin = new Plugin2({
273
+ key: searchAndReplaceKey,
274
+ state: {
275
+ init: () => EMPTY_STATE,
276
+ apply: (tr, prev) => {
277
+ const meta = tr.getMeta(searchAndReplaceKey);
278
+ if (meta) {
279
+ if (meta.type === "clear") return EMPTY_STATE;
280
+ if (meta.type === "set") return computeState(tr.doc, meta.query);
281
+ return { ...prev, activeIndex: clampIndex(meta.index, prev.matches) };
282
+ }
283
+ if (tr.docChanged && prev.query) {
284
+ return computeState(tr.doc, prev.query, prev.activeIndex);
285
+ }
286
+ return prev;
287
+ }
288
+ },
289
+ props: {
290
+ decorations: (state) => {
291
+ const s = searchAndReplaceKey.getState(state);
292
+ if (!s || s.matches.length === 0) return null;
293
+ return DecorationSet2.create(
294
+ state.doc,
295
+ s.matches.map(
296
+ (m, i) => Decoration2.inline(m.from, m.to, {
297
+ class: i === s.activeIndex ? "find-match find-match-active" : "find-match"
298
+ })
299
+ )
300
+ );
301
+ }
302
+ }
303
+ });
304
+ var SearchAndReplaceExtension = Extension3.create({
305
+ name: "searchAndReplace",
306
+ addProseMirrorPlugins() {
307
+ return [searchPlugin];
308
+ }
309
+ });
310
+ function getSearchState(editor) {
311
+ return searchAndReplaceKey.getState(editor.state) ?? EMPTY_STATE;
312
+ }
313
+ function setSearchQuery(editor, query) {
314
+ editor.view.dispatch(editor.state.tr.setMeta(searchAndReplaceKey, { type: "set", query }));
315
+ }
316
+ function clearSearch(editor) {
317
+ editor.view.dispatch(editor.state.tr.setMeta(searchAndReplaceKey, { type: "clear" }));
318
+ }
319
+ function activateMatch(editor, index) {
320
+ const s = getSearchState(editor);
321
+ const match = s.matches[index];
322
+ const tr = editor.state.tr.setMeta(searchAndReplaceKey, { type: "setActive", index });
323
+ if (match) {
324
+ tr.setSelection(TextSelection.create(editor.state.doc, match.from, match.to));
325
+ tr.scrollIntoView();
326
+ }
327
+ editor.view.dispatch(tr);
328
+ }
329
+ function searchNext(editor) {
330
+ const s = getSearchState(editor);
331
+ if (s.matches.length === 0) return null;
332
+ const next = (s.activeIndex + 1) % s.matches.length;
333
+ activateMatch(editor, next);
334
+ return s.matches[next];
335
+ }
336
+ function searchPrev(editor) {
337
+ const s = getSearchState(editor);
338
+ if (s.matches.length === 0) return null;
339
+ const prev = (s.activeIndex - 1 + s.matches.length) % s.matches.length;
340
+ activateMatch(editor, prev);
341
+ return s.matches[prev];
342
+ }
343
+ function replaceCurrent(editor, replacement) {
344
+ const s = getSearchState(editor);
345
+ const match = s.matches[s.activeIndex];
346
+ if (!match) return false;
347
+ editor.view.dispatch(editor.state.tr.insertText(replacement, match.from, match.to));
348
+ return true;
349
+ }
350
+ function replaceAll(editor, replacement) {
351
+ const s = getSearchState(editor);
352
+ if (s.matches.length === 0) return 0;
353
+ const tr = editor.state.tr;
354
+ for (let i = s.matches.length - 1; i >= 0; i--) {
355
+ tr.insertText(replacement, s.matches[i].from, s.matches[i].to);
356
+ }
357
+ editor.view.dispatch(tr);
358
+ return s.matches.length;
359
+ }
360
+
361
+ // ../../node_modules/.pnpm/tiptap-pagination-plus@3.1.0_@tiptap+core@2.27.2_@tiptap+pm@2.27.2__@tiptap+pm@2.27.2/node_modules/tiptap-pagination-plus/dist/PaginationPlus.js
362
+ import { Extension as Extension4 } from "@tiptap/core";
363
+ import { Plugin as Plugin3, PluginKey as PluginKey3 } from "@tiptap/pm/state";
364
+ import { ReplaceStep, ReplaceAroundStep, AddMarkStep, RemoveMarkStep, RemoveNodeMarkStep, AttrStep } from "@tiptap/pm/transform";
365
+ import { Decoration as Decoration3, DecorationSet as DecorationSet3 } from "@tiptap/pm/view";
366
+
367
+ // ../../node_modules/.pnpm/tiptap-pagination-plus@3.1.0_@tiptap+core@2.27.2_@tiptap+pm@2.27.2__@tiptap+pm@2.27.2/node_modules/tiptap-pagination-plus/dist/utils.js
368
+ var updateCssVariables = (targetNode, config) => {
369
+ const cssVariables = {
370
+ "rm-page-height": `${config.pageHeight}px`,
371
+ "rm-margin-top": `${config.marginTop}px`,
372
+ "rm-margin-bottom": `${config.marginBottom}px`,
373
+ "rm-margin-left": `${config.marginLeft}px`,
374
+ "rm-margin-right": `${config.marginRight}px`,
375
+ "rm-content-margin-top": `${config.contentMarginTop}px`,
376
+ "rm-content-margin-bottom": `${config.contentMarginBottom}px`,
377
+ "rm-page-gap-border-color": `${config.pageGapBorderColor}`,
378
+ "rm-page-width": `${config.pageWidth}px`
379
+ };
380
+ Object.entries(cssVariables).forEach(([key2, value]) => {
381
+ targetNode.style.setProperty(`--${key2}`, value);
382
+ });
383
+ };
384
+ var getPageSize = (height, width, marginTop, marginBottom, marginLeft, marginRight) => {
385
+ return {
386
+ pageHeight: height,
387
+ pageWidth: width,
388
+ marginTop,
389
+ marginBottom,
390
+ marginLeft,
391
+ marginRight
392
+ };
393
+ };
394
+ var getHeaderHeight = (targetNode, pageNumbers, type) => {
395
+ const headerHeightMap = /* @__PURE__ */ new Map();
396
+ const clientHeader = targetNode.querySelector(getHeaderHeightSelector(0, type));
397
+ headerHeightMap.set(0, clientHeader ? clientHeader.clientHeight : 0);
398
+ pageNumbers.forEach((pageNumber) => {
399
+ const clientHeader2 = targetNode.querySelector(getHeaderHeightSelector(pageNumber, type));
400
+ const headerHeight = clientHeader2 ? clientHeader2.clientHeight : 0;
401
+ headerHeightMap.set(pageNumber, headerHeight);
402
+ });
403
+ return headerHeightMap;
404
+ };
405
+ var getHeaderHeightSelector = (pageNumber, type) => {
406
+ return type === "actual" ? `.rm-page-header-${pageNumber}` : `.rm-page-header-${pageNumber} .rm-page-header-content`;
407
+ };
408
+ var getFooterHeight = (targetNode, pageNumbers, type) => {
409
+ const footerHeightMap = /* @__PURE__ */ new Map();
410
+ const clientFooter = targetNode.querySelector(getFooterHeightSelector(0, type));
411
+ footerHeightMap.set(0, clientFooter ? clientFooter.clientHeight : 0);
412
+ pageNumbers.forEach((pageNumber) => {
413
+ const clientFooter2 = targetNode.querySelector(getFooterHeightSelector(pageNumber, type));
414
+ const footerHeight = clientFooter2 ? clientFooter2.clientHeight : 0;
415
+ footerHeightMap.set(pageNumber, footerHeight);
416
+ });
417
+ return footerHeightMap;
418
+ };
419
+ var getFooterHeightSelector = (pageNumber, type) => {
420
+ return type === "actual" ? `.rm-page-footer-${pageNumber}` : `.rm-page-footer-${pageNumber} .rm-page-footer-content`;
421
+ };
422
+ function deepEqualIterative(a, b) {
423
+ if (a === b)
424
+ return true;
425
+ if (typeof a !== "object" || typeof b !== "object" || a == null || b == null) {
426
+ return false;
427
+ }
428
+ const stack = [{ x: a, y: b }];
429
+ while (stack.length) {
430
+ const _stackItem = stack.pop();
431
+ if (!_stackItem)
432
+ continue;
433
+ const { x, y } = _stackItem;
434
+ if (x === y)
435
+ continue;
436
+ if (typeof x !== typeof y)
437
+ return false;
438
+ if (typeof x !== "object")
439
+ return false;
440
+ if (x == null || y == null)
441
+ return false;
442
+ const xKeys = Object.keys(x);
443
+ const yKeys = Object.keys(y);
444
+ if (xKeys.length !== yKeys.length)
445
+ return false;
446
+ for (const key2 of xKeys) {
447
+ if (!(key2 in y))
448
+ return false;
449
+ const xVal = x[key2];
450
+ const yVal = y[key2];
451
+ if (xVal === yVal)
452
+ continue;
453
+ if (typeof xVal === "object" && typeof yVal === "object") {
454
+ stack.push({ x: xVal, y: yVal });
455
+ } else {
456
+ if (xVal !== yVal)
457
+ return false;
458
+ }
459
+ }
460
+ }
461
+ return true;
462
+ }
463
+ function getCustomPages(customHeader, customFooter) {
464
+ return [...Object.keys(customHeader), ...Object.keys(customFooter)].map(Number);
465
+ }
466
+ function getFooter(footerRightContent, footerLeftContent, onFooterClick, pageNumber) {
467
+ const pageFooter = document.createElement("div");
468
+ pageFooter.classList.add("rm-page-footer");
469
+ pageFooter.classList.add(`rm-page-footer-${pageNumber ? pageNumber : 0}`);
470
+ pageFooter.style.overflow = "visible";
471
+ pageFooter.style.position = "relative";
472
+ pageFooter.style.cursor = "pointer";
473
+ const pageFooterContent = document.createElement("div");
474
+ pageFooterContent.classList.add("rm-page-footer-content");
475
+ pageFooterContent.style.width = "100%";
476
+ pageFooterContent.style.overflow = "hidden";
477
+ const footerRight = footerRightContent.replace("{page}", `<span class="rm-page-number"></span>`);
478
+ const footerLeft = footerLeftContent.replace("{page}", `<span class="rm-page-number"></span>`);
479
+ const pageFooterLeft = document.createElement("div");
480
+ pageFooterLeft.classList.add("rm-page-footer-left");
481
+ pageFooterLeft.innerHTML = footerLeft;
482
+ const pageFooterRight = document.createElement("div");
483
+ pageFooterRight.classList.add("rm-page-footer-right");
484
+ pageFooterRight.innerHTML = footerRight;
485
+ pageFooterContent.append(pageFooterLeft, pageFooterRight);
486
+ pageFooter.append(pageFooterContent);
487
+ pageFooter.addEventListener("click", onFooterClick);
488
+ return pageFooter;
489
+ }
490
+ function getHeader(headerRightContent, headerLeftContent, onHeaderClick, pageNumber) {
491
+ const pageHeader = document.createElement("div");
492
+ pageHeader.classList.add("rm-page-header");
493
+ pageHeader.classList.add(`rm-page-header-${pageNumber ? pageNumber : 0}`);
494
+ pageHeader.style.overflow = "hidden";
495
+ pageHeader.style.cursor = "pointer";
496
+ pageHeader.style.position = "relative";
497
+ const pageHeaderContent = document.createElement("div");
498
+ pageHeaderContent.classList.add("rm-page-header-content");
499
+ pageHeaderContent.style.width = "100%";
500
+ pageHeaderContent.style.overflow = "hidden";
501
+ const headerLeft = headerLeftContent.replace("{page}", `<span class="rm-page-number-plus"></span>`);
502
+ const headerRight = headerRightContent.replace("{page}", `<span class="rm-page-number-plus"></span>`);
503
+ const pageHeaderLeft = document.createElement("div");
504
+ pageHeaderLeft.classList.add("rm-page-header-left");
505
+ pageHeaderLeft.innerHTML = headerLeft;
506
+ const pageHeaderRight = document.createElement("div");
507
+ pageHeaderRight.classList.add("rm-page-header-right");
508
+ pageHeaderRight.innerHTML = headerRight;
509
+ pageHeaderContent.append(pageHeaderLeft, pageHeaderRight);
510
+ pageHeader.append(pageHeaderContent);
511
+ pageHeader.addEventListener("click", onHeaderClick);
512
+ return pageHeader;
513
+ }
514
+ var getHeight = (pageOptions, _headerHeight, _footerHeight) => {
515
+ const _pageHeaderHeight = pageOptions.contentMarginTop + pageOptions.marginTop + _headerHeight;
516
+ const _pageFooterHeight = pageOptions.contentMarginBottom + pageOptions.marginBottom + _footerHeight;
517
+ const _pageHeight = pageOptions.pageHeight - _pageHeaderHeight - _pageFooterHeight;
518
+ return {
519
+ _pageHeaderHeight,
520
+ _pageFooterHeight,
521
+ _pageHeight
522
+ };
523
+ };
524
+ var headerClickEvent = (pageNumber, onHeaderClick) => {
525
+ return (event) => {
526
+ onHeaderClick === null || onHeaderClick === void 0 ? void 0 : onHeaderClick({
527
+ event,
528
+ pageNumber
529
+ });
530
+ };
531
+ };
532
+ var footerClickEvent = (pageNumber, onFooterClick) => {
533
+ return (event) => {
534
+ onFooterClick === null || onFooterClick === void 0 ? void 0 : onFooterClick({
535
+ event,
536
+ pageNumber
537
+ });
538
+ };
539
+ };
540
+
541
+ // ../../node_modules/.pnpm/tiptap-pagination-plus@3.1.0_@tiptap+core@2.27.2_@tiptap+pm@2.27.2__@tiptap+pm@2.27.2/node_modules/tiptap-pagination-plus/dist/PaginationPlus.js
542
+ var page_count_meta_key = "PAGE_COUNT_META_KEY";
543
+ var key = new PluginKey3("brDecoration");
544
+ function buildDecorations(doc) {
545
+ const decorations = [];
546
+ doc.descendants((node, pos) => {
547
+ if (node.type.name === "hardBreak") {
548
+ const afterPos = pos + 1;
549
+ const widget = Decoration3.widget(afterPos, () => {
550
+ const el = document.createElement("span");
551
+ el.classList.add("rm-br-decoration");
552
+ return el;
553
+ });
554
+ decorations.push(widget);
555
+ }
556
+ });
557
+ return DecorationSet3.create(doc, decorations);
558
+ }
559
+ var defaultPageConfig = {
560
+ enabled: true,
561
+ pageBreakBackground: "#ffffff",
562
+ pageHeight: 800,
563
+ pageWidth: 789,
564
+ marginTop: 20,
565
+ marginBottom: 20,
566
+ marginLeft: 50,
567
+ marginRight: 50,
568
+ pageGap: 50,
569
+ contentMarginTop: 10,
570
+ contentMarginBottom: 10,
571
+ footerRight: "{page}",
572
+ footerLeft: "",
573
+ headerRight: "",
574
+ headerLeft: "",
575
+ customHeader: {},
576
+ customFooter: {}
577
+ };
578
+ var defaultOptions = Object.assign({ pageGapBorderSize: 1, pageGapBorderColor: "#e5e5e5" }, defaultPageConfig);
579
+ var refreshPage = (targetNode, paginationEnabled = true) => {
580
+ var _a;
581
+ const paginationElement = targetNode.querySelector("[data-rm-pagination]");
582
+ if (paginationEnabled) {
583
+ targetNode.removeAttribute("rm-pagination-disabled");
584
+ if (paginationElement) {
585
+ const lastPageBreak = (_a = paginationElement.lastElementChild) === null || _a === void 0 ? void 0 : _a.querySelector(".breaker");
586
+ if (lastPageBreak) {
587
+ const minHeight = lastPageBreak.offsetTop + lastPageBreak.offsetHeight;
588
+ targetNode.style.minHeight = `calc(${minHeight}px + 2px)`;
589
+ }
590
+ }
591
+ } else {
592
+ targetNode.setAttribute("rm-pagination-disabled", "");
593
+ targetNode.style.minHeight = `auto`;
594
+ }
595
+ };
596
+ var getPageConfig = (_storage, _currentOptions) => {
597
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
598
+ const pageConfig = {
599
+ enabled: (_a = _storage.enabled) !== null && _a !== void 0 ? _a : defaultOptions.enabled,
600
+ pageBreakBackground: (_b = _storage.pageBreakBackground) !== null && _b !== void 0 ? _b : defaultOptions.pageBreakBackground,
601
+ pageHeight: (_c = _storage.pageHeight) !== null && _c !== void 0 ? _c : defaultOptions.pageHeight,
602
+ pageWidth: (_d = _storage.pageWidth) !== null && _d !== void 0 ? _d : defaultPageConfig.pageWidth,
603
+ marginTop: (_e = _storage.marginTop) !== null && _e !== void 0 ? _e : defaultPageConfig.marginTop,
604
+ marginBottom: (_f = _storage.marginBottom) !== null && _f !== void 0 ? _f : defaultPageConfig.marginBottom,
605
+ marginLeft: (_g = _storage.marginLeft) !== null && _g !== void 0 ? _g : defaultPageConfig.marginLeft,
606
+ marginRight: (_h = _storage.marginRight) !== null && _h !== void 0 ? _h : defaultPageConfig.marginRight,
607
+ pageGap: (_j = _storage.pageGap) !== null && _j !== void 0 ? _j : defaultPageConfig.pageGap,
608
+ contentMarginTop: (_k = _storage.contentMarginTop) !== null && _k !== void 0 ? _k : defaultPageConfig.contentMarginTop,
609
+ contentMarginBottom: (_l = _storage.contentMarginBottom) !== null && _l !== void 0 ? _l : defaultPageConfig.contentMarginBottom,
610
+ footerRight: (_m = _storage.footerRight) !== null && _m !== void 0 ? _m : defaultPageConfig.footerRight,
611
+ footerLeft: (_o = _storage.footerLeft) !== null && _o !== void 0 ? _o : defaultPageConfig.footerLeft,
612
+ headerRight: (_p = _storage.headerRight) !== null && _p !== void 0 ? _p : defaultPageConfig.headerRight,
613
+ headerLeft: (_q = _storage.headerLeft) !== null && _q !== void 0 ? _q : defaultPageConfig.headerLeft,
614
+ customHeader: (_r = _storage.customHeader) !== null && _r !== void 0 ? _r : defaultPageConfig.customHeader,
615
+ customFooter: (_s = _storage.customFooter) !== null && _s !== void 0 ? _s : defaultPageConfig.customFooter
616
+ };
617
+ return {
618
+ config: pageConfig,
619
+ options: Object.assign(Object.assign({}, _currentOptions), pageConfig)
620
+ };
621
+ };
622
+ var getPageConfigFromOptions = (_currentOptions) => {
623
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
624
+ return {
625
+ enabled: (_a = _currentOptions.enabled) !== null && _a !== void 0 ? _a : defaultOptions.enabled,
626
+ pageBreakBackground: (_b = _currentOptions.pageBreakBackground) !== null && _b !== void 0 ? _b : defaultOptions.pageBreakBackground,
627
+ pageHeight: (_c = _currentOptions.pageHeight) !== null && _c !== void 0 ? _c : defaultOptions.pageHeight,
628
+ pageWidth: (_d = _currentOptions.pageWidth) !== null && _d !== void 0 ? _d : defaultPageConfig.pageWidth,
629
+ marginTop: (_e = _currentOptions.marginTop) !== null && _e !== void 0 ? _e : defaultPageConfig.marginTop,
630
+ marginBottom: (_f = _currentOptions.marginBottom) !== null && _f !== void 0 ? _f : defaultPageConfig.marginBottom,
631
+ marginLeft: (_g = _currentOptions.marginLeft) !== null && _g !== void 0 ? _g : defaultPageConfig.marginLeft,
632
+ marginRight: (_h = _currentOptions.marginRight) !== null && _h !== void 0 ? _h : defaultPageConfig.marginRight,
633
+ pageGap: (_j = _currentOptions.pageGap) !== null && _j !== void 0 ? _j : defaultPageConfig.pageGap,
634
+ contentMarginTop: (_k = _currentOptions.contentMarginTop) !== null && _k !== void 0 ? _k : defaultPageConfig.contentMarginTop,
635
+ contentMarginBottom: (_l = _currentOptions.contentMarginBottom) !== null && _l !== void 0 ? _l : defaultPageConfig.contentMarginBottom,
636
+ footerRight: (_m = _currentOptions.footerRight) !== null && _m !== void 0 ? _m : defaultPageConfig.footerRight,
637
+ footerLeft: (_o = _currentOptions.footerLeft) !== null && _o !== void 0 ? _o : defaultPageConfig.footerLeft,
638
+ headerRight: (_p = _currentOptions.headerRight) !== null && _p !== void 0 ? _p : defaultPageConfig.headerRight,
639
+ headerLeft: (_q = _currentOptions.headerLeft) !== null && _q !== void 0 ? _q : defaultPageConfig.headerLeft,
640
+ customHeader: (_r = _currentOptions.customHeader) !== null && _r !== void 0 ? _r : defaultPageConfig.customHeader,
641
+ customFooter: (_s = _currentOptions.customFooter) !== null && _s !== void 0 ? _s : defaultPageConfig.customFooter
642
+ };
643
+ };
644
+ var paginationKey = new PluginKey3("pagination");
645
+ var PaginationPlus = Extension4.create({
646
+ name: "PaginationPlus",
647
+ addOptions() {
648
+ return defaultOptions;
649
+ },
650
+ addStorage() {
651
+ return Object.assign(Object.assign({}, defaultOptions), { headerHeight: /* @__PURE__ */ new Map(), footerHeight: /* @__PURE__ */ new Map(), appliedConfig: defaultPageConfig });
652
+ },
653
+ onCreate() {
654
+ const { options: _currentOptions } = getPageConfig(this.storage, this.options);
655
+ const pageConfig = getPageConfigFromOptions(this.options);
656
+ const targetNode = this.editor.view.dom;
657
+ targetNode.classList.add("rm-with-pagination");
658
+ targetNode.style.border = `1px solid var(--rm-page-gap-border-color)`;
659
+ targetNode.style.paddingLeft = `var(--rm-margin-left)`;
660
+ targetNode.style.paddingRight = `var(--rm-margin-right)`;
661
+ targetNode.style.width = `var(--rm-page-width)`;
662
+ updateCssVariables(targetNode, Object.assign(Object.assign({}, _currentOptions), pageConfig));
663
+ const style = document.createElement("style");
664
+ style.dataset.rmPaginationStyle = "";
665
+ style.textContent = `
666
+ .rm-pagination-gap{
667
+ border-top: 1px solid;
668
+ border-bottom: 1px solid;
669
+ border-color: var(--rm-page-gap-border-color);
670
+ }
671
+ .rm-with-pagination,
672
+ .rm-with-pagination .rm-first-page-header {
673
+ counter-reset: page-number page-number-plus 1;
674
+ }
675
+ .rm-with-pagination .image-plus-wrapper,
676
+ .rm-with-pagination .table-plus td,
677
+ .rm-with-pagination .table-plus th {
678
+ max-height: var(--rm-max-content-child-height);
679
+ overflow-y: auto;
680
+ }
681
+ .rm-with-pagination .image-plus-wrapper {
682
+ overflow-y: visible;
683
+ }
684
+ .rm-with-pagination .rm-page-break {
685
+ counter-increment: page-number page-number-plus;
686
+ }
687
+
688
+ .rm-with-pagination .rm-page-break:last-child .rm-pagination-gap {
689
+ display: none;
690
+ }
691
+ .rm-with-pagination .rm-page-break:last-child .rm-page-header {
692
+ display: none;
693
+ }
694
+
695
+ .rm-with-pagination table tr td,
696
+ .rm-with-pagination table tr th {
697
+ word-break: break-all;
698
+ }
699
+ .rm-with-pagination table > tr {
700
+ display: grid;
701
+ min-width: 100%;
702
+ }
703
+ .rm-with-pagination table {
704
+ border-collapse: collapse;
705
+ width: 100%;
706
+ display: contents;
707
+ }
708
+ .rm-with-pagination table tbody{
709
+ display: table;
710
+ max-height: 300px;
711
+ overflow-y: auto;
712
+ }
713
+ .rm-with-pagination table tbody > tr{
714
+ display: table-row !important;
715
+ }
716
+ .rm-with-pagination *:has(>br.ProseMirror-trailingBreak:only-child) {
717
+ display: table;
718
+ width: 100%;
719
+ }
720
+ .rm-with-pagination .rm-br-decoration {
721
+ display: table;
722
+ width: 100%;
723
+ }
724
+ .rm-with-pagination .table-row-group {
725
+ max-height: var(--rm-max-content-child-height);
726
+ overflow-y: auto;
727
+ width: 100%;
728
+ }
729
+ .rm-with-pagination .rm-page-footer-left,
730
+ .rm-with-pagination .rm-page-footer-right,
731
+ .rm-with-pagination .rm-page-header-left,
732
+ .rm-with-pagination .rm-page-header-right {
733
+ display: inline-block;
734
+ }
735
+
736
+ .rm-with-pagination .rm-page-header-left,
737
+ .rm-with-pagination .rm-page-footer-left{
738
+ float: left;
739
+ margin-left: var(--rm-margin-left);
740
+ }
741
+ .rm-with-pagination .rm-page-header-right,
742
+ .rm-with-pagination .rm-page-footer-right{
743
+ float: right;
744
+ margin-right: var(--rm-margin-right);
745
+ }
746
+ .rm-with-pagination .rm-first-page-header .rm-page-header-right{
747
+ margin-right: 0px !important;
748
+ }
749
+ .rm-with-pagination .rm-first-page-header .rm-page-header-left{
750
+ margin-left: 0px !important;
751
+ }
752
+ .rm-with-pagination .rm-page-number::before {
753
+ content: counter(page-number);
754
+ }
755
+ .rm-with-pagination .rm-page-number-plus::before {
756
+ content: counter(page-number-plus);
757
+ }
758
+ .rm-with-pagination .rm-page-header,
759
+ .rm-with-pagination .rm-page-footer{
760
+ width: 100%;
761
+ }
762
+ .rm-with-pagination .rm-page-header{
763
+ padding-bottom: var(--rm-content-margin-top) !important;
764
+ padding-top: var(--rm-margin-top) !important;
765
+ display: inline-flex;
766
+ justify-content: space-between;
767
+ max-height: calc(calc(var(--rm-page-height) * 0.45) - var(--rm-margin-top) - var(--rm-content-margin-top));
768
+ overflow-y: hidden;
769
+ }
770
+ .rm-with-pagination .rm-page-footer{
771
+ padding-top: var(--rm-content-margin-bottom) !important;
772
+ padding-bottom: var(--rm-margin-bottom) !important;
773
+ display: inline-flex;
774
+ justify-content: space-between;
775
+ max-height: calc(calc(var(--rm-page-height) * 0.45) - var(--rm-content-margin-bottom) - var(--rm-margin-bottom));
776
+ overflow-y: hidden;
777
+ }
778
+ .rm-with-pagination[rm-pagination-disabled] {
779
+ padding-top: var(--rm-margin-top) !important;
780
+ padding-bottom: var(--rm-margin-bottom) !important;
781
+ }
782
+ `;
783
+ document.head.appendChild(style);
784
+ refreshPage(targetNode, _currentOptions.enabled);
785
+ },
786
+ addProseMirrorPlugins() {
787
+ const editor = this.editor;
788
+ const storage = this.storage;
789
+ return [
790
+ new Plugin3({
791
+ key: paginationKey,
792
+ state: {
793
+ init: (_, state) => {
794
+ const _currentOptions = getPageConfigFromOptions(this.options);
795
+ const pageConfig = getPageConfigFromOptions(this.options);
796
+ const widgetList = createDecoration(Object.assign(Object.assign({}, this.options), _currentOptions), /* @__PURE__ */ new Map(), /* @__PURE__ */ new Map());
797
+ storage.pageBreakBackground = _currentOptions.pageBreakBackground;
798
+ storage.pageHeight = _currentOptions.pageHeight;
799
+ storage.pageWidth = _currentOptions.pageWidth;
800
+ storage.marginTop = _currentOptions.marginTop;
801
+ storage.marginBottom = _currentOptions.marginBottom;
802
+ storage.marginLeft = _currentOptions.marginLeft;
803
+ storage.marginRight = _currentOptions.marginRight;
804
+ storage.pageGap = _currentOptions.pageGap;
805
+ storage.contentMarginTop = _currentOptions.contentMarginTop;
806
+ storage.contentMarginBottom = _currentOptions.contentMarginBottom;
807
+ storage.footerRight = _currentOptions.footerRight;
808
+ storage.footerLeft = _currentOptions.footerLeft;
809
+ storage.headerRight = _currentOptions.headerRight;
810
+ storage.headerLeft = _currentOptions.headerLeft;
811
+ storage.customHeader = _currentOptions.customHeader;
812
+ storage.customFooter = _currentOptions.customFooter;
813
+ storage.headerHeight = /* @__PURE__ */ new Map();
814
+ storage.footerHeight = /* @__PURE__ */ new Map();
815
+ storage.appliedConfig = pageConfig;
816
+ return {
817
+ decorations: DecorationSet3.create(state.doc, widgetList)
818
+ };
819
+ },
820
+ apply: (tr, oldDeco, oldState, newState) => {
821
+ const { options: _currentOptions, config: pageConfig } = getPageConfig(storage, this.options);
822
+ if (storage.enabled === storage.appliedConfig.enabled && storage.enabled === false && storage.appliedConfig.enabled === false) {
823
+ return oldDeco;
824
+ }
825
+ const pageCount = getNewPageCount(editor.view, Object.assign(Object.assign({}, _currentOptions), pageConfig));
826
+ const currentPageCount = getExistingPageCount(editor.view);
827
+ const getNewDecoration = () => {
828
+ const { options: _currentOptions2, config: pageConfig2 } = getPageConfig(storage, this.options);
829
+ updateCssVariables(editor.view.dom, _currentOptions2);
830
+ let headerHeight = "headerHeight" in this.storage ? this.storage.headerHeight : /* @__PURE__ */ new Map();
831
+ let footerHeight = "footerHeight" in this.storage ? this.storage.footerHeight : /* @__PURE__ */ new Map();
832
+ const widgetList = createDecoration(Object.assign(Object.assign({}, _currentOptions2), pageConfig2), headerHeight, footerHeight);
833
+ storage.appliedConfig = pageConfig2;
834
+ storage.headerHeight = headerHeight;
835
+ storage.footerHeight = footerHeight;
836
+ return {
837
+ decorations: DecorationSet3.create(newState.doc, [...widgetList]),
838
+ footerHeight
839
+ };
840
+ };
841
+ if (
842
+ // If pagination is enabled only then check for other changes
843
+ (pageCount > 1 ? pageCount : 1) !== currentPageCount || storage.enabled !== storage.appliedConfig.enabled || storage.pageBreakBackground !== storage.appliedConfig.pageBreakBackground || storage.pageHeight !== storage.appliedConfig.pageHeight || storage.pageWidth !== storage.appliedConfig.pageWidth || storage.marginTop !== storage.appliedConfig.marginTop || storage.marginBottom !== storage.appliedConfig.marginBottom || storage.marginLeft !== storage.appliedConfig.marginLeft || storage.marginRight !== storage.appliedConfig.marginRight || storage.pageGap !== storage.appliedConfig.pageGap || storage.contentMarginTop !== storage.appliedConfig.contentMarginTop || storage.contentMarginBottom !== storage.appliedConfig.contentMarginBottom || storage.headerLeft !== storage.appliedConfig.headerLeft || storage.headerRight !== storage.appliedConfig.headerRight || storage.footerLeft !== storage.appliedConfig.footerLeft || storage.footerRight !== storage.appliedConfig.footerRight || !deepEqualIterative(storage.appliedConfig.customHeader, storage.customHeader) || !deepEqualIterative(storage.appliedConfig.customFooter, storage.customFooter)
844
+ ) {
845
+ return getNewDecoration();
846
+ }
847
+ return oldDeco;
848
+ }
849
+ },
850
+ props: {
851
+ decorations(state) {
852
+ var _a;
853
+ return (_a = this.getState(state)) === null || _a === void 0 ? void 0 : _a.decorations;
854
+ }
855
+ },
856
+ view: (editorView) => {
857
+ return {
858
+ update: (view) => {
859
+ const { options: _currentOptions, config: pageConfig } = getPageConfig(storage, this.options);
860
+ if (!pageConfig.enabled && !view.dom.hasAttribute("rm-pagination-disabled")) {
861
+ refreshPage(view.dom, false);
862
+ return;
863
+ }
864
+ const pageCount = getNewPageCount(view, Object.assign(Object.assign({}, _currentOptions), pageConfig));
865
+ const currentPageCount = getExistingPageCount(view);
866
+ const triggerUpdate = (_footerHeight) => {
867
+ requestAnimationFrame(() => {
868
+ const tr = view.state.tr.setMeta(page_count_meta_key, { footerHeight: _footerHeight });
869
+ view.dispatch(tr);
870
+ });
871
+ };
872
+ if (currentPageCount !== pageCount) {
873
+ triggerUpdate();
874
+ return;
875
+ }
876
+ const headerHeight = getHeaderHeight(view.dom, getCustomPages(_currentOptions.customHeader, {}), "content");
877
+ const footerHeight = getFooterHeight(view.dom, getCustomPages({}, _currentOptions.customFooter), "content");
878
+ const footerHeightForCurrentPages = /* @__PURE__ */ new Map();
879
+ for (let i = 0; i <= pageCount; i++) {
880
+ if (footerHeight.has(i)) {
881
+ footerHeightForCurrentPages.set(i, footerHeight.get(i) || 0);
882
+ }
883
+ }
884
+ const headerHeightForCurrentPages = /* @__PURE__ */ new Map();
885
+ for (let i = 0; i <= pageCount; i++) {
886
+ if (headerHeight.has(i)) {
887
+ headerHeightForCurrentPages.set(i, headerHeight.get(i) || 0);
888
+ }
889
+ }
890
+ const pagesSetToCheck = /* @__PURE__ */ new Set([1, ...footerHeightForCurrentPages.keys(), ...headerHeightForCurrentPages.keys()]);
891
+ let missingPageNumber = void 0;
892
+ for (let i = 1; i <= pageCount; i++) {
893
+ if (!pagesSetToCheck.has(i)) {
894
+ missingPageNumber = i;
895
+ break;
896
+ }
897
+ }
898
+ if (missingPageNumber) {
899
+ pagesSetToCheck.add(missingPageNumber);
900
+ }
901
+ pagesSetToCheck.delete(0);
902
+ let pageContentHeightVariable = {};
903
+ let maxContentHeight = void 0;
904
+ for (const page of pagesSetToCheck) {
905
+ const headerHeight2 = headerHeightForCurrentPages.has(page) ? headerHeightForCurrentPages.get(page) || 0 : headerHeightForCurrentPages.get(0) || 0;
906
+ const footerHeight2 = footerHeightForCurrentPages.has(page) ? footerHeightForCurrentPages.get(page) || 0 : footerHeightForCurrentPages.get(0) || 0;
907
+ const { _pageHeaderHeight, _pageHeight } = getHeight(_currentOptions, headerHeight2, footerHeight2);
908
+ const contentHeight = page === 1 ? _pageHeight + _pageHeaderHeight : _pageHeight;
909
+ if (page === 1) {
910
+ pageContentHeightVariable[`rm-page-content-first`] = `${contentHeight}px`;
911
+ }
912
+ if (page === missingPageNumber) {
913
+ pageContentHeightVariable[`rm-page-content-general`] = `${contentHeight}px`;
914
+ } else {
915
+ pageContentHeightVariable[`rm-page-content-${page}`] = `${contentHeight}px`;
916
+ }
917
+ if (maxContentHeight === void 0 || contentHeight < maxContentHeight) {
918
+ maxContentHeight = contentHeight;
919
+ }
920
+ }
921
+ if (maxContentHeight) {
922
+ view.dom.style.setProperty(`--rm-max-content-child-height`, `${maxContentHeight - 10}px`);
923
+ }
924
+ Object.entries(pageContentHeightVariable).forEach(([key2, value]) => {
925
+ view.dom.style.setProperty(`--${key2}`, value);
926
+ });
927
+ refreshPage(view.dom, _currentOptions.enabled);
928
+ return;
929
+ }
930
+ };
931
+ }
932
+ }),
933
+ new Plugin3({
934
+ key,
935
+ state: {
936
+ init(_, state) {
937
+ return buildDecorations(state.doc);
938
+ },
939
+ apply(tr, old) {
940
+ if (tr.docChanged || tr.steps.some((step) => step instanceof ReplaceStep) || tr.steps.some((step) => step instanceof ReplaceAroundStep) || tr.steps.some((step) => step instanceof AddMarkStep) || tr.steps.some((step) => step instanceof RemoveMarkStep) || tr.steps.some((step) => step instanceof RemoveNodeMarkStep) || tr.steps.some((step) => step instanceof AttrStep)) {
941
+ return buildDecorations(tr.doc);
942
+ }
943
+ return old;
944
+ }
945
+ },
946
+ props: {
947
+ decorations(state) {
948
+ var _a;
949
+ return (_a = key.getState(state)) !== null && _a !== void 0 ? _a : DecorationSet3.empty;
950
+ }
951
+ }
952
+ })
953
+ ];
954
+ },
955
+ addCommands() {
956
+ return {
957
+ updatePageBreakBackground: (color) => () => {
958
+ this.storage.pageBreakBackground = color;
959
+ return true;
960
+ },
961
+ updatePageSize: (size) => () => {
962
+ this.storage.pageHeight = size.pageHeight;
963
+ this.storage.pageWidth = size.pageWidth;
964
+ this.storage.marginTop = size.marginTop;
965
+ this.storage.marginBottom = size.marginBottom;
966
+ this.storage.marginLeft = size.marginLeft;
967
+ this.storage.marginRight = size.marginRight;
968
+ return true;
969
+ },
970
+ updatePageWidth: (width) => () => {
971
+ this.storage.pageWidth = width;
972
+ return true;
973
+ },
974
+ updatePageHeight: (height) => () => {
975
+ this.storage.pageHeight = height;
976
+ return true;
977
+ },
978
+ updatePageGap: (gap) => () => {
979
+ this.storage.pageGap = gap;
980
+ return true;
981
+ },
982
+ updateMargins: (margins) => () => {
983
+ this.storage.marginTop = margins.top;
984
+ this.storage.marginBottom = margins.bottom;
985
+ this.storage.marginLeft = margins.left;
986
+ this.storage.marginRight = margins.right;
987
+ return true;
988
+ },
989
+ updateContentMargins: (margins) => () => {
990
+ this.storage.contentMarginTop = margins.top;
991
+ this.storage.contentMarginBottom = margins.bottom;
992
+ return true;
993
+ },
994
+ updateHeaderContent: (left, right, pageNumber) => () => {
995
+ if (pageNumber) {
996
+ this.storage.customHeader = Object.assign(Object.assign({}, this.storage.customHeader), { [pageNumber]: { headerLeft: left, headerRight: right } });
997
+ } else {
998
+ this.storage.headerLeft = left;
999
+ this.storage.headerRight = right;
1000
+ }
1001
+ return true;
1002
+ },
1003
+ updateFooterContent: (left, right, pageNumber) => () => {
1004
+ if (pageNumber) {
1005
+ this.storage.customFooter = Object.assign(Object.assign({}, this.storage.customFooter), { [pageNumber]: { footerLeft: left, footerRight: right } });
1006
+ } else {
1007
+ this.storage.footerLeft = left;
1008
+ this.storage.footerRight = right;
1009
+ }
1010
+ return true;
1011
+ },
1012
+ togglePagination: () => () => {
1013
+ this.storage.enabled = !this.storage.enabled;
1014
+ return true;
1015
+ },
1016
+ enablePagination: () => () => {
1017
+ this.storage.enabled = true;
1018
+ return true;
1019
+ },
1020
+ disablePagination: () => () => {
1021
+ this.storage.enabled = false;
1022
+ return true;
1023
+ }
1024
+ };
1025
+ }
1026
+ });
1027
+ var getExistingPageCount = (view) => {
1028
+ const editorDom = view.dom;
1029
+ const paginationElement = editorDom.querySelector("[data-rm-pagination]");
1030
+ if (paginationElement) {
1031
+ return paginationElement.children.length;
1032
+ }
1033
+ return 0;
1034
+ };
1035
+ var calculatePageCount = (view, pageOptions, headerHeight = 0, footerHeight = 0) => {
1036
+ var _a;
1037
+ const editorDom = view.dom;
1038
+ const _pageHeaderHeight = pageOptions.contentMarginTop + pageOptions.marginTop + headerHeight;
1039
+ const _pageFooterHeight = pageOptions.contentMarginBottom + pageOptions.marginBottom + footerHeight;
1040
+ const pageContentAreaHeight = pageOptions.pageHeight - _pageHeaderHeight - _pageFooterHeight;
1041
+ const paginationElement = editorDom.querySelector("[data-rm-pagination]");
1042
+ const currentPageCount = getExistingPageCount(view);
1043
+ if (paginationElement) {
1044
+ const lastElementOfEditor = editorDom.lastElementChild;
1045
+ const lastPageBreak = (_a = paginationElement.lastElementChild) === null || _a === void 0 ? void 0 : _a.querySelector(".breaker");
1046
+ if (lastElementOfEditor && lastPageBreak) {
1047
+ const lastElementRect = lastElementOfEditor.getBoundingClientRect();
1048
+ const lastPageBreakRect = lastPageBreak.getBoundingClientRect();
1049
+ const lastPageGap = lastElementRect.bottom - lastPageBreakRect.bottom;
1050
+ if (lastPageGap > 0) {
1051
+ const addPage = Math.ceil(lastPageGap / pageContentAreaHeight);
1052
+ return currentPageCount + addPage;
1053
+ } else {
1054
+ const allBreaksAfterLastElement = Array.from(paginationElement.querySelectorAll(".breaker"));
1055
+ const allBreaksAfterLastElementRect = allBreaksAfterLastElement.filter((element) => element.getBoundingClientRect().top > lastElementRect.bottom);
1056
+ const removePage = allBreaksAfterLastElementRect.length;
1057
+ if (removePage > 1) {
1058
+ return currentPageCount - removePage;
1059
+ } else {
1060
+ return currentPageCount;
1061
+ }
1062
+ }
1063
+ }
1064
+ return 1;
1065
+ } else {
1066
+ const editorHeight = editorDom.scrollHeight;
1067
+ let pageCount = Math.ceil(editorHeight / pageContentAreaHeight);
1068
+ pageCount = pageCount <= 0 ? 1 : pageCount;
1069
+ return pageCount;
1070
+ }
1071
+ };
1072
+ var getNewPageCount = (view, pageOptions) => {
1073
+ if (pageOptions.enabled) {
1074
+ const pageCount = calculatePageCount(view, pageOptions);
1075
+ return pageCount <= 1 ? 1 : pageCount;
1076
+ } else {
1077
+ return 0;
1078
+ }
1079
+ };
1080
+ function createDecoration(pageOptions, headerHeightMap, footerHeightMap) {
1081
+ if (!pageOptions.enabled) {
1082
+ return [];
1083
+ }
1084
+ const commonHeaderOptions = { headerLeft: pageOptions.headerLeft, headerRight: pageOptions.headerRight };
1085
+ const commonFooterOptions = { footerLeft: pageOptions.footerLeft, footerRight: pageOptions.footerRight };
1086
+ const pageWidget = Decoration3.widget(0, (view) => {
1087
+ const _pageGap = pageOptions.pageGap;
1088
+ const _pageBreakBackground = pageOptions.pageBreakBackground;
1089
+ const el = document.createElement("div");
1090
+ el.dataset.rmPagination = "true";
1091
+ const pageBreakDefinition = (firstPage, pageHeader, pageFooter, headerHeight, footerHeight, pageNumber) => {
1092
+ const { _pageHeaderHeight, _pageHeight } = getHeight(pageOptions, headerHeight, footerHeight);
1093
+ const pageContainer = document.createElement("div");
1094
+ pageContainer.classList.add("rm-page-break");
1095
+ const page = document.createElement("div");
1096
+ page.classList.add("page");
1097
+ page.style.position = "relative";
1098
+ page.style.float = "left";
1099
+ page.style.clear = "both";
1100
+ const marginTop = firstPage ? `calc(${_pageHeaderHeight}px + ${_pageHeight}px)` : _pageHeight + "px";
1101
+ if (pageNumber) {
1102
+ page.style.marginTop = `var(--rm-page-content-${pageNumber}, ${marginTop})`;
1103
+ } else {
1104
+ page.style.marginTop = firstPage ? `var(--rm-page-content-first, ${marginTop})` : `var(--rm-page-content-general, ${marginTop})`;
1105
+ }
1106
+ const pageBreak = document.createElement("div");
1107
+ pageBreak.classList.add("breaker");
1108
+ pageBreak.style.width = `calc(100% + var(--rm-margin-left) + var(--rm-margin-right))`;
1109
+ pageBreak.style.marginLeft = `calc(-1 * var(--rm-margin-left))`;
1110
+ pageBreak.style.marginRight = `calc(-1 * var(--rm-margin-right))`;
1111
+ pageBreak.style.position = "relative";
1112
+ pageBreak.style.float = "left";
1113
+ pageBreak.style.clear = "both";
1114
+ pageBreak.style.left = `0px`;
1115
+ pageBreak.style.right = `0px`;
1116
+ pageBreak.style.zIndex = "2";
1117
+ const pageSpace = document.createElement("div");
1118
+ pageSpace.classList.add("rm-pagination-gap");
1119
+ pageSpace.style.height = _pageGap + "px";
1120
+ pageSpace.style.borderLeft = "1px solid";
1121
+ pageSpace.style.borderRight = "1px solid";
1122
+ pageSpace.style.position = "relative";
1123
+ pageSpace.style.setProperty("width", "calc(100% + 2px)", "important");
1124
+ pageSpace.style.left = "-1px";
1125
+ pageSpace.style.backgroundColor = _pageBreakBackground;
1126
+ pageSpace.style.borderLeftColor = _pageBreakBackground;
1127
+ pageSpace.style.borderRightColor = _pageBreakBackground;
1128
+ pageBreak.append(pageFooter, pageSpace, pageHeader);
1129
+ pageContainer.append(page, pageBreak);
1130
+ return pageContainer;
1131
+ };
1132
+ const _headerHeight = headerHeightMap.get(0) || 0;
1133
+ const _footerHeight = footerHeightMap.get(0) || 0;
1134
+ const fragment = document.createDocumentFragment();
1135
+ const pageCount = getNewPageCount(view, pageOptions);
1136
+ for (let i = 0; i < pageCount; i++) {
1137
+ const pageNumber = i + 1;
1138
+ const headerPageNumber = i + 2;
1139
+ if (headerPageNumber in pageOptions.customHeader || pageNumber in pageOptions.customFooter || pageNumber in pageOptions.customHeader) {
1140
+ let _headerOptions = commonHeaderOptions;
1141
+ let _footerOptions = commonFooterOptions;
1142
+ let _pageHeaderHeight = _headerHeight;
1143
+ let _pageFooterHeight = _footerHeight;
1144
+ if (headerPageNumber in pageOptions.customHeader) {
1145
+ _headerOptions = pageOptions.customHeader[headerPageNumber] || commonHeaderOptions;
1146
+ _pageHeaderHeight = headerHeightMap.get(headerPageNumber) || 0;
1147
+ }
1148
+ if (pageNumber in pageOptions.customFooter) {
1149
+ _footerOptions = pageOptions.customFooter[pageNumber] || commonFooterOptions;
1150
+ _pageFooterHeight = footerHeightMap.get(pageNumber) || 0;
1151
+ }
1152
+ let _pageHeader = getHeader(_headerOptions.headerRight, _headerOptions.headerLeft, headerClickEvent(headerPageNumber, pageOptions.onHeaderClick), headerPageNumber);
1153
+ let _pageFooter = getFooter(_footerOptions.footerRight, _footerOptions.footerLeft, footerClickEvent(pageNumber, pageOptions.onFooterClick), pageNumber);
1154
+ let pageBreak = pageBreakDefinition(i === 0, _pageHeader, _pageFooter, _pageHeaderHeight, _pageFooterHeight, pageNumber);
1155
+ fragment.appendChild(pageBreak);
1156
+ } else {
1157
+ const __pageHeader = getHeader(commonHeaderOptions.headerRight, commonHeaderOptions.headerLeft, headerClickEvent(headerPageNumber, pageOptions.onHeaderClick));
1158
+ const __pageFooter = getFooter(commonFooterOptions.footerRight, commonFooterOptions.footerLeft, footerClickEvent(pageNumber, pageOptions.onFooterClick));
1159
+ fragment.appendChild(pageBreakDefinition(i === 0, __pageHeader, __pageFooter, _headerHeight, _footerHeight));
1160
+ }
1161
+ }
1162
+ el.append(fragment);
1163
+ el.id = "pages";
1164
+ el.classList.add("rm-pages-wrapper");
1165
+ return el;
1166
+ }, { side: -1 });
1167
+ const firstHeaderWidget = Decoration3.widget(0, () => {
1168
+ const pageNumber = 1;
1169
+ let _headerOptions = commonHeaderOptions;
1170
+ if (pageNumber in pageOptions.customHeader) {
1171
+ _headerOptions = pageOptions.customHeader[pageNumber];
1172
+ }
1173
+ const el = getHeader(_headerOptions.headerRight, _headerOptions.headerLeft, headerClickEvent(pageNumber, pageOptions.onHeaderClick));
1174
+ el.classList.add("rm-first-page-header");
1175
+ return el;
1176
+ }, { side: -1 });
1177
+ return [pageWidget, firstHeaderWidget];
1178
+ }
1179
+
1180
+ // ../../node_modules/.pnpm/tiptap-pagination-plus@3.1.0_@tiptap+core@2.27.2_@tiptap+pm@2.27.2__@tiptap+pm@2.27.2/node_modules/tiptap-pagination-plus/dist/constants.js
1181
+ var A4_PAGE_SIZE = getPageSize(1123, 794, 95, 95, 76, 76);
1182
+ var A3_PAGE_SIZE = getPageSize(1591, 1123, 95, 95, 76, 76);
1183
+ var A5_PAGE_SIZE = getPageSize(794, 419, 76, 76, 57, 57);
1184
+ var LETTER_PAGE_SIZE = getPageSize(1060, 818, 96, 96, 96, 96);
1185
+ var LEGAL_PAGE_SIZE = getPageSize(1404, 818, 96, 96, 96, 96);
1186
+ var TABLOID_PAGE_SIZE = getPageSize(1635, 1060, 96, 96, 96, 96);
1187
+ var PAGE_SIZES = {
1188
+ A4: A4_PAGE_SIZE,
1189
+ A3: A3_PAGE_SIZE,
1190
+ A5: A5_PAGE_SIZE,
1191
+ LETTER: LETTER_PAGE_SIZE,
1192
+ LEGAL: LEGAL_PAGE_SIZE,
1193
+ TABLOID: TABLOID_PAGE_SIZE
1194
+ };
1195
+
192
1196
  // src/Editor.ts
193
- import { PaginationPlus } from "tiptap-pagination-plus";
1197
+ function sanitizePastedHTML(html) {
1198
+ let cleaned = html.replace(/<meta[^>]*>/gi, "");
1199
+ cleaned = cleaned.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "");
1200
+ cleaned = cleaned.replace(/<!--[\s\S]*?-->/g, "");
1201
+ cleaned = cleaned.replace(/<link[^>]*>/gi, "");
1202
+ cleaned = cleaned.replace(/<base[^>]*>/gi, "");
1203
+ cleaned = cleaned.replace(/<title[^>]*>[\s\S]*?<\/title>/gi, "");
1204
+ {
1205
+ for (let pass = 0; pass < 10; pass++) {
1206
+ const before = cleaned;
1207
+ cleaned = cleaned.replace(
1208
+ /<span\s([^>]*style\s*=\s*["'][^"']*(?:background-color|background)[^"']*["'][^>]*)>([^<]*(?:<(?!\/?span)[^>]*>[^<]*)*)<\/span>/gi,
1209
+ (_full, attrs, content) => {
1210
+ if (!/background(?:-color)?\s*:/.test(attrs)) return _full;
1211
+ const colorMatch = attrs.match(/(?<!background-)color\s*:\s*([^;"]+)/i);
1212
+ const colorVal = colorMatch ? colorMatch[1].trim() : null;
1213
+ const markAttrs = colorVal ? attrs.replace(/(?<!background-)color\s*:\s*[^;"]+;?\s*/gi, "").trim() : attrs;
1214
+ if (colorVal) {
1215
+ return `<mark ${markAttrs}><span style="color: ${colorVal};">${content}</span></mark>`;
1216
+ }
1217
+ return `<mark ${markAttrs}>${content}</mark>`;
1218
+ }
1219
+ );
1220
+ if (cleaned === before) break;
1221
+ }
1222
+ }
1223
+ cleaned = cleaned.replace(
1224
+ /<b\s[^>]*style\s*=\s*["'][^"']*font-weight:\s*normal[^"']*["'][^>]*>/gi,
1225
+ ""
1226
+ );
1227
+ cleaned = cleaned.replace(/<\/b>/gi, "");
1228
+ cleaned = cleaned.replace(/\sid\s*=\s*["']docs-internal[^"']*["']/gi, "");
1229
+ return cleaned;
1230
+ }
194
1231
  function migrateContent(content) {
195
1232
  if (!content) return content;
196
1233
  if (typeof content === "string") {
@@ -290,20 +1327,338 @@ function createTiptapEditor(options, plugins, collaborationSetup) {
290
1327
  const pluginExtensions = collectExtensions(plugins);
291
1328
  const blockAttrs = options.getPageMap ? BlockAttributesExtension.configure({ pageMap: options.getPageMap }) : BlockAttributesExtension;
292
1329
  const paginationExt = options.paginationOptions ? PaginationPlus.configure(options.paginationOptions) : PaginationPlus;
1330
+ const ManualColumnResize = Extension5.create({
1331
+ name: "manualColumnResize",
1332
+ addProseMirrorPlugins() {
1333
+ const key2 = new PluginKey4("manualColumnResize");
1334
+ return [new Plugin4({
1335
+ key: key2,
1336
+ view(view) {
1337
+ function pauseObserver() {
1338
+ try {
1339
+ view.domObserver?.stop?.();
1340
+ } catch (_) {
1341
+ }
1342
+ }
1343
+ function resumeObserver() {
1344
+ try {
1345
+ view.domObserver?.start?.();
1346
+ } catch (_) {
1347
+ }
1348
+ }
1349
+ function getMaxContainerWidth(tableEl) {
1350
+ let curr = tableEl.parentElement;
1351
+ while (curr) {
1352
+ const style = window.getComputedStyle(curr);
1353
+ const paddingLeft = parseFloat(style.paddingLeft) || 0;
1354
+ const paddingRight = parseFloat(style.paddingRight) || 0;
1355
+ const availWidth = curr.clientWidth - paddingLeft - paddingRight;
1356
+ if (availWidth > 100 && (curr.classList.contains("docs-editor__paper") || curr.classList.contains("docs-editor-page") || curr.classList.contains("ProseMirror") || curr.classList.contains("rm-with-pagination"))) {
1357
+ return availWidth;
1358
+ }
1359
+ curr = curr.parentElement;
1360
+ }
1361
+ return tableEl.parentElement?.clientWidth || 614;
1362
+ }
1363
+ const onMouseDown = function(event) {
1364
+ if (event.button !== 0) return;
1365
+ const td = event.target.closest("td, th");
1366
+ if (!td) return;
1367
+ const r = td.getBoundingClientRect();
1368
+ const parent = td.parentElement;
1369
+ if (!parent) return;
1370
+ const colIdx = Array.from(parent.children).indexOf(td);
1371
+ if (colIdx === -1) return;
1372
+ const table = td.closest("table");
1373
+ if (!table) return;
1374
+ const distRight = Math.abs(event.clientX - r.right);
1375
+ const distLeft = Math.abs(event.clientX - r.left);
1376
+ let targetColIdx = -1;
1377
+ if (distRight <= 16) {
1378
+ targetColIdx = colIdx;
1379
+ } else if (distLeft <= 16 && colIdx > 0) {
1380
+ targetColIdx = colIdx - 1;
1381
+ } else {
1382
+ return;
1383
+ }
1384
+ const colsList = table.querySelectorAll("colgroup col");
1385
+ const totalCols = colsList.length || table.querySelector("tr")?.children.length || 0;
1386
+ const allColWidths = [];
1387
+ for (let c = 0; c < totalCols; c++) {
1388
+ const colEl = colsList[c];
1389
+ const w = colEl ? parseFloat(colEl.style.width) : 0;
1390
+ allColWidths[c] = w || initialWidth(table, c);
1391
+ }
1392
+ const isLastCol = targetColIdx === totalCols - 1;
1393
+ const startX = event.clientX;
1394
+ const startW = allColWidths[targetColIdx] || initialWidth(table, targetColIdx);
1395
+ const maxContainerW = getMaxContainerWidth(table);
1396
+ let otherColsW = 0;
1397
+ allColWidths.forEach((w, idx) => {
1398
+ if (idx !== targetColIdx) {
1399
+ otherColsW += w;
1400
+ }
1401
+ });
1402
+ const maxNw = Math.max(20, maxContainerW - otherColsW);
1403
+ function updateDOMWidths(targetIdx, targetW) {
1404
+ let totalWidth = 0;
1405
+ allColWidths.forEach((_, idx) => {
1406
+ const w = idx === targetIdx ? targetW : allColWidths[idx];
1407
+ const col = table.querySelector(`colgroup col:nth-child(${idx + 1})`);
1408
+ if (col) col.style.setProperty("width", w + "px", "important");
1409
+ table.querySelectorAll("tr").forEach(function(row) {
1410
+ const cell = row.children[idx];
1411
+ if (cell) {
1412
+ cell.style.setProperty("width", w + "px", "important");
1413
+ cell.setAttribute("width", String(w));
1414
+ }
1415
+ });
1416
+ totalWidth += w;
1417
+ });
1418
+ if (totalWidth > 0) {
1419
+ table.style.setProperty("width", Math.min(totalWidth, maxContainerW) + "px", "important");
1420
+ }
1421
+ }
1422
+ event.stopPropagation();
1423
+ let lastNw = startW;
1424
+ let moveCount = 0;
1425
+ const onMove = function(e) {
1426
+ moveCount++;
1427
+ if (!e.buttons) {
1428
+ onUp(e);
1429
+ return;
1430
+ }
1431
+ const diff = e.clientX - startX;
1432
+ const nw = Math.min(maxNw, Math.max(20, startW + diff));
1433
+ lastNw = nw;
1434
+ let borderPos = table.getBoundingClientRect().left;
1435
+ for (let i = 0; i <= targetColIdx; i++) {
1436
+ borderPos += i === targetColIdx ? nw : allColWidths[i];
1437
+ }
1438
+ showLine(table, borderPos);
1439
+ pauseObserver();
1440
+ updateDOMWidths(targetColIdx, nw);
1441
+ resumeObserver();
1442
+ };
1443
+ const onUp = function(upEvent) {
1444
+ document.removeEventListener("mousemove", onMove);
1445
+ document.removeEventListener("mouseup", onUp, true);
1446
+ upEvent.stopPropagation();
1447
+ hideLine();
1448
+ if (lastNw === startW) return;
1449
+ allColWidths[targetColIdx] = lastNw;
1450
+ console.log("[Resize] onUp:", { lastNw, startW, isLastCol, targetColIdx, allColWidths });
1451
+ try {
1452
+ const { state } = view;
1453
+ const { doc } = state;
1454
+ let tablePos = -1;
1455
+ doc.descendants((node, pos) => {
1456
+ if (tablePos >= 0) return false;
1457
+ if (node.type.name === "table") {
1458
+ try {
1459
+ const dom = view.nodeDOM(pos);
1460
+ if (dom === table || dom instanceof HTMLElement && dom.contains(table) || table.contains(dom)) {
1461
+ tablePos = pos;
1462
+ return false;
1463
+ }
1464
+ } catch (_) {
1465
+ }
1466
+ }
1467
+ return true;
1468
+ });
1469
+ if (tablePos >= 0) {
1470
+ const tableNode = doc.nodeAt(tablePos);
1471
+ if (tableNode) {
1472
+ const tr = state.tr;
1473
+ let cellsUpdated = 0;
1474
+ tableNode.forEach((row, rowOffset) => {
1475
+ let cellColIdx = 0;
1476
+ row.forEach((cell, cellOffset) => {
1477
+ const colspan = cell.attrs.colspan || 1;
1478
+ const cellPos = tablePos + 1 + rowOffset + 1 + cellOffset;
1479
+ const cw = new Array(colspan);
1480
+ for (let k = 0; k < colspan; k++) {
1481
+ cw[k] = allColWidths[cellColIdx + k] || 100;
1482
+ }
1483
+ tr.setNodeMarkup(cellPos, null, { ...cell.attrs, colwidth: cw });
1484
+ cellsUpdated++;
1485
+ cellColIdx += colspan;
1486
+ });
1487
+ });
1488
+ view.dispatch(tr);
1489
+ pauseObserver();
1490
+ updateDOMWidths(targetColIdx, lastNw);
1491
+ resumeObserver();
1492
+ }
1493
+ } else {
1494
+ console.warn("[Resize] could not find table position in doc");
1495
+ }
1496
+ } catch (err) {
1497
+ console.warn("[Resize] transaction failed, falling back to DOM:", err);
1498
+ pauseObserver();
1499
+ updateDOMWidths(targetColIdx, lastNw);
1500
+ resumeObserver();
1501
+ }
1502
+ };
1503
+ document.addEventListener("mousemove", onMove);
1504
+ document.addEventListener("mouseup", onUp, true);
1505
+ };
1506
+ function initialWidth(table, colIdx) {
1507
+ const firstRow = table.querySelector("tr");
1508
+ if (!firstRow) return 100;
1509
+ const cell = firstRow.children[colIdx];
1510
+ if (!cell) return 100;
1511
+ return Math.round(cell.getBoundingClientRect().width) || cell.offsetWidth || 100;
1512
+ }
1513
+ let lineEl = null;
1514
+ let isDragging = false;
1515
+ function getOrCreateLine() {
1516
+ if (!lineEl) {
1517
+ lineEl = document.createElement("div");
1518
+ lineEl.className = "docflow-active-border-line";
1519
+ Object.assign(lineEl.style, {
1520
+ position: "fixed",
1521
+ width: "3px",
1522
+ background: "#06b6d4",
1523
+ boxShadow: "0 0 8px rgba(6, 182, 212, 0.9)",
1524
+ pointerEvents: "none",
1525
+ zIndex: "999999",
1526
+ display: "none",
1527
+ borderRadius: "1.5px"
1528
+ });
1529
+ const dotTop = document.createElement("div");
1530
+ Object.assign(dotTop.style, {
1531
+ position: "absolute",
1532
+ top: "-4px",
1533
+ left: "-3.5px",
1534
+ width: "10px",
1535
+ height: "10px",
1536
+ borderRadius: "50%",
1537
+ background: "#ffffff",
1538
+ border: "2px solid #06b6d4"
1539
+ });
1540
+ const dotBottom = document.createElement("div");
1541
+ Object.assign(dotBottom.style, {
1542
+ position: "absolute",
1543
+ bottom: "-4px",
1544
+ left: "-3.5px",
1545
+ width: "10px",
1546
+ height: "10px",
1547
+ borderRadius: "50%",
1548
+ background: "#ffffff",
1549
+ border: "2px solid #06b6d4"
1550
+ });
1551
+ lineEl.appendChild(dotTop);
1552
+ lineEl.appendChild(dotBottom);
1553
+ document.body.appendChild(lineEl);
1554
+ }
1555
+ return lineEl;
1556
+ }
1557
+ function showLine(table, borderX) {
1558
+ const line = getOrCreateLine();
1559
+ const tableRect = table.getBoundingClientRect();
1560
+ line.style.left = `${borderX - 1.5}px`;
1561
+ line.style.top = `${tableRect.top}px`;
1562
+ line.style.height = `${tableRect.height}px`;
1563
+ line.style.display = "block";
1564
+ document.body.style.cursor = "col-resize";
1565
+ view.dom.style.cursor = "col-resize";
1566
+ }
1567
+ function hideLine() {
1568
+ if (lineEl) {
1569
+ lineEl.style.display = "none";
1570
+ }
1571
+ document.body.style.cursor = "";
1572
+ view.dom.style.cursor = "";
1573
+ }
1574
+ const onMouseMoveHover = function(event) {
1575
+ if (isDragging) return;
1576
+ const target = event.target;
1577
+ const td = target.closest("td, th");
1578
+ if (!td) {
1579
+ hideLine();
1580
+ return;
1581
+ }
1582
+ const r = td.getBoundingClientRect();
1583
+ const distRight = Math.abs(event.clientX - r.right);
1584
+ const distLeft = Math.abs(event.clientX - r.left);
1585
+ const parent = td.parentElement;
1586
+ if (!parent) {
1587
+ hideLine();
1588
+ return;
1589
+ }
1590
+ const colIdx = Array.from(parent.children).indexOf(td);
1591
+ let borderX = -1;
1592
+ if (distRight <= 16) {
1593
+ borderX = r.right;
1594
+ } else if (distLeft <= 16 && colIdx > 0) {
1595
+ borderX = r.left;
1596
+ }
1597
+ if (borderX >= 0) {
1598
+ const table = td.closest("table");
1599
+ if (table) {
1600
+ showLine(table, borderX);
1601
+ }
1602
+ } else {
1603
+ hideLine();
1604
+ }
1605
+ };
1606
+ document.addEventListener("mousemove", onMouseMoveHover, true);
1607
+ view.dom.addEventListener("mousedown", function handleMouseDown(event) {
1608
+ onMouseDown(event);
1609
+ const td = event.target.closest("td, th");
1610
+ if (!td) return;
1611
+ const r = td.getBoundingClientRect();
1612
+ const distRight = Math.abs(event.clientX - r.right);
1613
+ const distLeft = Math.abs(event.clientX - r.left);
1614
+ const parent = td.parentElement;
1615
+ if (!parent) return;
1616
+ const colIdx = Array.from(parent.children).indexOf(td);
1617
+ if (distRight <= 16 || distLeft <= 16 && colIdx > 0) {
1618
+ isDragging = true;
1619
+ hideLine();
1620
+ const onDragEnd = function() {
1621
+ isDragging = false;
1622
+ hideLine();
1623
+ document.removeEventListener("mouseup", onDragEnd, true);
1624
+ };
1625
+ document.addEventListener("mouseup", onDragEnd, true);
1626
+ }
1627
+ }, true);
1628
+ return {
1629
+ destroy: function() {
1630
+ document.removeEventListener("mousemove", onMouseMoveHover, true);
1631
+ if (lineEl && lineEl.parentElement) {
1632
+ lineEl.parentElement.removeChild(lineEl);
1633
+ }
1634
+ lineEl = null;
1635
+ hideLine();
1636
+ }
1637
+ };
1638
+ }
1639
+ })];
1640
+ }
1641
+ });
293
1642
  let extensions = [
1643
+ ManualColumnResize,
294
1644
  baseStarterKit,
295
1645
  TextStyle,
296
1646
  blockAttrs,
297
1647
  paginationExt,
1648
+ // Always present — carries host-injected ports (onImageUpload, citation, …)
1649
+ // in storage so plugin commands can reach them through the editor instance.
1650
+ EditorContextExtension.configure({
1651
+ onImageUpload: options.onImageUpload,
1652
+ citation: options.citation,
1653
+ aiStream: options.aiStream,
1654
+ aiDraft: options.aiDraft
1655
+ }),
1656
+ // Always present — find & replace decorations + state (core editing infra).
1657
+ SearchAndReplaceExtension,
298
1658
  ...pluginExtensions
299
1659
  ];
300
1660
  const content = options.collaboration ? void 0 : options.content;
301
1661
  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
1662
  extensions = [...extensions, ...collaborationExtensions(collaborationSetup)];
308
1663
  }
309
1664
  return new TiptapEditor({
@@ -313,12 +1668,18 @@ function createTiptapEditor(options, plugins, collaborationSetup) {
313
1668
  editable: options.editable ?? true,
314
1669
  onUpdate: ({ editor }) => {
315
1670
  options.onUpdate?.(editor.getJSON());
1671
+ },
1672
+ editorProps: {
1673
+ // Sanitize pasted HTML (strips <meta>, <style>, comments, etc.)
1674
+ // before ProseMirror parsing. Prevents crashes from non-content
1675
+ // tags commonly produced by Google Docs clipboard data.
1676
+ transformPastedHTML: sanitizePastedHTML
316
1677
  }
317
1678
  });
318
1679
  }
319
1680
 
320
1681
  // src/FontSize.ts
321
- import { Extension as Extension2 } from "@tiptap/core";
1682
+ import { Extension as Extension6 } from "@tiptap/core";
322
1683
  function mergeFontSize(textStyleType, existing, fontSize) {
323
1684
  if (fontSize === null) {
324
1685
  const { fontSize: _removed, ...rest } = existing?.attrs ?? {};
@@ -329,7 +1690,7 @@ function mergeFontSize(textStyleType, existing, fontSize) {
329
1690
  function hasAttrs(mark) {
330
1691
  return Object.values(mark.attrs).some((v) => v != null);
331
1692
  }
332
- var FontSizeExtension = Extension2.create({
1693
+ var FontSizeExtension = Extension6.create({
333
1694
  name: "fontSize",
334
1695
  addGlobalAttributes() {
335
1696
  return [
@@ -427,18 +1788,135 @@ var FontSizeExtension = Extension2.create({
427
1788
  }
428
1789
  });
429
1790
 
430
- // src/index.ts
431
- import { PaginationPlus as PaginationPlus2, PAGE_SIZES } from "tiptap-pagination-plus";
1791
+ // src/SubdocumentProvider.ts
1792
+ import { Awareness as AwarenessClass } from "y-protocols/awareness";
1793
+ import { WebsocketProvider as WebsocketProvider2 } from "y-websocket";
1794
+ import * as Y2 from "yjs";
1795
+ var SubdocumentProvider = class {
1796
+ parentDoc;
1797
+ subdocs;
1798
+ awareness;
1799
+ options;
1800
+ states = /* @__PURE__ */ new Map();
1801
+ activeQueue = [];
1802
+ parentProvider = null;
1803
+ constructor(options) {
1804
+ this.options = {
1805
+ maxActive: options.maxActive ?? 5,
1806
+ onStateChange: options.onStateChange ?? (() => {
1807
+ }),
1808
+ ...options
1809
+ };
1810
+ this.parentDoc = new Y2.Doc();
1811
+ this.subdocs = this.parentDoc.getMap("subdocs");
1812
+ this.awareness = new AwarenessClass(this.parentDoc);
1813
+ this.awareness.setLocalStateField("user", this.options.user);
1814
+ this.parentProvider = new WebsocketProvider2(
1815
+ this.options.websocketUrl,
1816
+ `${this.options.roomPrefix}/_parent`,
1817
+ this.parentDoc
1818
+ );
1819
+ }
1820
+ /** Create a new subdocument. Does NOT activate it. */
1821
+ createSubdoc(id, initialState) {
1822
+ if (this.states.has(id)) return this.states.get(id).doc;
1823
+ const doc = new Y2.Doc();
1824
+ if (initialState) Y2.applyUpdate(doc, initialState);
1825
+ doc.getXmlFragment("default");
1826
+ this.subdocs.set(id, doc);
1827
+ this.states.set(id, {
1828
+ id,
1829
+ doc,
1830
+ provider: null,
1831
+ active: false
1832
+ });
1833
+ this.options.onStateChange(this.getAllStates());
1834
+ return doc;
1835
+ }
1836
+ /** Activate a subdocument — connects it to the network for live sync. */
1837
+ activate(id) {
1838
+ const state = this.states.get(id);
1839
+ if (!state || state.active) return;
1840
+ if (this.activeQueue.length >= this.options.maxActive) {
1841
+ const oldest = this.activeQueue.shift();
1842
+ if (oldest) this.deactivate(oldest);
1843
+ }
1844
+ const doc = state.doc;
1845
+ const roomName = `${this.options.roomPrefix}/${id}`;
1846
+ const provider = new WebsocketProvider2(
1847
+ this.options.websocketUrl,
1848
+ roomName,
1849
+ doc
1850
+ );
1851
+ provider.awareness.setLocalStateField("user", this.options.user);
1852
+ state.provider = provider;
1853
+ state.active = true;
1854
+ this.activeQueue.push(id);
1855
+ this.options.onStateChange(this.getAllStates());
1856
+ }
1857
+ /** Deactivate a subdocument — disconnects it from the network. */
1858
+ deactivate(id) {
1859
+ const state = this.states.get(id);
1860
+ if (!state || !state.active) return;
1861
+ state.provider?.destroy();
1862
+ state.provider = null;
1863
+ state.active = false;
1864
+ const idx = this.activeQueue.indexOf(id);
1865
+ if (idx >= 0) this.activeQueue.splice(idx, 1);
1866
+ this.options.onStateChange(this.getAllStates());
1867
+ }
1868
+ /** Get the Y.XmlFragment for a subdocument. */
1869
+ getFragment(id) {
1870
+ const doc = this.states.get(id)?.doc ?? this.subdocs.get(id);
1871
+ if (!doc) return null;
1872
+ return doc.getXmlFragment("default");
1873
+ }
1874
+ /** Check if a subdocument is currently active (syncing). */
1875
+ isActive(id) {
1876
+ return this.states.get(id)?.active ?? false;
1877
+ }
1878
+ /** Get all subdocument states. */
1879
+ getAllStates() {
1880
+ return Array.from(this.states.values());
1881
+ }
1882
+ /** Get IDs of all active subdocuments. */
1883
+ getActiveIds() {
1884
+ return [...this.activeQueue];
1885
+ }
1886
+ /** Destroy all subdocuments and providers. */
1887
+ destroy() {
1888
+ for (const [id] of this.states) {
1889
+ this.deactivate(id);
1890
+ }
1891
+ this.parentProvider?.destroy();
1892
+ this.parentDoc.destroy();
1893
+ this.states.clear();
1894
+ this.activeQueue.length = 0;
1895
+ }
1896
+ };
432
1897
  export {
433
1898
  BlockAttributesExtension,
1899
+ EditorContextExtension,
434
1900
  FontSizeExtension,
435
1901
  PAGE_SIZES,
436
- PaginationPlus2 as PaginationPlus,
1902
+ PaginationPlus,
1903
+ SearchAndReplaceExtension,
1904
+ SubdocumentProvider,
1905
+ clearSearch,
437
1906
  collaborationExtensions,
438
1907
  collectExtensions,
439
1908
  createActionMap,
440
1909
  createCollaboration,
441
1910
  createEditor,
442
1911
  definePlugin,
443
- resolveAction
1912
+ findMatches,
1913
+ getSearchState,
1914
+ replaceAll,
1915
+ replaceCurrent,
1916
+ resolveAction,
1917
+ sanitizePastedHTML,
1918
+ searchAndReplaceKey,
1919
+ searchNext,
1920
+ searchPrev,
1921
+ setSearchQuery
444
1922
  };