@harbour-enterprises/superdoc 1.3.0-next.2 → 1.3.0-next.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.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  const jszip = require("./jszip-C8_CqJxM.cjs");
3
3
  const helpers$1 = require("./helpers-nOdwpmwb.cjs");
4
- const superEditor_converter = require("./SuperConverter-DOTz2R8L.cjs");
4
+ const superEditor_converter = require("./SuperConverter-qB6m0K1X.cjs");
5
5
  const vue = require("./vue-De9wkgLl.cjs");
6
6
  require("./jszip.min-BPh2MMAa.cjs");
7
7
  const eventemitter3 = require("./eventemitter3-BQuRcMPI.cjs");
@@ -175,6 +175,354 @@ function parseSizeUnit(val = "0") {
175
175
  function minMax(value = 0, min2 = 0, max2 = 0) {
176
176
  return Math.min(Math.max(value, min2), max2);
177
177
  }
178
+ const FONT_FAMILY_FALLBACKS = Object.freeze({
179
+ swiss: "Arial, sans-serif",
180
+ roman: "Times New Roman, serif",
181
+ modern: "Courier New, monospace",
182
+ script: "cursive",
183
+ decorative: "fantasy",
184
+ system: "system-ui",
185
+ auto: "sans-serif"
186
+ });
187
+ const DEFAULT_GENERIC_FALLBACK = "sans-serif";
188
+ const normalizeParts = (value) => (value || "").split(",").map((part) => part.trim()).filter(Boolean);
189
+ function mapWordFamilyFallback(wordFamily) {
190
+ if (!wordFamily) return DEFAULT_GENERIC_FALLBACK;
191
+ const mapped = FONT_FAMILY_FALLBACKS[wordFamily.toLowerCase()];
192
+ return mapped || DEFAULT_GENERIC_FALLBACK;
193
+ }
194
+ function toCssFontFamily(fontName, options = {}) {
195
+ if (!fontName || typeof fontName !== "string") return fontName;
196
+ const trimmed = fontName.trim();
197
+ if (!trimmed || trimmed.includes(",")) return trimmed;
198
+ const { fallback, wordFamily } = options;
199
+ const fallbackValue = fallback ?? (wordFamily ? mapWordFamilyFallback(wordFamily) : void 0) ?? DEFAULT_GENERIC_FALLBACK;
200
+ const fallbackParts = normalizeParts(fallbackValue);
201
+ if (fallbackParts.length === 0) {
202
+ return trimmed;
203
+ }
204
+ const normalizedName = trimmed.toLowerCase();
205
+ const includesName = fallbackParts.some((part) => part.toLowerCase() === normalizedName);
206
+ if (includesName) {
207
+ return fallbackParts.join(", ");
208
+ }
209
+ return [trimmed, ...fallbackParts].join(", ");
210
+ }
211
+ const sdtMetadataCache = /* @__PURE__ */ new Map();
212
+ function resolveStyle(node, context, options = {}) {
213
+ let paragraph = createDefaultParagraph();
214
+ let character = createDefaultCharacter(context);
215
+ let numbering;
216
+ const chain = resolveStyleChain(node.styleId, context.styles);
217
+ for (const style2 of chain) {
218
+ paragraph = mergeParagraph(paragraph, style2.paragraph);
219
+ character = mergeCharacter(character, style2.character);
220
+ if (!numbering && style2.numbering) {
221
+ numbering = resolveNumbering(style2.numbering.numId, style2.numbering.level, context);
222
+ }
223
+ }
224
+ paragraph = mergeParagraph(paragraph, node.paragraphProps);
225
+ character = mergeCharacter(character, node.characterProps);
226
+ if (node.numbering) {
227
+ numbering = resolveNumbering(node.numbering.numId, node.numbering.level, context);
228
+ }
229
+ const sdt = options?.sdt ? resolveSdtMetadata(options.sdt) : void 0;
230
+ return {
231
+ paragraph,
232
+ character,
233
+ numbering,
234
+ sdt
235
+ };
236
+ }
237
+ function resolveNumbering(numId, level, context) {
238
+ const def = context.numbering?.[numId];
239
+ if (!def) return void 0;
240
+ const levelDef = def.levels.find((entry) => entry.level === level) ?? def.levels[level];
241
+ if (!levelDef) return void 0;
242
+ return {
243
+ numId,
244
+ level,
245
+ indent: {
246
+ left: levelDef.indent?.left,
247
+ hanging: levelDef.indent?.hanging
248
+ },
249
+ format: levelDef.format ?? "decimal",
250
+ text: levelDef.text ?? "%1.",
251
+ start: levelDef.start ?? 1
252
+ };
253
+ }
254
+ function resolveSdtMetadata(input) {
255
+ if (!input) return void 0;
256
+ const { nodeType, attrs, cacheKey: explicitKey } = input;
257
+ if (!nodeType) return void 0;
258
+ const normalizedAttrs = isPlainObject$4(attrs) ? attrs : {};
259
+ const cacheKey = buildSdtCacheKey(nodeType, normalizedAttrs, explicitKey);
260
+ if (cacheKey && sdtMetadataCache.has(cacheKey)) {
261
+ return sdtMetadataCache.get(cacheKey);
262
+ }
263
+ let metadata;
264
+ switch (nodeType) {
265
+ case "fieldAnnotation":
266
+ metadata = normalizeFieldAnnotationMetadata(normalizedAttrs);
267
+ break;
268
+ case "structuredContent":
269
+ case "structuredContentBlock":
270
+ metadata = normalizeStructuredContentMetadata(nodeType, normalizedAttrs);
271
+ break;
272
+ case "documentSection":
273
+ metadata = normalizeDocumentSectionMetadata(normalizedAttrs);
274
+ break;
275
+ case "docPartObject":
276
+ metadata = normalizeDocPartMetadata(normalizedAttrs);
277
+ break;
278
+ }
279
+ if (metadata && cacheKey) {
280
+ sdtMetadataCache.set(cacheKey, metadata);
281
+ }
282
+ return metadata;
283
+ }
284
+ function createDefaultParagraph(_context) {
285
+ return {
286
+ alignment: "left",
287
+ spacing: {
288
+ before: 0,
289
+ after: 0,
290
+ line: 12,
291
+ lineRule: "auto"
292
+ },
293
+ indent: {
294
+ left: 0,
295
+ right: 0,
296
+ firstLine: 0,
297
+ hanging: 0
298
+ },
299
+ tabs: []
300
+ };
301
+ }
302
+ function createDefaultCharacter(context) {
303
+ const baseFont = context.defaults?.paragraphFont ?? "Calibri";
304
+ const fallback = context.defaults?.paragraphFontFallback;
305
+ const wordFamily = context.defaults?.paragraphFontFamily;
306
+ const resolvedFamily = toCssFontFamily(baseFont, { fallback, wordFamily }) ?? baseFont;
307
+ return {
308
+ font: {
309
+ family: resolvedFamily,
310
+ size: context.defaults?.fontSize ?? 11,
311
+ weight: 400,
312
+ italic: false
313
+ },
314
+ color: "#000000"
315
+ };
316
+ }
317
+ function resolveStyleChain(styleId, styles) {
318
+ if (!styleId || !styles) return [];
319
+ const result = [];
320
+ const visited = /* @__PURE__ */ new Set();
321
+ let current = styles[styleId];
322
+ while (current && !visited.has(current.id)) {
323
+ result.unshift(current);
324
+ visited.add(current.id);
325
+ current = current.basedOn ? styles[current.basedOn] : void 0;
326
+ }
327
+ return result;
328
+ }
329
+ function mergeParagraph(base2, overrides) {
330
+ if (!overrides) return base2;
331
+ return {
332
+ ...base2,
333
+ alignment: overrides.alignment ?? base2.alignment,
334
+ spacing: overrides.spacing ? { ...base2.spacing, ...overrides.spacing } : base2.spacing,
335
+ indent: overrides.indent ? { ...base2.indent, ...overrides.indent } : base2.indent,
336
+ borders: overrides.borders ? { ...base2.borders, ...overrides.borders } : base2.borders,
337
+ shading: overrides.shading ?? base2.shading,
338
+ tabs: overrides.tabs ?? base2.tabs
339
+ };
340
+ }
341
+ function mergeCharacter(base2, overrides) {
342
+ if (!overrides) return base2;
343
+ return {
344
+ ...base2,
345
+ font: overrides.font ? { ...base2.font, ...overrides.font } : base2.font,
346
+ color: overrides.color ?? base2.color,
347
+ underline: overrides.underline ?? base2.underline,
348
+ strike: overrides.strike ?? base2.strike,
349
+ highlight: overrides.highlight ?? base2.highlight,
350
+ letterSpacing: overrides.letterSpacing ?? base2.letterSpacing
351
+ };
352
+ }
353
+ function normalizeFieldAnnotationMetadata(attrs) {
354
+ const fieldId = toOptionalString(attrs.fieldId) ?? "";
355
+ const formatting = extractFormatting(attrs);
356
+ const size2 = normalizeSize(attrs.size);
357
+ const extras = isPlainObject$4(attrs.extras) ? attrs.extras : null;
358
+ const marks = isPlainObject$4(attrs.marks) ? attrs.marks : void 0;
359
+ return {
360
+ type: "fieldAnnotation",
361
+ fieldId,
362
+ variant: normalizeFieldAnnotationVariant(attrs.type),
363
+ fieldType: toOptionalString(attrs.fieldType),
364
+ displayLabel: toOptionalString(attrs.displayLabel),
365
+ defaultDisplayLabel: toOptionalString(attrs.defaultDisplayLabel),
366
+ alias: toOptionalString(attrs.alias),
367
+ fieldColor: normalizeColorValue(attrs.fieldColor),
368
+ borderColor: normalizeColorValue(attrs.borderColor),
369
+ highlighted: toBoolean$3(attrs.highlighted, true),
370
+ fontFamily: toNullableString(attrs.fontFamily),
371
+ fontSize: normalizeFontSize(attrs.fontSize),
372
+ textColor: normalizeColorValue(attrs.textColor) ?? null,
373
+ textHighlight: normalizeColorValue(attrs.textHighlight) ?? null,
374
+ linkUrl: toNullableString(attrs.linkUrl),
375
+ imageSrc: toNullableString(attrs.imageSrc),
376
+ rawHtml: attrs.rawHtml ?? void 0,
377
+ size: size2 ?? null,
378
+ extras,
379
+ multipleImage: toBoolean$3(attrs.multipleImage, false),
380
+ hash: toOptionalString(attrs.hash) ?? null,
381
+ generatorIndex: toNumber(attrs.generatorIndex),
382
+ sdtId: toOptionalString(attrs.sdtId) ?? null,
383
+ hidden: toBoolean$3(attrs.hidden, false),
384
+ visibility: normalizeVisibility(attrs.visibility),
385
+ isLocked: toBoolean$3(attrs.isLocked, false),
386
+ formatting,
387
+ marks
388
+ };
389
+ }
390
+ function normalizeStructuredContentMetadata(nodeType, attrs) {
391
+ return {
392
+ type: "structuredContent",
393
+ scope: nodeType === "structuredContentBlock" ? "block" : "inline",
394
+ id: toNullableString(attrs.id),
395
+ tag: toOptionalString(attrs.tag),
396
+ alias: toOptionalString(attrs.alias),
397
+ sdtPr: attrs.sdtPr
398
+ };
399
+ }
400
+ function normalizeDocumentSectionMetadata(attrs) {
401
+ return {
402
+ type: "documentSection",
403
+ id: toNullableString(attrs.id),
404
+ title: toOptionalString(attrs.title) ?? null,
405
+ description: toOptionalString(attrs.description) ?? null,
406
+ sectionType: toOptionalString(attrs.sectionType) ?? null,
407
+ isLocked: toBoolean$3(attrs.isLocked, false),
408
+ sdBlockId: toNullableString(attrs.sdBlockId)
409
+ };
410
+ }
411
+ function normalizeDocPartMetadata(attrs) {
412
+ return {
413
+ type: "docPartObject",
414
+ gallery: toOptionalString(attrs.docPartGallery ?? attrs.gallery) ?? null,
415
+ // Source uniqueId from attrs.id (PM adapter uses getDocPartObjectId which extracts attrs.id)
416
+ // Fall back to attrs.uniqueId for compatibility
417
+ uniqueId: toOptionalString(attrs.id ?? attrs.uniqueId) ?? null,
418
+ alias: toOptionalString(attrs.alias) ?? null,
419
+ instruction: toOptionalString(attrs.instruction) ?? null
420
+ };
421
+ }
422
+ function isPlainObject$4(value) {
423
+ return !!value && typeof value === "object" && !Array.isArray(value);
424
+ }
425
+ function toOptionalString(value) {
426
+ if (value == null) return void 0;
427
+ if (typeof value === "string") {
428
+ const trimmed = value.trim();
429
+ return trimmed.length ? trimmed : void 0;
430
+ }
431
+ return String(value);
432
+ }
433
+ function toNullableString(value) {
434
+ const str = toOptionalString(value);
435
+ return str ?? null;
436
+ }
437
+ function toBoolean$3(value, fallback) {
438
+ if (typeof value === "boolean") return value;
439
+ if (typeof value === "string") {
440
+ const lower = value.toLowerCase();
441
+ if (lower === "true") return true;
442
+ if (lower === "false") return false;
443
+ }
444
+ if (value == null) return fallback;
445
+ return Boolean(value);
446
+ }
447
+ function normalizeVisibility(value) {
448
+ if (typeof value !== "string") return void 0;
449
+ const normalized = value.toLowerCase();
450
+ if (normalized === "visible" || normalized === "hidden") {
451
+ return normalized;
452
+ }
453
+ return void 0;
454
+ }
455
+ function normalizeColorValue(value) {
456
+ if (typeof value !== "string") return void 0;
457
+ const trimmed = value.trim();
458
+ if (!trimmed || trimmed.toLowerCase() === "none") return void 0;
459
+ return trimmed;
460
+ }
461
+ function normalizeFontSize(value) {
462
+ if (value == null) return null;
463
+ if (typeof value === "number") {
464
+ return Number.isFinite(value) ? value : null;
465
+ }
466
+ if (typeof value === "string") {
467
+ const trimmed = value.trim();
468
+ return trimmed.length ? trimmed : null;
469
+ }
470
+ return null;
471
+ }
472
+ function toNumber(value) {
473
+ if (typeof value === "number") {
474
+ return Number.isFinite(value) ? value : null;
475
+ }
476
+ if (typeof value === "string") {
477
+ const parsed = parseFloat(value);
478
+ return Number.isFinite(parsed) ? parsed : null;
479
+ }
480
+ return null;
481
+ }
482
+ function normalizeSize(value) {
483
+ if (!isPlainObject$4(value)) return null;
484
+ const obj = value;
485
+ const width = toNumber(obj.width);
486
+ const height = toNumber(obj.height);
487
+ if (width == null && height == null) return null;
488
+ const result = {};
489
+ if (width != null) result.width = width;
490
+ if (height != null) result.height = height;
491
+ return result;
492
+ }
493
+ function normalizeFieldAnnotationVariant(value) {
494
+ if (typeof value !== "string") return void 0;
495
+ const normalized = value.toLowerCase();
496
+ if (normalized === "text" || normalized === "image" || normalized === "signature" || normalized === "checkbox" || normalized === "html" || normalized === "link") {
497
+ return normalized;
498
+ }
499
+ return void 0;
500
+ }
501
+ function extractFormatting(attrs) {
502
+ const bold = toBoolean$3(attrs.bold, false);
503
+ const italic = toBoolean$3(attrs.italic, false);
504
+ const underline = toBoolean$3(attrs.underline, false);
505
+ const formatting = {};
506
+ if (bold) formatting.bold = true;
507
+ if (italic) formatting.italic = true;
508
+ if (underline) formatting.underline = true;
509
+ return Object.keys(formatting).length ? formatting : void 0;
510
+ }
511
+ function buildSdtCacheKey(nodeType, attrs, explicitKey) {
512
+ const provided = toOptionalString(explicitKey);
513
+ if (provided) {
514
+ return `${nodeType}:${provided}`;
515
+ }
516
+ const hash2 = toOptionalString(attrs.hash);
517
+ if (hash2) {
518
+ return `${nodeType}:${hash2}`;
519
+ }
520
+ const id = toOptionalString(attrs.id);
521
+ if (id) {
522
+ return `${nodeType}:${id}`;
523
+ }
524
+ return void 0;
525
+ }
178
526
  function createDocument(converter, schema, editor, { check = false } = {}) {
179
527
  const documentData = converter.getSchema(editor);
180
528
  if (documentData) {
@@ -9108,15 +9456,19 @@ const splitRunToParagraph = () => (props) => {
9108
9456
  dispatchTransaction = editor.dispatch.bind(editor);
9109
9457
  }
9110
9458
  if (!dispatchTransaction) return false;
9111
- const handled = splitBlockPatch(state, (transaction) => {
9112
- dispatchTransaction(transaction);
9113
- });
9459
+ const handled = splitBlockPatch(
9460
+ state,
9461
+ (transaction) => {
9462
+ dispatchTransaction(transaction);
9463
+ },
9464
+ editor
9465
+ );
9114
9466
  if (handled) {
9115
9467
  tr.setMeta("preventDispatch", true);
9116
9468
  }
9117
9469
  return handled;
9118
9470
  };
9119
- function splitBlockPatch(state, dispatch) {
9471
+ function splitBlockPatch(state, dispatch, editor) {
9120
9472
  let { $from } = state.selection;
9121
9473
  if (state.selection instanceof superEditor_converter.NodeSelection && state.selection.node.isBlock) {
9122
9474
  if (!$from.parentOffset || !superEditor_converter.canSplit(state.doc, $from.pos)) return false;
@@ -9125,14 +9477,15 @@ function splitBlockPatch(state, dispatch) {
9125
9477
  }
9126
9478
  if (!$from.depth) return false;
9127
9479
  let types = [];
9128
- let splitDepth, deflt, atEnd = false, atStart = false;
9480
+ let splitDepth, deflt, paragraphAttrs = null, atEnd = false, atStart = false;
9129
9481
  for (let d2 = $from.depth; ; d2--) {
9130
9482
  let node = $from.node(d2);
9131
9483
  if (node.isBlock) {
9132
9484
  atEnd = $from.end(d2) == $from.pos + ($from.depth - d2);
9133
9485
  atStart = $from.start(d2) == $from.pos - ($from.depth - d2);
9134
9486
  deflt = defaultBlockAt$1($from.node(d2 - 1).contentMatchAt($from.indexAfter(d2 - 1)));
9135
- types.unshift(null);
9487
+ paragraphAttrs = { ...node.attrs };
9488
+ types.unshift({ type: deflt || node.type, attrs: paragraphAttrs });
9136
9489
  splitDepth = d2;
9137
9490
  break;
9138
9491
  } else {
@@ -9145,7 +9498,7 @@ function splitBlockPatch(state, dispatch) {
9145
9498
  let splitPos = tr.mapping.map($from.pos);
9146
9499
  let can = superEditor_converter.canSplit(tr.doc, splitPos, types.length, types);
9147
9500
  if (!can) {
9148
- types[0] = deflt ? { type: deflt } : null;
9501
+ types[0] = deflt ? { type: deflt, attrs: paragraphAttrs } : null;
9149
9502
  can = superEditor_converter.canSplit(tr.doc, splitPos, types.length, types);
9150
9503
  }
9151
9504
  if (!can) return false;
@@ -9155,9 +9508,37 @@ function splitBlockPatch(state, dispatch) {
9155
9508
  if (deflt && $from.node(splitDepth - 1).canReplaceWith($first.index(), $first.index() + 1, deflt))
9156
9509
  tr.setNodeMarkup(tr.mapping.map($from.before(splitDepth)), deflt);
9157
9510
  }
9511
+ applyStyleMarks(state, tr, editor, paragraphAttrs);
9158
9512
  if (dispatch) dispatch(tr.scrollIntoView());
9159
9513
  return true;
9160
9514
  }
9515
+ function applyStyleMarks(state, tr, editor, paragraphAttrs) {
9516
+ const styleId = paragraphAttrs?.paragraphProperties?.styleId;
9517
+ if (!editor?.converter && !styleId) {
9518
+ return;
9519
+ }
9520
+ try {
9521
+ const params2 = { docx: editor?.converter?.convertedXml ?? {}, numbering: editor?.converter?.numbering ?? {} };
9522
+ const resolvedPpr = styleId ? { styleId } : {};
9523
+ const runProperties = styleId ? superEditor_converter.resolveRunProperties(params2, {}, resolvedPpr, false, false) : {};
9524
+ const markDefsFromStyle = styleId ? (
9525
+ /** @type {Array<{type: string, attrs: Record<string, unknown>}>} */
9526
+ superEditor_converter.encodeMarksFromRPr(runProperties, editor?.converter?.convertedXml ?? {})
9527
+ ) : [];
9528
+ const selectionMarks = state.selection?.$from?.marks ? state.selection.$from.marks() : [];
9529
+ const selectionMarkDefs = selectionMarks.map((mark) => ({ type: mark.type.name, attrs: mark.attrs }));
9530
+ const markDefsToApply = selectionMarks.length ? selectionMarkDefs : markDefsFromStyle;
9531
+ const marksToApply = markDefsToApply.map((def) => {
9532
+ const markType = state.schema.marks[def.type];
9533
+ return markType ? markType.create(def.attrs) : null;
9534
+ }).filter(Boolean);
9535
+ if (marksToApply.length > 0) {
9536
+ tr.ensureMarks(marksToApply);
9537
+ tr.setMeta("sdStyleMarks", markDefsToApply);
9538
+ }
9539
+ } catch {
9540
+ }
9541
+ }
9161
9542
  const splitRunAtCursor = () => (props) => {
9162
9543
  let { state, dispatch, tr } = props;
9163
9544
  const sel = state.selection;
@@ -10041,7 +10422,7 @@ const updateAttributes = (typeOrName, attrs = {}) => ({ tr, state, dispatch }) =
10041
10422
  }
10042
10423
  return true;
10043
10424
  };
10044
- const isPlainObject$4 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
10425
+ const isPlainObject$3 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
10045
10426
  const assignNestedValue = (target, path, value) => {
10046
10427
  if (!path.includes(".")) {
10047
10428
  target[path] = value;
@@ -10055,7 +10436,7 @@ const assignNestedValue = (target, path, value) => {
10055
10436
  if (isLast) {
10056
10437
  current[part] = value;
10057
10438
  } else {
10058
- if (!isPlainObject$4(current[part])) {
10439
+ if (!isPlainObject$3(current[part])) {
10059
10440
  current[part] = {};
10060
10441
  }
10061
10442
  current = current[part];
@@ -13028,8 +13409,12 @@ const createOrUpdateTrackedChangeComment = ({ event, marks, deletionNodes, nodes
13028
13409
  const hasMatchingId = changeMarks.find((mark) => mark.attrs.id === id);
13029
13410
  if (hasMatchingId) nodesWithMark.push(node2);
13030
13411
  });
13412
+ const nodesToProcess = nodesWithMark.length ? nodesWithMark : node ? [node] : [];
13413
+ if (!nodesToProcess.length) {
13414
+ return;
13415
+ }
13031
13416
  const { deletionText, trackedChangeText } = getTrackedChangeText({
13032
- nodes: nodesWithMark.length ? nodesWithMark : [node],
13417
+ nodes: nodesToProcess,
13033
13418
  mark: trackedMark,
13034
13419
  trackedChangeType,
13035
13420
  isDeletionInsertion
@@ -13745,6 +14130,45 @@ const updateYdocDocxData = async (editor, ydoc) => {
13745
14130
  console.warn("[collaboration] Failed to update Ydoc docx data", error);
13746
14131
  }
13747
14132
  };
14133
+ let isApplyingRemoteChanges = false;
14134
+ const isApplyingRemoteHeaderFooterChanges = () => isApplyingRemoteChanges;
14135
+ const pushHeaderFooterToYjs = (editor, type, sectionId, content) => {
14136
+ if (isApplyingRemoteChanges) return;
14137
+ const ydoc = editor?.options?.ydoc;
14138
+ if (!ydoc) return;
14139
+ const headerFooterMap = ydoc.getMap("headerFooterJson");
14140
+ const key2 = `${type}:${sectionId}`;
14141
+ const existing = headerFooterMap.get(key2)?.content;
14142
+ if (existing && JSON.stringify(existing) === JSON.stringify(content)) {
14143
+ return;
14144
+ }
14145
+ ydoc.transact(() => headerFooterMap.set(key2, { type, sectionId, content }), {
14146
+ event: "header-footer-update",
14147
+ user: editor.options.user
14148
+ });
14149
+ };
14150
+ const applyRemoteHeaderFooterChanges = (editor, key2, data) => {
14151
+ if (!editor || editor.isDestroyed || !editor.converter) return;
14152
+ const { type, sectionId, content } = data;
14153
+ if (!type || !sectionId || !content) return;
14154
+ isApplyingRemoteChanges = true;
14155
+ try {
14156
+ const storage = editor.converter[`${type}s`];
14157
+ if (storage) storage[sectionId] = content;
14158
+ editor.converter.headerFooterModified = true;
14159
+ const editors = editor.converter[`${type}Editors`];
14160
+ editors?.forEach((item) => {
14161
+ if (item.id === sectionId && item.editor) {
14162
+ item.editor.replaceContent(content);
14163
+ }
14164
+ });
14165
+ editor.emit("remoteHeaderFooterChanged", { type, sectionId, content });
14166
+ } finally {
14167
+ setTimeout(() => {
14168
+ isApplyingRemoteChanges = false;
14169
+ }, 0);
14170
+ }
14171
+ };
13748
14172
  new superEditor_converter.PluginKey("collaboration");
13749
14173
  const Collaboration = Extension.create({
13750
14174
  name: "collaboration",
@@ -13773,6 +14197,18 @@ const Collaboration = Extension.create({
13773
14197
  }
13774
14198
  });
13775
14199
  });
14200
+ const headerFooterMap = this.options.ydoc.getMap("headerFooterJson");
14201
+ headerFooterMap.observe((event) => {
14202
+ if (event.transaction.local) return;
14203
+ event.changes.keys.forEach((change, key2) => {
14204
+ if (change.action === "add" || change.action === "update") {
14205
+ const data = headerFooterMap.get(key2);
14206
+ if (data) {
14207
+ applyRemoteHeaderFooterChanges(this.editor, key2, data);
14208
+ }
14209
+ }
14210
+ });
14211
+ });
13776
14212
  return [syncPlugin];
13777
14213
  },
13778
14214
  addCommands() {
@@ -14915,7 +15351,7 @@ const canUseDOM = () => {
14915
15351
  return false;
14916
15352
  }
14917
15353
  };
14918
- const summaryVersion = "1.3.0-next.2";
15354
+ const summaryVersion = "1.3.0-next.4";
14919
15355
  const nodeKeys = ["group", "content", "marks", "inline", "atom", "defining", "code", "tableRole", "summary"];
14920
15356
  const markKeys = ["group", "inclusive", "excludes", "spanning", "code"];
14921
15357
  function mapAttributes(attrs) {
@@ -17548,7 +17984,7 @@ class Editor extends EventEmitter {
17548
17984
  * Process collaboration migrations
17549
17985
  */
17550
17986
  processCollaborationMigrations() {
17551
- console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.2");
17987
+ console.debug("[checkVersionMigrations] Current editor version", "1.3.0-next.4");
17552
17988
  if (!this.options.ydoc) return;
17553
17989
  const metaMap = this.options.ydoc.getMap("meta");
17554
17990
  let docVersion = metaMap.get("version");
@@ -23123,39 +23559,6 @@ const resolveTableCellBorders = (tableBorders, rowIndex, colIndex, totalRows, to
23123
23559
  right: borderValueToSpec(isLastCol ? tableBorders?.right : null)
23124
23560
  };
23125
23561
  };
23126
- const FONT_FAMILY_FALLBACKS = Object.freeze({
23127
- swiss: "Arial, sans-serif",
23128
- roman: "Times New Roman, serif",
23129
- modern: "Courier New, monospace",
23130
- script: "cursive",
23131
- decorative: "fantasy",
23132
- system: "system-ui",
23133
- auto: "sans-serif"
23134
- });
23135
- const DEFAULT_GENERIC_FALLBACK = "sans-serif";
23136
- const normalizeParts = (value) => (value || "").split(",").map((part) => part.trim()).filter(Boolean);
23137
- function mapWordFamilyFallback(wordFamily) {
23138
- if (!wordFamily) return DEFAULT_GENERIC_FALLBACK;
23139
- const mapped = FONT_FAMILY_FALLBACKS[wordFamily.toLowerCase()];
23140
- return mapped || DEFAULT_GENERIC_FALLBACK;
23141
- }
23142
- function toCssFontFamily(fontName, options = {}) {
23143
- if (!fontName || typeof fontName !== "string") return fontName;
23144
- const trimmed = fontName.trim();
23145
- if (!trimmed || trimmed.includes(",")) return trimmed;
23146
- const { fallback, wordFamily } = options;
23147
- const fallbackValue = fallback ?? (wordFamily ? mapWordFamilyFallback(wordFamily) : void 0) ?? DEFAULT_GENERIC_FALLBACK;
23148
- const fallbackParts = normalizeParts(fallbackValue);
23149
- if (fallbackParts.length === 0) {
23150
- return trimmed;
23151
- }
23152
- const normalizedName = trimmed.toLowerCase();
23153
- const includesName = fallbackParts.some((part) => part.toLowerCase() === normalizedName);
23154
- if (includesName) {
23155
- return fallbackParts.join(", ");
23156
- }
23157
- return [trimmed, ...fallbackParts].join(", ");
23158
- }
23159
23562
  const LIST_MARKER_GAP$3 = 8;
23160
23563
  function renderListMarker(params2) {
23161
23564
  const { doc: doc2, lineEl, markerLayout, markerMeasure, indentLeftPx } = params2;
@@ -27158,7 +27561,12 @@ class DomPainter {
27158
27561
  const hanging = paraIndent?.hanging ?? 0;
27159
27562
  const isFirstLineOfPara = lineIndex === 0 || lineIndex === void 0;
27160
27563
  const firstLineOffsetForCumX = isFirstLineOfPara ? firstLine - hanging : 0;
27161
- const indentOffset = indentLeft + firstLineOffsetForCumX;
27564
+ const wordLayoutValue = block.attrs?.wordLayout;
27565
+ const wordLayout = isMinimalWordLayout(wordLayoutValue) ? wordLayoutValue : void 0;
27566
+ const isListParagraph = Boolean(wordLayout?.marker);
27567
+ const rawTextStartPx = typeof wordLayout?.marker?.textStartX === "number" && Number.isFinite(wordLayout.marker.textStartX) ? wordLayout.marker.textStartX : typeof wordLayout?.textStartPx === "number" && Number.isFinite(wordLayout.textStartPx) ? wordLayout.textStartPx : void 0;
27568
+ const listIndentOffset = isFirstLineOfPara ? rawTextStartPx ?? indentLeft : indentLeft;
27569
+ const indentOffset = isListParagraph ? listIndentOffset : indentLeft + firstLineOffsetForCumX;
27162
27570
  let cumulativeX = 0;
27163
27571
  const segmentsByRun = /* @__PURE__ */ new Map();
27164
27572
  line.segments.forEach((segment) => {
@@ -39719,8 +40127,17 @@ const pxToPt = (px) => {
39719
40127
  if (px == null || !Number.isFinite(px)) return void 0;
39720
40128
  return px / PX_PER_PT;
39721
40129
  };
40130
+ const convertIndentTwipsToPx$1 = (indent) => {
40131
+ if (!indent) return void 0;
40132
+ const result = {};
40133
+ if (isFiniteNumber(indent.left)) result.left = twipsToPx$1(indent.left);
40134
+ if (isFiniteNumber(indent.right)) result.right = twipsToPx$1(indent.right);
40135
+ if (isFiniteNumber(indent.firstLine)) result.firstLine = twipsToPx$1(indent.firstLine);
40136
+ if (isFiniteNumber(indent.hanging)) result.hanging = twipsToPx$1(indent.hanging);
40137
+ return Object.keys(result).length ? result : void 0;
40138
+ };
39722
40139
  const isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
39723
- const isPlainObject$3 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
40140
+ const isPlainObject$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
39724
40141
  const normalizePrefix = (value) => {
39725
40142
  if (!value) return "";
39726
40143
  return String(value);
@@ -39782,7 +40199,7 @@ function coerceBoolean(value) {
39782
40199
  }
39783
40200
  return void 0;
39784
40201
  }
39785
- const toBoolean$3 = (value) => {
40202
+ const toBoolean$2 = (value) => {
39786
40203
  if (typeof value === "boolean") return value;
39787
40204
  if (typeof value === "string") {
39788
40205
  const v = value.trim().toLowerCase();
@@ -40073,7 +40490,7 @@ function hydrateImageBlocks(blocks, mediaFiles) {
40073
40490
  });
40074
40491
  }
40075
40492
  function isGradientFill(value) {
40076
- if (!isPlainObject$3(value)) return false;
40493
+ if (!isPlainObject$2(value)) return false;
40077
40494
  if (value.type !== "gradient") return false;
40078
40495
  const gradientType = value.gradientType;
40079
40496
  if (gradientType !== "linear" && gradientType !== "radial") return false;
@@ -40084,12 +40501,12 @@ function isGradientFill(value) {
40084
40501
  }
40085
40502
  if (!Array.isArray(value.stops) || value.stops.length === 0) return false;
40086
40503
  return value.stops.every((stop) => {
40087
- if (!isPlainObject$3(stop)) return false;
40504
+ if (!isPlainObject$2(stop)) return false;
40088
40505
  return typeof stop.position === "number" && Number.isFinite(stop.position) && typeof stop.color === "string" && (stop.alpha === void 0 || typeof stop.alpha === "number" && Number.isFinite(stop.alpha));
40089
40506
  });
40090
40507
  }
40091
40508
  function isSolidFillWithAlpha(value) {
40092
- return isPlainObject$3(value) && value.type === "solidWithAlpha" && typeof value.color === "string" && typeof value.alpha === "number";
40509
+ return isPlainObject$2(value) && value.type === "solidWithAlpha" && typeof value.color === "string" && typeof value.alpha === "number";
40093
40510
  }
40094
40511
  function normalizeFillColor(value) {
40095
40512
  if (value === null) return null;
@@ -40104,10 +40521,10 @@ function normalizeStrokeColor(value) {
40104
40521
  return void 0;
40105
40522
  }
40106
40523
  function normalizeTextContent(value) {
40107
- if (!isPlainObject$3(value)) return void 0;
40524
+ if (!isPlainObject$2(value)) return void 0;
40108
40525
  if (!Array.isArray(value.parts)) return void 0;
40109
40526
  if (value.parts.length === 0) return void 0;
40110
- const validParts = value.parts.filter((p) => isPlainObject$3(p) && typeof p.text === "string");
40527
+ const validParts = value.parts.filter((p) => isPlainObject$2(p) && typeof p.text === "string");
40111
40528
  if (validParts.length === 0) return void 0;
40112
40529
  const result = {
40113
40530
  parts: validParts
@@ -40125,7 +40542,7 @@ function normalizeTextVerticalAlign(value) {
40125
40542
  return void 0;
40126
40543
  }
40127
40544
  function normalizeTextInsets(value) {
40128
- if (!isPlainObject$3(value)) return void 0;
40545
+ if (!isPlainObject$2(value)) return void 0;
40129
40546
  const top2 = pickNumber(value.top);
40130
40547
  const right2 = pickNumber(value.right);
40131
40548
  const bottom2 = pickNumber(value.bottom);
@@ -40137,7 +40554,7 @@ function normalizeTextInsets(value) {
40137
40554
  }
40138
40555
  const OOXML_Z_INDEX_BASE = 251658240;
40139
40556
  function normalizeZIndex(originalAttributes) {
40140
- if (!isPlainObject$3(originalAttributes)) return void 0;
40557
+ if (!isPlainObject$2(originalAttributes)) return void 0;
40141
40558
  const relativeHeight = originalAttributes.relativeHeight;
40142
40559
  if (typeof relativeHeight !== "number") return void 0;
40143
40560
  return Math.max(0, relativeHeight - OOXML_Z_INDEX_BASE);
@@ -41331,321 +41748,6 @@ const ensureBidiIndentPx = (indent) => {
41331
41748
  }
41332
41749
  return adjusted;
41333
41750
  };
41334
- const sdtMetadataCache = /* @__PURE__ */ new Map();
41335
- function resolveStyle(node, context, options = {}) {
41336
- let paragraph = createDefaultParagraph();
41337
- let character = createDefaultCharacter(context);
41338
- let numbering;
41339
- const chain = resolveStyleChain(node.styleId, context.styles);
41340
- for (const style2 of chain) {
41341
- paragraph = mergeParagraph(paragraph, style2.paragraph);
41342
- character = mergeCharacter(character, style2.character);
41343
- if (!numbering && style2.numbering) {
41344
- numbering = resolveNumbering(style2.numbering.numId, style2.numbering.level, context);
41345
- }
41346
- }
41347
- paragraph = mergeParagraph(paragraph, node.paragraphProps);
41348
- character = mergeCharacter(character, node.characterProps);
41349
- if (node.numbering) {
41350
- numbering = resolveNumbering(node.numbering.numId, node.numbering.level, context);
41351
- }
41352
- const sdt = options?.sdt ? resolveSdtMetadata(options.sdt) : void 0;
41353
- return {
41354
- paragraph,
41355
- character,
41356
- numbering,
41357
- sdt
41358
- };
41359
- }
41360
- function resolveNumbering(numId, level, context) {
41361
- const def = context.numbering?.[numId];
41362
- if (!def) return void 0;
41363
- const levelDef = def.levels.find((entry) => entry.level === level) ?? def.levels[level];
41364
- if (!levelDef) return void 0;
41365
- return {
41366
- numId,
41367
- level,
41368
- indent: {
41369
- left: levelDef.indent?.left,
41370
- hanging: levelDef.indent?.hanging
41371
- },
41372
- format: levelDef.format ?? "decimal",
41373
- text: levelDef.text ?? "%1.",
41374
- start: levelDef.start ?? 1
41375
- };
41376
- }
41377
- function resolveSdtMetadata(input) {
41378
- if (!input) return void 0;
41379
- const { nodeType, attrs, cacheKey: explicitKey } = input;
41380
- if (!nodeType) return void 0;
41381
- const normalizedAttrs = isPlainObject$2(attrs) ? attrs : {};
41382
- const cacheKey = buildSdtCacheKey(nodeType, normalizedAttrs, explicitKey);
41383
- if (cacheKey && sdtMetadataCache.has(cacheKey)) {
41384
- return sdtMetadataCache.get(cacheKey);
41385
- }
41386
- let metadata;
41387
- switch (nodeType) {
41388
- case "fieldAnnotation":
41389
- metadata = normalizeFieldAnnotationMetadata(normalizedAttrs);
41390
- break;
41391
- case "structuredContent":
41392
- case "structuredContentBlock":
41393
- metadata = normalizeStructuredContentMetadata(nodeType, normalizedAttrs);
41394
- break;
41395
- case "documentSection":
41396
- metadata = normalizeDocumentSectionMetadata(normalizedAttrs);
41397
- break;
41398
- case "docPartObject":
41399
- metadata = normalizeDocPartMetadata(normalizedAttrs);
41400
- break;
41401
- }
41402
- if (metadata && cacheKey) {
41403
- sdtMetadataCache.set(cacheKey, metadata);
41404
- }
41405
- return metadata;
41406
- }
41407
- function createDefaultParagraph(_context) {
41408
- return {
41409
- alignment: "left",
41410
- spacing: {
41411
- before: 0,
41412
- after: 0,
41413
- line: 12,
41414
- lineRule: "auto"
41415
- },
41416
- indent: {
41417
- left: 0,
41418
- right: 0,
41419
- firstLine: 0,
41420
- hanging: 0
41421
- },
41422
- tabs: []
41423
- };
41424
- }
41425
- function createDefaultCharacter(context) {
41426
- const baseFont = context.defaults?.paragraphFont ?? "Calibri";
41427
- const fallback = context.defaults?.paragraphFontFallback;
41428
- const wordFamily = context.defaults?.paragraphFontFamily;
41429
- const resolvedFamily = toCssFontFamily(baseFont, { fallback, wordFamily }) ?? baseFont;
41430
- return {
41431
- font: {
41432
- family: resolvedFamily,
41433
- size: context.defaults?.fontSize ?? 11,
41434
- weight: 400,
41435
- italic: false
41436
- },
41437
- color: "#000000"
41438
- };
41439
- }
41440
- function resolveStyleChain(styleId, styles) {
41441
- if (!styleId || !styles) return [];
41442
- const result = [];
41443
- const visited = /* @__PURE__ */ new Set();
41444
- let current = styles[styleId];
41445
- while (current && !visited.has(current.id)) {
41446
- result.unshift(current);
41447
- visited.add(current.id);
41448
- current = current.basedOn ? styles[current.basedOn] : void 0;
41449
- }
41450
- return result;
41451
- }
41452
- function mergeParagraph(base2, overrides) {
41453
- if (!overrides) return base2;
41454
- return {
41455
- ...base2,
41456
- alignment: overrides.alignment ?? base2.alignment,
41457
- spacing: overrides.spacing ? { ...base2.spacing, ...overrides.spacing } : base2.spacing,
41458
- indent: overrides.indent ? { ...base2.indent, ...overrides.indent } : base2.indent,
41459
- borders: overrides.borders ? { ...base2.borders, ...overrides.borders } : base2.borders,
41460
- shading: overrides.shading ?? base2.shading,
41461
- tabs: overrides.tabs ?? base2.tabs
41462
- };
41463
- }
41464
- function mergeCharacter(base2, overrides) {
41465
- if (!overrides) return base2;
41466
- return {
41467
- ...base2,
41468
- font: overrides.font ? { ...base2.font, ...overrides.font } : base2.font,
41469
- color: overrides.color ?? base2.color,
41470
- underline: overrides.underline ?? base2.underline,
41471
- strike: overrides.strike ?? base2.strike,
41472
- highlight: overrides.highlight ?? base2.highlight,
41473
- letterSpacing: overrides.letterSpacing ?? base2.letterSpacing
41474
- };
41475
- }
41476
- function normalizeFieldAnnotationMetadata(attrs) {
41477
- const fieldId = toOptionalString(attrs.fieldId) ?? "";
41478
- const formatting = extractFormatting(attrs);
41479
- const size2 = normalizeSize(attrs.size);
41480
- const extras = isPlainObject$2(attrs.extras) ? attrs.extras : null;
41481
- const marks = isPlainObject$2(attrs.marks) ? attrs.marks : void 0;
41482
- return {
41483
- type: "fieldAnnotation",
41484
- fieldId,
41485
- variant: normalizeFieldAnnotationVariant(attrs.type),
41486
- fieldType: toOptionalString(attrs.fieldType),
41487
- displayLabel: toOptionalString(attrs.displayLabel),
41488
- defaultDisplayLabel: toOptionalString(attrs.defaultDisplayLabel),
41489
- alias: toOptionalString(attrs.alias),
41490
- fieldColor: normalizeColorValue(attrs.fieldColor),
41491
- borderColor: normalizeColorValue(attrs.borderColor),
41492
- highlighted: toBoolean$2(attrs.highlighted, true),
41493
- fontFamily: toNullableString(attrs.fontFamily),
41494
- fontSize: normalizeFontSize(attrs.fontSize),
41495
- textColor: normalizeColorValue(attrs.textColor) ?? null,
41496
- textHighlight: normalizeColorValue(attrs.textHighlight) ?? null,
41497
- linkUrl: toNullableString(attrs.linkUrl),
41498
- imageSrc: toNullableString(attrs.imageSrc),
41499
- rawHtml: attrs.rawHtml ?? void 0,
41500
- size: size2 ?? null,
41501
- extras,
41502
- multipleImage: toBoolean$2(attrs.multipleImage, false),
41503
- hash: toOptionalString(attrs.hash) ?? null,
41504
- generatorIndex: toNumber(attrs.generatorIndex),
41505
- sdtId: toOptionalString(attrs.sdtId) ?? null,
41506
- hidden: toBoolean$2(attrs.hidden, false),
41507
- visibility: normalizeVisibility(attrs.visibility),
41508
- isLocked: toBoolean$2(attrs.isLocked, false),
41509
- formatting,
41510
- marks
41511
- };
41512
- }
41513
- function normalizeStructuredContentMetadata(nodeType, attrs) {
41514
- return {
41515
- type: "structuredContent",
41516
- scope: nodeType === "structuredContentBlock" ? "block" : "inline",
41517
- id: toNullableString(attrs.id),
41518
- tag: toOptionalString(attrs.tag),
41519
- alias: toOptionalString(attrs.alias),
41520
- sdtPr: attrs.sdtPr
41521
- };
41522
- }
41523
- function normalizeDocumentSectionMetadata(attrs) {
41524
- return {
41525
- type: "documentSection",
41526
- id: toNullableString(attrs.id),
41527
- title: toOptionalString(attrs.title) ?? null,
41528
- description: toOptionalString(attrs.description) ?? null,
41529
- sectionType: toOptionalString(attrs.sectionType) ?? null,
41530
- isLocked: toBoolean$2(attrs.isLocked, false),
41531
- sdBlockId: toNullableString(attrs.sdBlockId)
41532
- };
41533
- }
41534
- function normalizeDocPartMetadata(attrs) {
41535
- return {
41536
- type: "docPartObject",
41537
- gallery: toOptionalString(attrs.docPartGallery ?? attrs.gallery) ?? null,
41538
- // Source uniqueId from attrs.id (PM adapter uses getDocPartObjectId which extracts attrs.id)
41539
- // Fall back to attrs.uniqueId for compatibility
41540
- uniqueId: toOptionalString(attrs.id ?? attrs.uniqueId) ?? null,
41541
- alias: toOptionalString(attrs.alias) ?? null,
41542
- instruction: toOptionalString(attrs.instruction) ?? null
41543
- };
41544
- }
41545
- function isPlainObject$2(value) {
41546
- return !!value && typeof value === "object" && !Array.isArray(value);
41547
- }
41548
- function toOptionalString(value) {
41549
- if (value == null) return void 0;
41550
- if (typeof value === "string") {
41551
- const trimmed = value.trim();
41552
- return trimmed.length ? trimmed : void 0;
41553
- }
41554
- return String(value);
41555
- }
41556
- function toNullableString(value) {
41557
- const str = toOptionalString(value);
41558
- return str ?? null;
41559
- }
41560
- function toBoolean$2(value, fallback) {
41561
- if (typeof value === "boolean") return value;
41562
- if (typeof value === "string") {
41563
- const lower = value.toLowerCase();
41564
- if (lower === "true") return true;
41565
- if (lower === "false") return false;
41566
- }
41567
- if (value == null) return fallback;
41568
- return Boolean(value);
41569
- }
41570
- function normalizeVisibility(value) {
41571
- if (typeof value !== "string") return void 0;
41572
- const normalized = value.toLowerCase();
41573
- if (normalized === "visible" || normalized === "hidden") {
41574
- return normalized;
41575
- }
41576
- return void 0;
41577
- }
41578
- function normalizeColorValue(value) {
41579
- if (typeof value !== "string") return void 0;
41580
- const trimmed = value.trim();
41581
- if (!trimmed || trimmed.toLowerCase() === "none") return void 0;
41582
- return trimmed;
41583
- }
41584
- function normalizeFontSize(value) {
41585
- if (value == null) return null;
41586
- if (typeof value === "number") {
41587
- return Number.isFinite(value) ? value : null;
41588
- }
41589
- if (typeof value === "string") {
41590
- const trimmed = value.trim();
41591
- return trimmed.length ? trimmed : null;
41592
- }
41593
- return null;
41594
- }
41595
- function toNumber(value) {
41596
- if (typeof value === "number") {
41597
- return Number.isFinite(value) ? value : null;
41598
- }
41599
- if (typeof value === "string") {
41600
- const parsed = parseFloat(value);
41601
- return Number.isFinite(parsed) ? parsed : null;
41602
- }
41603
- return null;
41604
- }
41605
- function normalizeSize(value) {
41606
- if (!isPlainObject$2(value)) return null;
41607
- const obj = value;
41608
- const width = toNumber(obj.width);
41609
- const height = toNumber(obj.height);
41610
- if (width == null && height == null) return null;
41611
- const result = {};
41612
- if (width != null) result.width = width;
41613
- if (height != null) result.height = height;
41614
- return result;
41615
- }
41616
- function normalizeFieldAnnotationVariant(value) {
41617
- if (typeof value !== "string") return void 0;
41618
- const normalized = value.toLowerCase();
41619
- if (normalized === "text" || normalized === "image" || normalized === "signature" || normalized === "checkbox" || normalized === "html" || normalized === "link") {
41620
- return normalized;
41621
- }
41622
- return void 0;
41623
- }
41624
- function extractFormatting(attrs) {
41625
- const bold = toBoolean$2(attrs.bold, false);
41626
- const italic = toBoolean$2(attrs.italic, false);
41627
- const underline = toBoolean$2(attrs.underline, false);
41628
- const formatting = {};
41629
- if (bold) formatting.bold = true;
41630
- if (italic) formatting.italic = true;
41631
- if (underline) formatting.underline = true;
41632
- return Object.keys(formatting).length ? formatting : void 0;
41633
- }
41634
- function buildSdtCacheKey(nodeType, attrs, explicitKey) {
41635
- const provided = toOptionalString(explicitKey);
41636
- if (provided) {
41637
- return `${nodeType}:${provided}`;
41638
- }
41639
- const hash2 = toOptionalString(attrs.hash);
41640
- if (hash2) {
41641
- return `${nodeType}:${hash2}`;
41642
- }
41643
- const id = toOptionalString(attrs.id);
41644
- if (id) {
41645
- return `${nodeType}:${id}`;
41646
- }
41647
- return void 0;
41648
- }
41649
41751
  const DEFAULT_LIST_HANGING_PX = 18;
41650
41752
  const LIST_MARKER_GAP = 8;
41651
41753
  const DEFAULT_BULLET_GLYPH = "•";
@@ -42205,6 +42307,7 @@ const EMPTY_NUMBERING_CONTEXT = {
42205
42307
  definitions: {},
42206
42308
  abstracts: {}
42207
42309
  };
42310
+ const ooxmlResolver = superEditor_converter.createOoxmlResolver({ pPr: superEditor_converter.translator, rPr: superEditor_converter.translator$1 });
42208
42311
  const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
42209
42312
  if (!hasParagraphStyleContext(context)) {
42210
42313
  return null;
@@ -42232,7 +42335,7 @@ const hydrateParagraphStyleAttrs = (para, context, preResolved) => {
42232
42335
  // should still get docDefaults spacing from style resolution
42233
42336
  numbering: context.numbering ?? EMPTY_NUMBERING_CONTEXT
42234
42337
  };
42235
- const resolved = superEditor_converter.resolveParagraphProperties(resolverParams, inlineProps);
42338
+ const resolved = ooxmlResolver.resolveParagraphProperties(resolverParams, inlineProps);
42236
42339
  if (!resolved) {
42237
42340
  return null;
42238
42341
  }
@@ -42287,6 +42390,138 @@ const cloneIfObject = (value) => {
42287
42390
  }
42288
42391
  return { ...value };
42289
42392
  };
42393
+ const buildCharacterStyleHydration = (resolved, docx) => {
42394
+ const fontFamily2 = extractFontFamily(resolved.fontFamily, docx);
42395
+ const fontSize2 = typeof resolved.fontSize === "number" ? resolved.fontSize : 20;
42396
+ const color = extractColorValue(resolved.color);
42397
+ const bold = normalizeBooleanProp(resolved.bold);
42398
+ const italic = normalizeBooleanProp(resolved.italic);
42399
+ const strike = normalizeBooleanProp(resolved.strike);
42400
+ const underline = extractUnderline(resolved.underline);
42401
+ const letterSpacing = typeof resolved.letterSpacing === "number" ? resolved.letterSpacing : void 0;
42402
+ return {
42403
+ fontFamily: fontFamily2,
42404
+ fontSize: fontSize2,
42405
+ color,
42406
+ bold,
42407
+ italic,
42408
+ strike,
42409
+ underline,
42410
+ letterSpacing
42411
+ };
42412
+ };
42413
+ const hydrateCharacterStyleAttrs = (para, context, resolvedPpr) => {
42414
+ if (!hasParagraphStyleContext(context)) {
42415
+ return null;
42416
+ }
42417
+ const attrs = para.attrs ?? {};
42418
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
42419
+ const styleIdSource = attrs.styleId ?? paragraphProps.styleId;
42420
+ const styleId = typeof styleIdSource === "string" && styleIdSource.trim() ? styleIdSource : null;
42421
+ const inlineRpr = {};
42422
+ const pprForChain = resolvedPpr ?? { styleId };
42423
+ const numberingProps = attrs.numberingProperties ?? paragraphProps.numberingProperties;
42424
+ if (numberingProps != null) {
42425
+ pprForChain.numberingProperties = numberingProps;
42426
+ }
42427
+ const resolverParams = {
42428
+ docx: context.docx,
42429
+ numbering: context.numbering ?? EMPTY_NUMBERING_CONTEXT
42430
+ };
42431
+ let resolved = null;
42432
+ try {
42433
+ resolved = ooxmlResolver.resolveRunProperties(
42434
+ resolverParams,
42435
+ inlineRpr,
42436
+ pprForChain,
42437
+ false,
42438
+ // not list number marker
42439
+ false
42440
+ // not numberingDefinedInline
42441
+ );
42442
+ if (!resolved || typeof resolved !== "object") {
42443
+ return null;
42444
+ }
42445
+ } catch {
42446
+ return null;
42447
+ }
42448
+ return buildCharacterStyleHydration(resolved, context.docx);
42449
+ };
42450
+ const hydrateMarkerStyleAttrs = (para, context, resolvedPpr) => {
42451
+ if (!hasParagraphStyleContext(context)) {
42452
+ return null;
42453
+ }
42454
+ const attrs = para.attrs ?? {};
42455
+ const paragraphProps = typeof attrs.paragraphProperties === "object" && attrs.paragraphProperties !== null ? attrs.paragraphProperties : {};
42456
+ const styleIdSource = attrs.styleId ?? paragraphProps.styleId;
42457
+ const styleId = typeof styleIdSource === "string" && styleIdSource.trim() ? styleIdSource : null;
42458
+ const inlineRpr = {};
42459
+ const numberingProps = attrs.numberingProperties ?? paragraphProps.numberingProperties;
42460
+ const numberingDefinedInline = numberingProps?.numId != null;
42461
+ const pprForChain = resolvedPpr ? { ...resolvedPpr } : { styleId };
42462
+ if (styleId && !pprForChain.styleId) {
42463
+ pprForChain.styleId = styleId;
42464
+ }
42465
+ if (numberingProps != null) {
42466
+ pprForChain.numberingProperties = numberingProps;
42467
+ }
42468
+ const resolverParams = {
42469
+ docx: context.docx,
42470
+ numbering: context.numbering ?? EMPTY_NUMBERING_CONTEXT
42471
+ };
42472
+ let resolved = null;
42473
+ try {
42474
+ resolved = ooxmlResolver.resolveRunProperties(
42475
+ resolverParams,
42476
+ inlineRpr,
42477
+ pprForChain,
42478
+ true,
42479
+ numberingDefinedInline
42480
+ );
42481
+ if (!resolved || typeof resolved !== "object") {
42482
+ return null;
42483
+ }
42484
+ } catch {
42485
+ return null;
42486
+ }
42487
+ return buildCharacterStyleHydration(resolved, context.docx);
42488
+ };
42489
+ function extractFontFamily(fontFamily2, docx) {
42490
+ if (!fontFamily2 || typeof fontFamily2 !== "object") return void 0;
42491
+ const toCssFontFamily2 = superEditor_converter.SuperConverter.toCssFontFamily;
42492
+ const resolved = superEditor_converter.resolveDocxFontFamily(fontFamily2, docx ?? null, toCssFontFamily2);
42493
+ return resolved ?? void 0;
42494
+ }
42495
+ function extractColorValue(color) {
42496
+ if (!color || typeof color !== "object") return void 0;
42497
+ const c2 = color;
42498
+ const val = c2.val;
42499
+ if (typeof val !== "string") return void 0;
42500
+ if (!val || val.toLowerCase() === "auto") return void 0;
42501
+ return val;
42502
+ }
42503
+ function normalizeBooleanProp(value) {
42504
+ if (value == null) return void 0;
42505
+ if (typeof value === "boolean") return value;
42506
+ if (typeof value === "number") return value !== 0;
42507
+ if (typeof value === "string") {
42508
+ const lower = value.toLowerCase();
42509
+ if (lower === "0" || lower === "false" || lower === "off") return false;
42510
+ if (lower === "1" || lower === "true" || lower === "on" || lower === "") return true;
42511
+ }
42512
+ return Boolean(value);
42513
+ }
42514
+ function extractUnderline(underline) {
42515
+ if (!underline || typeof underline !== "object") return void 0;
42516
+ const u = underline;
42517
+ const type = u["w:val"] ?? u.type ?? u.val;
42518
+ if (typeof type !== "string" || type === "none") return void 0;
42519
+ const color = u["w:color"] ?? u.color;
42520
+ return {
42521
+ type,
42522
+ color: typeof color === "string" ? color : void 0
42523
+ };
42524
+ }
42290
42525
  const { resolveSpacingIndent } = Engines;
42291
42526
  const DEFAULT_DECIMAL_SEPARATOR$2 = ".";
42292
42527
  const isValidNumberingId = (numId) => {
@@ -42802,7 +43037,7 @@ const extractDropCapRunFromParagraph = (para) => {
42802
43037
  }
42803
43038
  return dropCapRun;
42804
43039
  };
42805
- const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, _paragraphNode) => {
43040
+ const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleContext, paragraphNode, converterContext, resolvedPpr) => {
42806
43041
  if (numberingProps === null) {
42807
43042
  return null;
42808
43043
  }
@@ -42840,7 +43075,23 @@ const computeWordLayoutForParagraph = (paragraphAttrs, numberingProps, styleCont
42840
43075
  spacing: {}
42841
43076
  }
42842
43077
  };
42843
- let markerRun = numberingProps?.resolvedMarkerRpr;
43078
+ let markerRun;
43079
+ const markerHydration = paragraphNode && converterContext ? hydrateMarkerStyleAttrs(paragraphNode, converterContext, resolvedPpr) : null;
43080
+ if (markerHydration) {
43081
+ const resolvedColor = markerHydration.color ? `#${markerHydration.color.replace("#", "")}` : void 0;
43082
+ markerRun = {
43083
+ fontFamily: markerHydration.fontFamily ?? "Times New Roman",
43084
+ fontSize: markerHydration.fontSize / 2,
43085
+ // half-points to points
43086
+ bold: markerHydration.bold,
43087
+ italic: markerHydration.italic,
43088
+ color: resolvedColor,
43089
+ letterSpacing: markerHydration.letterSpacing != null ? twipsToPx$1(markerHydration.letterSpacing) : void 0
43090
+ };
43091
+ }
43092
+ if (!markerRun) {
43093
+ markerRun = numberingProps?.resolvedMarkerRpr;
43094
+ }
42844
43095
  if (!markerRun) {
42845
43096
  const { character: characterStyle } = resolveStyle({ styleId: paragraphAttrs.styleId }, styleContext);
42846
43097
  if (characterStyle) {
@@ -42909,8 +43160,11 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
42909
43160
  const hydrated = hydrationOverride ?? hydrateParagraphStyleAttrs(para, converterContext);
42910
43161
  const mergedSpacing = mergeSpacingSources(hydrated?.spacing, paragraphProps.spacing, attrs.spacing);
42911
43162
  const normalizedSpacing = normalizeParagraphSpacing(mergedSpacing);
42912
- const indentSource = attrs.indent ?? paragraphProps.indent ?? hydrated?.indent;
42913
- const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? attrs.textIndent);
43163
+ const normalizeIndentObject = (value) => {
43164
+ if (!value || typeof value !== "object") return;
43165
+ return normalizePxIndent(value) ?? convertIndentTwipsToPx(value);
43166
+ };
43167
+ const normalizedIndent = normalizeIndentObject(attrs.indent) ?? convertIndentTwipsToPx(paragraphProps.indent) ?? convertIndentTwipsToPx(hydrated?.indent) ?? normalizeParagraphIndent(attrs.textIndent);
42914
43168
  const unwrapTabStops = (tabStops) => {
42915
43169
  if (!Array.isArray(tabStops)) {
42916
43170
  return void 0;
@@ -43161,7 +43415,12 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
43161
43415
  const numId = numberingProps.numId;
43162
43416
  const ilvl = Number.isFinite(numberingProps.ilvl) ? Math.max(0, Math.floor(Number(numberingProps.ilvl))) : 0;
43163
43417
  const numericNumId = typeof numId === "number" ? numId : void 0;
43164
- const resolvedLevel = resolveNumberingFromContext(numId, ilvl, converterContext?.numbering);
43418
+ let resolvedLevel;
43419
+ try {
43420
+ resolvedLevel = resolveNumberingFromContext(numId, ilvl, converterContext?.numbering);
43421
+ } catch (error) {
43422
+ resolvedLevel = void 0;
43423
+ }
43165
43424
  if (resolvedLevel) {
43166
43425
  if (resolvedLevel.format && numberingProps.format == null) {
43167
43426
  numberingProps.format = resolvedLevel.format;
@@ -43222,7 +43481,19 @@ const computeParagraphAttrs = (para, styleContext, listCounterContext, converter
43222
43481
  }
43223
43482
  }
43224
43483
  }
43225
- let wordLayout = computeWordLayoutForParagraph(paragraphAttrs, enrichedNumberingProps, styleContext);
43484
+ let wordLayout = null;
43485
+ try {
43486
+ wordLayout = computeWordLayoutForParagraph(
43487
+ paragraphAttrs,
43488
+ enrichedNumberingProps,
43489
+ styleContext,
43490
+ para,
43491
+ converterContext,
43492
+ hydrated?.resolved
43493
+ );
43494
+ } catch (error) {
43495
+ wordLayout = null;
43496
+ }
43226
43497
  if (!wordLayout && enrichedNumberingProps.resolvedLevelIndent) {
43227
43498
  const resolvedIndentPx = convertIndentTwipsToPx(enrichedNumberingProps.resolvedLevelIndent);
43228
43499
  const baseIndent = resolvedIndentPx ?? enrichedNumberingProps.resolvedLevelIndent;
@@ -43767,7 +44038,7 @@ const V_RELATIVE_VALUES$1 = /* @__PURE__ */ new Set(["paragraph", "page", "margi
43767
44038
  const H_ALIGN_VALUES$1 = /* @__PURE__ */ new Set(["left", "center", "right"]);
43768
44039
  const V_ALIGN_VALUES$1 = /* @__PURE__ */ new Set(["top", "center", "bottom"]);
43769
44040
  const getAttrs$1 = (node) => {
43770
- return isPlainObject$3(node.attrs) ? node.attrs : {};
44041
+ return isPlainObject$2(node.attrs) ? node.attrs : {};
43771
44042
  };
43772
44043
  const normalizeWrapType$1 = (value) => {
43773
44044
  if (typeof value !== "string") return void 0;
@@ -43790,7 +44061,7 @@ const normalizePolygon$1 = (value) => {
43790
44061
  return polygon.length > 0 ? polygon : void 0;
43791
44062
  };
43792
44063
  const normalizeWrap$2 = (value) => {
43793
- if (!isPlainObject$3(value)) {
44064
+ if (!isPlainObject$2(value)) {
43794
44065
  return void 0;
43795
44066
  }
43796
44067
  const type = normalizeWrapType$1(value.type);
@@ -43798,7 +44069,7 @@ const normalizeWrap$2 = (value) => {
43798
44069
  return void 0;
43799
44070
  }
43800
44071
  const wrap = { type };
43801
- const attrs = isPlainObject$3(value.attrs) ? value.attrs : {};
44072
+ const attrs = isPlainObject$2(value.attrs) ? value.attrs : {};
43802
44073
  const wrapText = normalizeWrapText$1(attrs.wrapText);
43803
44074
  if (wrapText) {
43804
44075
  wrap.wrapText = wrapText;
@@ -43815,7 +44086,7 @@ const normalizeWrap$2 = (value) => {
43815
44086
  if (polygon) {
43816
44087
  wrap.polygon = polygon;
43817
44088
  }
43818
- const behindDoc = toBoolean$3(attrs.behindDoc);
44089
+ const behindDoc = toBoolean$2(attrs.behindDoc);
43819
44090
  if (behindDoc != null) {
43820
44091
  wrap.behindDoc = behindDoc;
43821
44092
  }
@@ -43830,10 +44101,10 @@ const normalizeAnchorAlign$1 = (value, allowed) => {
43830
44101
  return allowed.has(value) ? value : void 0;
43831
44102
  };
43832
44103
  const normalizeAnchorData$1 = (value, attrs, wrapBehindDoc) => {
43833
- const raw = isPlainObject$3(value) ? value : void 0;
43834
- const marginOffset = isPlainObject$3(attrs.marginOffset) ? attrs.marginOffset : void 0;
43835
- const simplePos = isPlainObject$3(attrs.simplePos) ? attrs.simplePos : void 0;
43836
- const originalAttrs = isPlainObject$3(attrs.originalAttributes) ? attrs.originalAttributes : void 0;
44104
+ const raw = isPlainObject$2(value) ? value : void 0;
44105
+ const marginOffset = isPlainObject$2(attrs.marginOffset) ? attrs.marginOffset : void 0;
44106
+ const simplePos = isPlainObject$2(attrs.simplePos) ? attrs.simplePos : void 0;
44107
+ const originalAttrs = isPlainObject$2(attrs.originalAttributes) ? attrs.originalAttributes : void 0;
43837
44108
  const isAnchored = attrs.isAnchor === true || Boolean(raw);
43838
44109
  const anchor = {};
43839
44110
  if (isAnchored) {
@@ -43851,7 +44122,7 @@ const normalizeAnchorData$1 = (value, attrs, wrapBehindDoc) => {
43851
44122
  if (offsetH != null) anchor.offsetH = offsetH;
43852
44123
  const offsetV = pickNumber(marginOffset?.top ?? marginOffset?.vertical ?? raw?.offsetV ?? simplePos?.y);
43853
44124
  if (offsetV != null) anchor.offsetV = offsetV;
43854
- const behindDoc = toBoolean$3(raw?.behindDoc ?? wrapBehindDoc ?? originalAttrs?.behindDoc);
44125
+ const behindDoc = toBoolean$2(raw?.behindDoc ?? wrapBehindDoc ?? originalAttrs?.behindDoc);
43855
44126
  if (behindDoc != null) anchor.behindDoc = behindDoc;
43856
44127
  const hasData = anchor.isAnchored || anchor.hRelativeFrom != null || anchor.vRelativeFrom != null || anchor.alignH != null || anchor.alignV != null || anchor.offsetH != null || anchor.offsetV != null || anchor.behindDoc != null;
43857
44128
  return hasData ? anchor : void 0;
@@ -43976,7 +44247,7 @@ function handleShapeTextboxNode(node, context) {
43976
44247
  }
43977
44248
  }
43978
44249
  const getAttrs = (node) => {
43979
- return isPlainObject$3(node.attrs) ? { ...node.attrs } : {};
44250
+ return isPlainObject$2(node.attrs) ? { ...node.attrs } : {};
43980
44251
  };
43981
44252
  const parseFullWidth = (value) => {
43982
44253
  if (typeof value === "string") {
@@ -43995,7 +44266,7 @@ function contentBlockNodeToDrawingBlock(node, nextBlockId, positions) {
43995
44266
  if (rawAttrs.horizontalRule !== true) {
43996
44267
  return null;
43997
44268
  }
43998
- const size2 = isPlainObject$3(rawAttrs.size) ? rawAttrs.size : void 0;
44269
+ const size2 = isPlainObject$2(rawAttrs.size) ? rawAttrs.size : void 0;
43999
44270
  const { width, isFullWidth } = parseFullWidth(size2?.width);
44000
44271
  const height = pickNumber(size2?.height);
44001
44272
  if (!height || height <= 0) {
@@ -44197,6 +44468,9 @@ const extractRunStyleId = (runProperties) => {
44197
44468
  return null;
44198
44469
  };
44199
44470
  const DEFAULT_IMAGE_DIMENSION_PX = 100;
44471
+ const HALF_POINTS_PER_POINT = 2;
44472
+ const SCREEN_DPI = 96;
44473
+ const POINT_DPI = 72;
44200
44474
  function isInlineImage(node) {
44201
44475
  const attrs = node.attrs ?? {};
44202
44476
  const wrap = attrs.wrap;
@@ -44224,8 +44498,8 @@ function imageNodeToRun(node, positions, activeSdt) {
44224
44498
  const size2 = attrs.size ?? {};
44225
44499
  const width = typeof size2.width === "number" && Number.isFinite(size2.width) && size2.width > 0 ? size2.width : DEFAULT_IMAGE_DIMENSION_PX;
44226
44500
  const height = typeof size2.height === "number" && Number.isFinite(size2.height) && size2.height > 0 ? size2.height : DEFAULT_IMAGE_DIMENSION_PX;
44227
- const wrap = isPlainObject$3(attrs.wrap) ? attrs.wrap : {};
44228
- const wrapAttrs = isPlainObject$3(wrap.attrs) ? wrap.attrs : {};
44501
+ const wrap = isPlainObject$2(attrs.wrap) ? attrs.wrap : {};
44502
+ const wrapAttrs = isPlainObject$2(wrap.attrs) ? wrap.attrs : {};
44229
44503
  const run = {
44230
44504
  kind: "image",
44231
44505
  src,
@@ -44435,15 +44709,6 @@ const applyBaseRunDefaults = (run, defaults, uiDisplayFallbackFont, fallbackSize
44435
44709
  if (defaults.letterSpacing != null && run.letterSpacing == null) {
44436
44710
  run.letterSpacing = defaults.letterSpacing;
44437
44711
  }
44438
- if (defaults.bold && run.bold === void 0) {
44439
- run.bold = true;
44440
- }
44441
- if (defaults.italic && run.italic === void 0) {
44442
- run.italic = true;
44443
- }
44444
- if (defaults.underline && !run.underline) {
44445
- run.underline = defaults.underline;
44446
- }
44447
44712
  };
44448
44713
  function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defaultSize, styleContext, listCounterContext, trackedChanges, bookmarks, hyperlinkConfig = DEFAULT_HYPERLINK_CONFIG$1, themeColors, converters, converterContext) {
44449
44714
  const baseBlockId = nextBlockId("paragraph");
@@ -44452,28 +44717,48 @@ function paragraphToFlowBlocks$1(para, nextBlockId, positions, defaultFont, defa
44452
44717
  const paragraphHydration = converterContext ? hydrateParagraphStyleAttrs(para, converterContext) : null;
44453
44718
  let baseRunDefaults = {};
44454
44719
  try {
44455
- const spacingSource = para.attrs?.spacing !== void 0 ? para.attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : paragraphHydration?.spacing;
44456
- const indentSource = para.attrs?.indent ?? paragraphProps.indent ?? paragraphHydration?.indent;
44457
- const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
44458
- const normalizedIndent = normalizePxIndent(indentSource) ?? normalizeParagraphIndent(indentSource ?? para.attrs?.textIndent);
44459
- const styleNodeAttrs = paragraphHydration?.tabStops && !para.attrs?.tabStops && !para.attrs?.tabs ? { ...para.attrs ?? {}, tabStops: paragraphHydration.tabStops } : para.attrs ?? {};
44460
- const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
44461
- if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
44462
- styleNode.styleId = paragraphProps.styleId;
44463
- }
44464
- const resolved = resolveStyle(styleNode, styleContext);
44465
- baseRunDefaults = {
44466
- fontFamily: resolved.character.font?.family,
44467
- fontSizePx: ptToPx(resolved.character.font?.size),
44468
- color: resolved.character.color,
44469
- bold: resolved.character.font?.weight != null ? resolved.character.font.weight >= 600 : void 0,
44470
- italic: resolved.character.font?.italic,
44471
- underline: resolved.character.underline ? {
44472
- style: resolved.character.underline.style,
44473
- color: resolved.character.underline.color
44474
- } : void 0,
44475
- letterSpacing: ptToPx(resolved.character.letterSpacing)
44476
- };
44720
+ const charHydration = converterContext ? hydrateCharacterStyleAttrs(para, converterContext, paragraphHydration?.resolved) : null;
44721
+ if (charHydration) {
44722
+ const fontSizePx = charHydration.fontSize / HALF_POINTS_PER_POINT * (SCREEN_DPI / POINT_DPI);
44723
+ baseRunDefaults = {
44724
+ fontFamily: charHydration.fontFamily,
44725
+ fontSizePx,
44726
+ color: charHydration.color ? `#${charHydration.color.replace("#", "")}` : void 0,
44727
+ bold: charHydration.bold,
44728
+ italic: charHydration.italic,
44729
+ underline: charHydration.underline ? {
44730
+ style: charHydration.underline.type,
44731
+ color: charHydration.underline.color
44732
+ } : void 0,
44733
+ letterSpacing: charHydration.letterSpacing != null ? twipsToPx$1(charHydration.letterSpacing) : void 0
44734
+ };
44735
+ } else {
44736
+ const spacingSource = para.attrs?.spacing !== void 0 ? para.attrs.spacing : paragraphProps.spacing !== void 0 ? paragraphProps.spacing : paragraphHydration?.spacing;
44737
+ const normalizeIndentObject = (value) => {
44738
+ if (!value || typeof value !== "object") return;
44739
+ return normalizePxIndent(value) ?? convertIndentTwipsToPx$1(value);
44740
+ };
44741
+ const normalizedSpacing = normalizeParagraphSpacing(spacingSource);
44742
+ const normalizedIndent = normalizeIndentObject(para.attrs?.indent) ?? convertIndentTwipsToPx$1(paragraphProps.indent) ?? convertIndentTwipsToPx$1(paragraphHydration?.indent) ?? normalizeParagraphIndent(para.attrs?.textIndent);
44743
+ const styleNodeAttrs = paragraphHydration?.tabStops && !para.attrs?.tabStops && !para.attrs?.tabs ? { ...para.attrs ?? {}, tabStops: paragraphHydration.tabStops } : para.attrs ?? {};
44744
+ const styleNode = buildStyleNodeFromAttrs(styleNodeAttrs, normalizedSpacing, normalizedIndent);
44745
+ if (styleNodeAttrs.styleId == null && paragraphProps.styleId) {
44746
+ styleNode.styleId = paragraphProps.styleId;
44747
+ }
44748
+ const resolved = resolveStyle(styleNode, styleContext);
44749
+ baseRunDefaults = {
44750
+ fontFamily: resolved.character.font?.family,
44751
+ fontSizePx: ptToPx(resolved.character.font?.size),
44752
+ color: resolved.character.color,
44753
+ bold: resolved.character.font?.weight != null ? resolved.character.font.weight >= 600 : void 0,
44754
+ italic: resolved.character.font?.italic,
44755
+ underline: resolved.character.underline ? {
44756
+ style: resolved.character.underline.style,
44757
+ color: resolved.character.underline.color
44758
+ } : void 0,
44759
+ letterSpacing: ptToPx(resolved.character.letterSpacing)
44760
+ };
44761
+ }
44477
44762
  } catch {
44478
44763
  baseRunDefaults = {};
44479
44764
  }
@@ -46175,6 +46460,9 @@ const createHeaderFooterEditor = ({
46175
46460
  };
46176
46461
  const onHeaderFooterDataUpdate = async ({ editor, transaction }, mainEditor, sectionId, type) => {
46177
46462
  if (!type || !sectionId) return;
46463
+ if (isApplyingRemoteHeaderFooterChanges()) {
46464
+ return;
46465
+ }
46178
46466
  const updatedData = editor.getUpdatedJson();
46179
46467
  const editorsList = mainEditor.converter[`${type}Editors`];
46180
46468
  if (Array.isArray(editorsList)) {
@@ -46198,6 +46486,7 @@ const onHeaderFooterDataUpdate = async ({ editor, transaction }, mainEditor, sec
46198
46486
  if (editor.docChanged && mainEditor.converter) {
46199
46487
  mainEditor.converter.headerFooterModified = true;
46200
46488
  }
46489
+ pushHeaderFooterToYjs(mainEditor, type, sectionId, updatedData);
46201
46490
  await updateYdocDocxData(mainEditor);
46202
46491
  };
46203
46492
  const setEditorToolbar = ({ editor }, mainEditor) => {
@@ -48024,7 +48313,8 @@ async function measureParagraphBlock(block, maxWidth) {
48024
48313
  const originX = currentLine.width;
48025
48314
  const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
48026
48315
  tabStopCursor = nextIndex;
48027
- const tabAdvance = Math.max(0, target - currentLine.width);
48316
+ const clampedTarget = Math.min(target, currentLine.maxWidth);
48317
+ const tabAdvance = Math.max(0, clampedTarget - currentLine.width);
48028
48318
  currentLine.width = roundValue(currentLine.width + tabAdvance);
48029
48319
  run.width = tabAdvance;
48030
48320
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, 12);
@@ -48032,14 +48322,14 @@ async function measureParagraphBlock(block, maxWidth) {
48032
48322
  currentLine.toChar = 1;
48033
48323
  if (stop) {
48034
48324
  validateTabStopVal(stop);
48035
- pendingTabAlignment = { target, val: stop.val };
48325
+ pendingTabAlignment = { target: clampedTarget, val: stop.val };
48036
48326
  } else {
48037
48327
  pendingTabAlignment = null;
48038
48328
  }
48039
48329
  if (stop && stop.leader && stop.leader !== "none") {
48040
48330
  const leaderStyle = stop.leader;
48041
- const from3 = Math.min(originX, target);
48042
- const to = Math.max(originX, target);
48331
+ const from3 = Math.min(originX, clampedTarget);
48332
+ const to = Math.max(originX, clampedTarget);
48043
48333
  if (!currentLine.leaders) currentLine.leaders = [];
48044
48334
  currentLine.leaders.push({ from: from3, to, style: leaderStyle });
48045
48335
  }
@@ -48634,7 +48924,8 @@ async function measureParagraphBlock(block, maxWidth) {
48634
48924
  const originX = currentLine.width;
48635
48925
  const { target, nextIndex, stop } = getNextTabStopPx(currentLine.width, tabStops, tabStopCursor);
48636
48926
  tabStopCursor = nextIndex;
48637
- const tabAdvance = Math.max(0, target - currentLine.width);
48927
+ const clampedTarget = Math.min(target, currentLine.maxWidth);
48928
+ const tabAdvance = Math.max(0, clampedTarget - currentLine.width);
48638
48929
  currentLine.width = roundValue(currentLine.width + tabAdvance);
48639
48930
  currentLine.maxFontInfo = updateMaxFontInfo(currentLine.maxFontSize, currentLine.maxFontInfo, run);
48640
48931
  currentLine.maxFontSize = Math.max(currentLine.maxFontSize, run.fontSize);
@@ -48643,14 +48934,14 @@ async function measureParagraphBlock(block, maxWidth) {
48643
48934
  charPosInRun += 1;
48644
48935
  if (stop) {
48645
48936
  validateTabStopVal(stop);
48646
- pendingTabAlignment = { target, val: stop.val };
48937
+ pendingTabAlignment = { target: clampedTarget, val: stop.val };
48647
48938
  } else {
48648
48939
  pendingTabAlignment = null;
48649
48940
  }
48650
48941
  if (stop && stop.leader && stop.leader !== "none" && stop.leader !== "middleDot") {
48651
48942
  const leaderStyle = stop.leader;
48652
- const from3 = Math.min(originX, target);
48653
- const to = Math.max(originX, target);
48943
+ const from3 = Math.min(originX, clampedTarget);
48944
+ const to = Math.max(originX, clampedTarget);
48654
48945
  if (!currentLine.leaders) currentLine.leaders = [];
48655
48946
  currentLine.leaders.push({ from: from3, to, style: leaderStyle });
48656
48947
  }
@@ -51047,6 +51338,17 @@ class PresentationEditor extends EventEmitter {
51047
51338
  event: "collaborationReady",
51048
51339
  handler: handleCollaborationReady
51049
51340
  });
51341
+ const handleRemoteHeaderFooterChanged = (payload) => {
51342
+ this.#headerFooterAdapter?.invalidate(payload.sectionId);
51343
+ this.#headerFooterManager?.refresh();
51344
+ this.#pendingDocChange = true;
51345
+ this.#scheduleRerender();
51346
+ };
51347
+ this.#editor.on("remoteHeaderFooterChanged", handleRemoteHeaderFooterChanged);
51348
+ this.#editorListeners.push({
51349
+ event: "remoteHeaderFooterChanged",
51350
+ handler: handleRemoteHeaderFooterChanged
51351
+ });
51050
51352
  }
51051
51353
  /**
51052
51354
  * Setup awareness event subscriptions for remote cursor tracking.
@@ -57206,16 +57508,112 @@ const mapRangesThroughTransactions = (ranges, transactions, docSize) => {
57206
57508
  });
57207
57509
  return mergeRanges$2(mapped, docSize);
57208
57510
  };
57209
- const buildWrapTransaction = (state, ranges, runType) => {
57511
+ const getParagraphAtPos = (doc2, pos) => {
57512
+ try {
57513
+ const $pos = doc2.resolve(pos);
57514
+ for (let depth = $pos.depth; depth >= 0; depth--) {
57515
+ const node = $pos.node(depth);
57516
+ if (node.type.name === "paragraph") {
57517
+ return node;
57518
+ }
57519
+ }
57520
+ } catch (_e) {
57521
+ }
57522
+ return null;
57523
+ };
57524
+ const resolveRunPropertiesFromParagraphStyle = (paragraphNode, editor) => {
57525
+ if (!paragraphNode || !editor?.converter) return {};
57526
+ const styleId = paragraphNode.attrs?.paragraphProperties?.styleId;
57527
+ if (!styleId) return {};
57528
+ try {
57529
+ const params2 = { docx: editor.converter.convertedXml, numbering: editor.converter.numbering };
57530
+ const resolvedPpr = { styleId };
57531
+ const runProps = superEditor_converter.resolveRunProperties(params2, {}, resolvedPpr, false, false);
57532
+ const runProperties = {};
57533
+ if (runProps.fontFamily) {
57534
+ const fontValue = runProps.fontFamily.ascii || runProps.fontFamily;
57535
+ if (fontValue) {
57536
+ runProperties.fontFamily = typeof fontValue === "string" ? fontValue : fontValue.ascii;
57537
+ }
57538
+ }
57539
+ if (runProps.fontSize) {
57540
+ runProperties.fontSize = `${runProps.fontSize / 2}pt`;
57541
+ }
57542
+ if (runProps.bold) runProperties.bold = true;
57543
+ if (runProps.italic) runProperties.italic = true;
57544
+ if (runProps.underline) runProperties.underline = runProps.underline;
57545
+ if (runProps.strike) runProperties.strike = true;
57546
+ return runProperties;
57547
+ } catch (_e) {
57548
+ return {};
57549
+ }
57550
+ };
57551
+ const createMarksFromDefs = (schema, markDefs = []) => markDefs.map((def) => {
57552
+ const markType = schema.marks[def.type];
57553
+ return markType ? markType.create(def.attrs) : null;
57554
+ }).filter(Boolean);
57555
+ const createMarkDefsFromStyleRunProps = (styleRunProps) => {
57556
+ const markDefs = [];
57557
+ const textStyleAttrs = {};
57558
+ if (styleRunProps.fontSize) {
57559
+ textStyleAttrs.fontSize = styleRunProps.fontSize;
57560
+ }
57561
+ if (styleRunProps.fontFamily) {
57562
+ textStyleAttrs.fontFamily = styleRunProps.fontFamily;
57563
+ }
57564
+ if (Object.keys(textStyleAttrs).length > 0) {
57565
+ markDefs.push({ type: "textStyle", attrs: textStyleAttrs });
57566
+ }
57567
+ if (styleRunProps.bold) {
57568
+ markDefs.push({ type: "bold", attrs: { value: true } });
57569
+ }
57570
+ if (styleRunProps.italic) {
57571
+ markDefs.push({ type: "italic", attrs: { value: true } });
57572
+ }
57573
+ if (styleRunProps.strike) {
57574
+ markDefs.push({ type: "strike", attrs: { value: true } });
57575
+ }
57576
+ if (styleRunProps.underline) {
57577
+ const underlineType = styleRunProps.underline["w:val"];
57578
+ if (underlineType) {
57579
+ let underlineColor = styleRunProps.underline["w:color"];
57580
+ if (underlineColor && underlineColor.toLowerCase() !== "auto" && !underlineColor.startsWith("#")) {
57581
+ underlineColor = `#${underlineColor}`;
57582
+ }
57583
+ markDefs.push({
57584
+ type: "underline",
57585
+ attrs: { underlineType, underlineColor }
57586
+ });
57587
+ }
57588
+ }
57589
+ return markDefs;
57590
+ };
57591
+ const buildWrapTransaction = (state, ranges, runType, editor, markDefsFromMeta = []) => {
57210
57592
  if (!ranges.length) return null;
57211
57593
  const replacements = [];
57594
+ const metaStyleMarks = createMarksFromDefs(state.schema, markDefsFromMeta);
57212
57595
  ranges.forEach(({ from: from3, to }) => {
57213
57596
  state.doc.nodesBetween(from3, to, (node, pos, parent, index2) => {
57214
57597
  if (!node.isText || !parent || parent.type === runType) return;
57215
57598
  const match = parent.contentMatchAt ? parent.contentMatchAt(index2) : null;
57216
57599
  if (match && !match.matchType(runType)) return;
57217
57600
  if (!match && !parent.type.contentMatch.matchType(runType)) return;
57218
- const runProperties = superEditor_converter.decodeRPrFromMarks(node.marks);
57601
+ let runProperties = superEditor_converter.decodeRPrFromMarks(node.marks);
57602
+ if ((!node.marks || node.marks.length === 0) && editor?.converter) {
57603
+ const paragraphNode = getParagraphAtPos(state.doc, pos);
57604
+ const styleRunProps = resolveRunPropertiesFromParagraphStyle(paragraphNode, editor);
57605
+ if (Object.keys(styleRunProps).length > 0) {
57606
+ runProperties = styleRunProps;
57607
+ const markDefs = metaStyleMarks.length ? markDefsFromMeta : createMarkDefsFromStyleRunProps(styleRunProps);
57608
+ const styleMarks = metaStyleMarks.length ? metaStyleMarks : createMarksFromDefs(state.schema, markDefs);
57609
+ if (styleMarks.length && typeof state.schema.text === "function") {
57610
+ const textNode = state.schema.text(node.text || "", styleMarks);
57611
+ if (textNode) {
57612
+ node = textNode;
57613
+ }
57614
+ }
57615
+ }
57616
+ }
57219
57617
  const runNode = runType.create({ runProperties }, node);
57220
57618
  replacements.push({ from: pos, to: pos + node.nodeSize, runNode });
57221
57619
  });
@@ -57225,9 +57623,10 @@ const buildWrapTransaction = (state, ranges, runType) => {
57225
57623
  replacements.sort((a, b) => b.from - a.from).forEach(({ from: from3, to, runNode }) => tr.replaceWith(from3, to, runNode));
57226
57624
  return tr.docChanged ? tr : null;
57227
57625
  };
57228
- const wrapTextInRunsPlugin = () => {
57626
+ const wrapTextInRunsPlugin = (editor) => {
57229
57627
  let view = null;
57230
57628
  let pendingRanges = [];
57629
+ let lastStyleMarksMeta = [];
57231
57630
  const flush = () => {
57232
57631
  if (!view) return;
57233
57632
  const runType = view.state.schema.nodes.run;
@@ -57235,7 +57634,7 @@ const wrapTextInRunsPlugin = () => {
57235
57634
  pendingRanges = [];
57236
57635
  return;
57237
57636
  }
57238
- const tr = buildWrapTransaction(view.state, pendingRanges, runType);
57637
+ const tr = buildWrapTransaction(view.state, pendingRanges, runType, editor, lastStyleMarksMeta);
57239
57638
  pendingRanges = [];
57240
57639
  if (tr) {
57241
57640
  view.dispatch(tr);
@@ -57254,6 +57653,7 @@ const wrapTextInRunsPlugin = () => {
57254
57653
  editorView.dom.removeEventListener("compositionend", onCompositionEnd);
57255
57654
  view = null;
57256
57655
  pendingRanges = [];
57656
+ lastStyleMarksMeta = [];
57257
57657
  }
57258
57658
  };
57259
57659
  },
@@ -57267,7 +57667,11 @@ const wrapTextInRunsPlugin = () => {
57267
57667
  if (view?.composing) {
57268
57668
  return null;
57269
57669
  }
57270
- const tr = buildWrapTransaction(newState, pendingRanges, runType);
57670
+ const latestStyleMarksMeta = [...transactions].reverse().find((tr2) => tr2.getMeta && tr2.getMeta("sdStyleMarks"))?.getMeta("sdStyleMarks") || lastStyleMarksMeta;
57671
+ if (latestStyleMarksMeta && latestStyleMarksMeta.length) {
57672
+ lastStyleMarksMeta = latestStyleMarksMeta;
57673
+ }
57674
+ const tr = buildWrapTransaction(newState, pendingRanges, runType, editor, latestStyleMarksMeta);
57271
57675
  pendingRanges = [];
57272
57676
  return tr;
57273
57677
  }
@@ -57530,7 +57934,7 @@ const Run = OxmlNode.create({
57530
57934
  },
57531
57935
  addPmPlugins() {
57532
57936
  return [
57533
- wrapTextInRunsPlugin(),
57937
+ wrapTextInRunsPlugin(this.editor),
57534
57938
  splitRunsAfterMarkPlugin,
57535
57939
  calculateInlineRunPropertiesPlugin(this.editor),
57536
57940
  cleanupEmptyRunsPlugin