@kedataindo/docflow-core 0.0.2 → 0.0.3

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