@a3s-lab/office 0.9.2 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/COLLABORATION_ROADMAP.md +29 -5
  2. package/README.md +19 -6
  3. package/dist/{0~7754.js → 0~5093.js} +1449 -3
  4. package/dist/0~document-editor.js +8 -1
  5. package/dist/0~work-docx-export.js +482 -16
  6. package/dist/0~work-docx-import.js +31 -1142
  7. package/dist/0~work-office-diagnostics.js +9 -5
  8. package/dist/4104.js +1 -1
  9. package/dist/8928.js +763 -149
  10. package/dist/internal/features/work/work-document-format-change-tracking.d.ts +9 -0
  11. package/dist/internal/features/work/work-document-format-changes.d.ts +28 -0
  12. package/dist/internal/features/work/work-document-paragraph-format-change-tracking.d.ts +7 -0
  13. package/dist/internal/features/work/work-document-paragraph-format-changes.d.ts +8 -0
  14. package/dist/internal/features/work/work-docx-format-change-export.d.ts +17 -0
  15. package/dist/internal/features/work/work-docx-import.d.ts +3 -1
  16. package/dist/internal/features/work/work-docx-paragraph-alignment-import.d.ts +1 -0
  17. package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +1 -0
  18. package/dist/internal/features/work/work-docx-paragraph-direction-import.d.ts +1 -0
  19. package/dist/internal/features/work/work-docx-paragraph-format-change-export.d.ts +13 -0
  20. package/dist/internal/features/work/work-docx-paragraph-format-change-import.d.ts +17 -0
  21. package/dist/internal/features/work/work-docx-paragraph-indent-import.d.ts +1 -0
  22. package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +1 -0
  23. package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +1 -0
  24. package/dist/internal/features/work/work-docx-paragraph-spacing-import.d.ts +1 -0
  25. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +10 -0
  26. package/dist/internal/features/work/work-docx-tab-stop-import.d.ts +1 -0
  27. package/dist/internal/features/work/work-types.d.ts +1 -1
  28. package/dist/office-kernel.wasm +0 -0
  29. package/dist/styles.css +28 -0
  30. package/docs/latest/en/browser-editor-architecture.md +18 -0
  31. package/package.json +7 -3
package/dist/8928.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Extension, Mark, Node as core_Node, ResizableNodeView, generateHTML, getSchema, mergeAttributes } from "@tiptap/core";
2
2
  import { Collaboration, isChangeOrigin } from "@tiptap/extension-collaboration";
3
3
  import { NodeSelection, Plugin, PluginKey, TextSelection } from "@tiptap/pm/state";
4
- import { AddMarkStep, Mapping, RemoveMarkStep, ReplaceStep } from "@tiptap/pm/transform";
4
+ import { AddMarkStep, Mapping, RemoveMarkStep, ReplaceAroundStep, ReplaceStep } from "@tiptap/pm/transform";
5
5
  import { defaultDeleteFilter, defaultProtectedNodes, prosemirrorJSONToYXmlFragment, ySyncPluginKey, yXmlFragmentToProsemirrorJSON } from "@tiptap/y-tiptap";
6
6
  import extension_color from "@tiptap/extension-color";
7
7
  import { Table, TableCell, TableHeader, TableKit, TableRow, TableView, createTable } from "@tiptap/extension-table";
@@ -8382,6 +8382,570 @@ function work_document_caption_nodes_stringAttribute(value) {
8382
8382
  function isBookmarkCrossReferenceTarget(target) {
8383
8383
  return 'type' in target && 'bookmark' === target.type;
8384
8384
  }
8385
+ const DOCUMENT_CHARACTER_FORMAT_MARKS = [
8386
+ 'bold',
8387
+ 'italic',
8388
+ 'underline',
8389
+ 'strike',
8390
+ "subscript",
8391
+ "superscript",
8392
+ 'textStyle',
8393
+ 'highlight'
8394
+ ];
8395
+ const CHARACTER_FORMAT_MARK_NAMES = new Set(DOCUMENT_CHARACTER_FORMAT_MARKS);
8396
+ const CHARACTER_FORMAT_MARK_ORDER = new Map(DOCUMENT_CHARACTER_FORMAT_MARKS.map((name, index)=>[
8397
+ name,
8398
+ index
8399
+ ]));
8400
+ const MAX_CHARACTER_FORMAT_SNAPSHOT_BYTES = 4096;
8401
+ const MAX_CHARACTER_FORMAT_ATTRIBUTE_LENGTH = 512;
8402
+ const ALLOWED_ATTRIBUTES = {
8403
+ bold: new Set(),
8404
+ italic: new Set(),
8405
+ underline: new Set(),
8406
+ strike: new Set(),
8407
+ subscript: new Set(),
8408
+ superscript: new Set(),
8409
+ textStyle: new Set([
8410
+ 'color',
8411
+ 'fontFamily',
8412
+ 'fontSize',
8413
+ 'themeColor',
8414
+ 'wordLineHeightFactor',
8415
+ 'wordSnapToGrid'
8416
+ ]),
8417
+ highlight: new Set([
8418
+ 'color',
8419
+ 'themeFill'
8420
+ ])
8421
+ };
8422
+ function isDocumentCharacterFormatMark(value) {
8423
+ return CHARACTER_FORMAT_MARK_NAMES.has(value);
8424
+ }
8425
+ function serializeDocumentCharacterFormatting(marks) {
8426
+ return JSON.stringify(marks.flatMap((mark)=>{
8427
+ const normalized = normalizeCharacterFormatMark({
8428
+ type: mark.type.name,
8429
+ attrs: mark.attrs
8430
+ });
8431
+ return normalized ? [
8432
+ normalized
8433
+ ] : [];
8434
+ }).sort(compareCharacterFormatMarks));
8435
+ }
8436
+ function parseDocumentCharacterFormatting(value) {
8437
+ if ('string' != typeof value || value.length > MAX_CHARACTER_FORMAT_SNAPSHOT_BYTES) return null;
8438
+ let parsed;
8439
+ try {
8440
+ parsed = JSON.parse(value);
8441
+ } catch {
8442
+ return null;
8443
+ }
8444
+ if (!Array.isArray(parsed) || parsed.length > DOCUMENT_CHARACTER_FORMAT_MARKS.length) return null;
8445
+ const result = [];
8446
+ const names = new Set();
8447
+ for (const candidate of parsed){
8448
+ const mark = normalizeCharacterFormatMark(candidate);
8449
+ if (!mark || names.has(mark.type)) return null;
8450
+ names.add(mark.type);
8451
+ result.push(mark);
8452
+ }
8453
+ result.sort(compareCharacterFormatMarks);
8454
+ return JSON.stringify(result) === value ? result : null;
8455
+ }
8456
+ function restoreDocumentCharacterFormatting(transaction, schema, from, to, serialized) {
8457
+ const formatting = parseDocumentCharacterFormatting(serialized);
8458
+ if (!formatting || from < 0 || to <= from || to > transaction.doc.content.size) return false;
8459
+ for (const name of DOCUMENT_CHARACTER_FORMAT_MARKS){
8460
+ const type = schema.marks[name];
8461
+ if (type) transaction.removeMark(from, to, type);
8462
+ }
8463
+ for (const mark of formatting){
8464
+ const type = schema.marks[mark.type];
8465
+ if (!type) return false;
8466
+ transaction.addMark(from, to, createCharacterFormatMark(type, mark));
8467
+ }
8468
+ return true;
8469
+ }
8470
+ function importedDocumentCharacterFormatting(formatting) {
8471
+ const marks = [];
8472
+ for (const name of [
8473
+ 'bold',
8474
+ 'italic',
8475
+ 'underline',
8476
+ 'strike',
8477
+ "subscript",
8478
+ "superscript"
8479
+ ])if (formatting[name]) marks.push({
8480
+ type: name
8481
+ });
8482
+ const textStyle = compactAttributes({
8483
+ color: formatting.color,
8484
+ fontFamily: formatting.fontFamily,
8485
+ fontSize: void 0 === formatting.fontSize ? void 0 : `${formatting.fontSize}pt`,
8486
+ themeColor: formatting.themeColor,
8487
+ wordLineHeightFactor: formatting.wordLineHeightFactor,
8488
+ wordSnapToGrid: formatting.wordSnapToGrid
8489
+ });
8490
+ if (textStyle) marks.push({
8491
+ type: 'textStyle',
8492
+ attrs: textStyle
8493
+ });
8494
+ const highlight = compactAttributes({
8495
+ color: formatting.backgroundColor,
8496
+ themeFill: formatting.themeFill
8497
+ });
8498
+ if (highlight) marks.push({
8499
+ type: 'highlight',
8500
+ attrs: highlight
8501
+ });
8502
+ marks.sort(compareCharacterFormatMarks);
8503
+ return JSON.stringify(marks);
8504
+ }
8505
+ function normalizeCharacterFormatMark(value) {
8506
+ if (!work_document_format_changes_isRecord(value) || 'string' != typeof value.type) return null;
8507
+ if (!isDocumentCharacterFormatMark(value.type)) return null;
8508
+ const type = value.type;
8509
+ const allowed = ALLOWED_ATTRIBUTES[type];
8510
+ const source = value.attrs;
8511
+ if (void 0 !== source && !work_document_format_changes_isRecord(source)) return null;
8512
+ const attrs = {};
8513
+ for (const [key, candidate] of Object.entries(source ?? {}))if (allowed.has(key) && null != candidate) {
8514
+ if ('string' == typeof candidate) {
8515
+ if (!candidate.length || candidate.length > MAX_CHARACTER_FORMAT_ATTRIBUTE_LENGTH) return null;
8516
+ attrs[key] = candidate;
8517
+ continue;
8518
+ }
8519
+ if ('boolean' == typeof candidate) {
8520
+ attrs[key] = candidate;
8521
+ continue;
8522
+ }
8523
+ if ('number' == typeof candidate && Number.isFinite(candidate)) {
8524
+ attrs[key] = candidate;
8525
+ continue;
8526
+ }
8527
+ return null;
8528
+ }
8529
+ const keys = Object.keys(attrs).sort();
8530
+ const normalizedAttributes = keys.length ? Object.fromEntries(keys.map((key)=>[
8531
+ key,
8532
+ attrs[key]
8533
+ ])) : void 0;
8534
+ return {
8535
+ type,
8536
+ ...normalizedAttributes ? {
8537
+ attrs: normalizedAttributes
8538
+ } : {}
8539
+ };
8540
+ }
8541
+ function compareCharacterFormatMarks(left, right) {
8542
+ return (CHARACTER_FORMAT_MARK_ORDER.get(left.type) ?? Number.MAX_SAFE_INTEGER) - (CHARACTER_FORMAT_MARK_ORDER.get(right.type) ?? Number.MAX_SAFE_INTEGER);
8543
+ }
8544
+ function createCharacterFormatMark(type, value) {
8545
+ return type.create(value.attrs ?? void 0);
8546
+ }
8547
+ function compactAttributes(value) {
8548
+ const entries = Object.entries(value).filter((entry)=>void 0 !== entry[1]);
8549
+ return entries.length ? Object.fromEntries(entries) : void 0;
8550
+ }
8551
+ function work_document_format_changes_isRecord(value) {
8552
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
8553
+ }
8554
+ const MAX_DOCUMENT_TAB_POSITION_PX = 4096;
8555
+ const MAX_DOCUMENT_TAB_STOPS = 64;
8556
+ const DocumentParagraphTabStops = Extension.create({
8557
+ name: 'documentParagraphTabStops',
8558
+ addGlobalAttributes () {
8559
+ return [
8560
+ {
8561
+ types: [
8562
+ 'paragraph',
8563
+ 'heading'
8564
+ ],
8565
+ attributes: {
8566
+ tabStops: {
8567
+ default: null,
8568
+ parseHTML: (element)=>normalizeDocumentTabStops(element.dataset.officeTabStops),
8569
+ renderHTML: (attributes)=>{
8570
+ const tabStops = normalizeDocumentTabStops(attributes.tabStops);
8571
+ return tabStops.length ? {
8572
+ 'data-office-tab-stops': serializeDocumentTabStops(tabStops)
8573
+ } : {};
8574
+ }
8575
+ }
8576
+ }
8577
+ }
8578
+ ];
8579
+ },
8580
+ addCommands () {
8581
+ return {
8582
+ setDocumentParagraphTabStops: (tabStops, options = {})=>({ chain, editor })=>{
8583
+ const nodeTypes = activeParagraphNodeTypes(editor);
8584
+ if (!nodeTypes.length) return false;
8585
+ const normalized = normalizeDocumentTabStops(tabStops);
8586
+ let commandChain = chain();
8587
+ if (false !== options.restoreFocus) commandChain = commandChain.focus();
8588
+ for (const nodeType of nodeTypes)commandChain = commandChain.updateAttributes(nodeType, {
8589
+ tabStops: normalized.length ? normalized : null
8590
+ });
8591
+ return commandChain.run();
8592
+ }
8593
+ };
8594
+ }
8595
+ });
8596
+ function documentParagraphTabStops(editor) {
8597
+ return normalizeDocumentTabStops(activeParagraphAttributes(editor).tabStops);
8598
+ }
8599
+ function normalizeDocumentTabStops(value) {
8600
+ const source = parsedTabStopSource(value);
8601
+ const byPosition = new Map();
8602
+ for (const candidate of source.slice(0, 4 * MAX_DOCUMENT_TAB_STOPS)){
8603
+ if (!work_document_tab_stops_isRecord(candidate)) continue;
8604
+ const rawPosition = Number(candidate.position);
8605
+ if (!Number.isFinite(rawPosition) || rawPosition <= 0) continue;
8606
+ const position = normalizedTabPosition(rawPosition);
8607
+ if (!(position <= 0)) byPosition.set(position, {
8608
+ position,
8609
+ alignment: normalizedTabAlignment(candidate.alignment),
8610
+ leader: normalizedTabLeader(candidate.leader)
8611
+ });
8612
+ }
8613
+ return Array.from(byPosition.values()).sort((left, right)=>left.position - right.position).slice(0, MAX_DOCUMENT_TAB_STOPS);
8614
+ }
8615
+ function serializeDocumentTabStops(value) {
8616
+ return JSON.stringify(normalizeDocumentTabStops(value));
8617
+ }
8618
+ function normalizedTabPosition(value) {
8619
+ if (!Number.isFinite(value)) return 0;
8620
+ return Math.min(MAX_DOCUMENT_TAB_POSITION_PX, Math.max(0, Math.round(100 * value) / 100));
8621
+ }
8622
+ function nextDocumentTabAlignment(alignment) {
8623
+ if ('left' === alignment) return 'center';
8624
+ if ('center' === alignment) return 'right';
8625
+ if ('right' === alignment) return 'decimal';
8626
+ return 'left';
8627
+ }
8628
+ function parsedTabStopSource(value) {
8629
+ if (Array.isArray(value)) return value;
8630
+ if ('string' != typeof value || !value.trim()) return [];
8631
+ try {
8632
+ const parsed = JSON.parse(value);
8633
+ return Array.isArray(parsed) ? parsed : [];
8634
+ } catch {
8635
+ return [];
8636
+ }
8637
+ }
8638
+ function normalizedTabAlignment(value) {
8639
+ return 'center' === value || 'right' === value || 'decimal' === value ? value : 'left';
8640
+ }
8641
+ function normalizedTabLeader(value) {
8642
+ return 'dot' === value || 'hyphen' === value || 'underscore' === value || 'middleDot' === value ? value : 'none';
8643
+ }
8644
+ function activeParagraphAttributes(editor) {
8645
+ return editor.isActive('heading') ? editor.getAttributes('heading') : editor.getAttributes('paragraph');
8646
+ }
8647
+ function activeParagraphNodeTypes(editor) {
8648
+ const types = [];
8649
+ if (editor.isActive('paragraph')) types.push('paragraph');
8650
+ if (editor.isActive('heading')) types.push('heading');
8651
+ return types;
8652
+ }
8653
+ function work_document_tab_stops_isRecord(value) {
8654
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
8655
+ }
8656
+ const DOCUMENT_PARAGRAPH_FORMAT_ATTRIBUTES = [
8657
+ 'textAlign',
8658
+ 'paragraphDirection',
8659
+ 'indentLevel',
8660
+ 'rightIndent',
8661
+ 'firstLineIndent',
8662
+ 'spaceBefore',
8663
+ 'spaceAfter',
8664
+ 'lineHeight',
8665
+ 'lineRule',
8666
+ 'autoLineHeight',
8667
+ 'keepLines',
8668
+ 'keepWithNext',
8669
+ 'pageBreakBefore',
8670
+ 'widowControl',
8671
+ 'contextualSpacing',
8672
+ 'outlineLevel',
8673
+ 'tabStops',
8674
+ 'paragraphBorders',
8675
+ 'paragraphShading',
8676
+ 'defaultCollapsed'
8677
+ ];
8678
+ const MAX_PARAGRAPH_FORMAT_SNAPSHOT_BYTES = 65536;
8679
+ const MAX_DOCUMENT_INDENT_PX = 192;
8680
+ function serializeDocumentParagraphFormatting(attributes) {
8681
+ return JSON.stringify(normalizeParagraphFormatting(attributes));
8682
+ }
8683
+ function parseDocumentParagraphFormatting(value) {
8684
+ if ('string' != typeof value || !value.length || value.length > MAX_PARAGRAPH_FORMAT_SNAPSHOT_BYTES) return null;
8685
+ let parsed;
8686
+ try {
8687
+ parsed = JSON.parse(value);
8688
+ } catch {
8689
+ return null;
8690
+ }
8691
+ if (!work_document_paragraph_format_changes_isRecord(parsed)) return null;
8692
+ const keys = Object.keys(parsed);
8693
+ if (keys.length !== DOCUMENT_PARAGRAPH_FORMAT_ATTRIBUTES.length || keys.some((key, index)=>key !== DOCUMENT_PARAGRAPH_FORMAT_ATTRIBUTES[index])) return null;
8694
+ const normalized = normalizeParagraphFormatting(parsed);
8695
+ return JSON.stringify(normalized) === value ? normalized : null;
8696
+ }
8697
+ function restoredDocumentParagraphAttributes(attributes, serialized) {
8698
+ const formatting = parseDocumentParagraphFormatting(serialized);
8699
+ if (!formatting) return null;
8700
+ return clearDocumentParagraphChangeAttributes({
8701
+ ...attributes,
8702
+ ...formatting
8703
+ });
8704
+ }
8705
+ function clearDocumentParagraphChangeAttributes(attributes) {
8706
+ return {
8707
+ ...attributes,
8708
+ paragraphChangeKind: null,
8709
+ paragraphChangeId: '',
8710
+ paragraphChangeActorId: '',
8711
+ paragraphChangeAuthor: '',
8712
+ paragraphChangeDate: '',
8713
+ paragraphChangeBefore: ''
8714
+ };
8715
+ }
8716
+ function normalizeParagraphFormatting(source) {
8717
+ const indentLevel = quarterNumber(source.indentLevel, 0, 8, 0);
8718
+ const leftIndent = 24 * indentLevel;
8719
+ const serializedBorders = serializeDocumentParagraphBorders(source.paragraphBorders);
8720
+ const serializedShading = serializeDocumentParagraphShading(source.paragraphShading);
8721
+ const tabStops = normalizeDocumentTabStops(source.tabStops);
8722
+ return {
8723
+ textAlign: oneOfOrNull(source.textAlign, [
8724
+ 'left',
8725
+ 'center',
8726
+ 'right',
8727
+ 'justify'
8728
+ ]),
8729
+ paragraphDirection: oneOfOrNull(source.paragraphDirection, [
8730
+ 'ltr',
8731
+ 'rtl'
8732
+ ]),
8733
+ indentLevel,
8734
+ rightIndent: integerNumber(source.rightIndent, 0, MAX_DOCUMENT_INDENT_PX, 0),
8735
+ firstLineIndent: integerNumber(source.firstLineIndent, -leftIndent, MAX_DOCUMENT_INDENT_PX, 0),
8736
+ spaceBefore: quarterNumberOrNull(source.spaceBefore, 0, 720),
8737
+ spaceAfter: quarterNumberOrNull(source.spaceAfter, 0, 720),
8738
+ lineHeight: normalizedLineHeight(source.lineHeight),
8739
+ lineRule: oneOfOrNull(source.lineRule, [
8740
+ 'auto',
8741
+ 'exact',
8742
+ 'atLeast'
8743
+ ]),
8744
+ autoLineHeight: decimalNumberOrNull(source.autoLineHeight, 0, 20, 4),
8745
+ keepLines: booleanOrNull(source.keepLines),
8746
+ keepWithNext: booleanOrNull(source.keepWithNext),
8747
+ pageBreakBefore: booleanOrNull(source.pageBreakBefore),
8748
+ widowControl: booleanOrNull(source.widowControl),
8749
+ contextualSpacing: booleanOrNull(source.contextualSpacing),
8750
+ outlineLevel: integerNumberOrNull(source.outlineLevel, 0, 9),
8751
+ tabStops: tabStops.length ? JSON.parse(serializeDocumentTabStops(tabStops)) : null,
8752
+ paragraphBorders: serializedBorders ? JSON.parse(serializedBorders) : null,
8753
+ paragraphShading: serializedShading ? JSON.parse(serializedShading) : null,
8754
+ defaultCollapsed: booleanOrNull(source.defaultCollapsed)
8755
+ };
8756
+ }
8757
+ function normalizedLineHeight(value) {
8758
+ if (null == value || '' === value) return null;
8759
+ if ('string' != typeof value || value.trim() !== value) return null;
8760
+ return /^(?:\d+(?:\.\d+)?|\d+(?:\.\d+)?(?:px|pt|%))$/i.test(value) ? value : null;
8761
+ }
8762
+ function oneOfOrNull(value, allowed) {
8763
+ return 'string' == typeof value && allowed.includes(value) ? value : null;
8764
+ }
8765
+ function booleanOrNull(value) {
8766
+ return 'boolean' == typeof value ? value : null;
8767
+ }
8768
+ function quarterNumber(value, minimum, maximum, fallback) {
8769
+ const number = Number(value);
8770
+ if (!Number.isFinite(number)) return fallback;
8771
+ return Math.min(maximum, Math.max(minimum, Math.round(4 * number) / 4));
8772
+ }
8773
+ function quarterNumberOrNull(value, minimum, maximum) {
8774
+ if (null == value || '' === value) return null;
8775
+ return quarterNumber(value, minimum, maximum, minimum);
8776
+ }
8777
+ function integerNumber(value, minimum, maximum, fallback) {
8778
+ const number = Number(value);
8779
+ if (!Number.isFinite(number)) return fallback;
8780
+ return Math.min(maximum, Math.max(minimum, Math.round(number)));
8781
+ }
8782
+ function integerNumberOrNull(value, minimum, maximum) {
8783
+ if (null == value || '' === value) return null;
8784
+ const number = Number(value);
8785
+ if (!Number.isSafeInteger(number) || number < minimum || number > maximum) return null;
8786
+ return number;
8787
+ }
8788
+ function decimalNumberOrNull(value, minimumExclusive, maximum, precision) {
8789
+ if (null == value || '' === value) return null;
8790
+ const number = Number(value);
8791
+ if (!Number.isFinite(number) || number <= minimumExclusive || number > maximum) return null;
8792
+ return Number(number.toFixed(precision));
8793
+ }
8794
+ function work_document_paragraph_format_changes_isRecord(value) {
8795
+ return 'object' == typeof value && null !== value && !Array.isArray(value);
8796
+ }
8797
+ function trackDocumentParagraphFormattingTransaction(transaction, state, options) {
8798
+ if (!transaction.steps.some((step)=>step instanceof ReplaceAroundStep)) return false;
8799
+ let identity = null;
8800
+ let tracked = false;
8801
+ state.doc.descendants((before, position)=>{
8802
+ if (!isParagraph(before)) return;
8803
+ const after = transaction.doc.nodeAt(position);
8804
+ if (!after || after.type !== before.type || !isParagraph(after)) return;
8805
+ const previous = serializeDocumentParagraphFormatting(before.attrs);
8806
+ const current = serializeDocumentParagraphFormatting(after.attrs);
8807
+ if (previous === current || !sameContentIgnoringMarks(before, after)) return;
8808
+ if ('paragraph-formatting' === after.attrs.paragraphChangeKind) return;
8809
+ identity ??= options.createChange();
8810
+ transaction.setNodeMarkup(position, void 0, {
8811
+ ...after.attrs,
8812
+ paragraphChangeKind: 'paragraph-formatting',
8813
+ paragraphChangeId: identity.id,
8814
+ paragraphChangeActorId: identity.actorId ?? '',
8815
+ paragraphChangeAuthor: identity.author || 'A3S Work',
8816
+ paragraphChangeDate: identity.date || new Date().toISOString(),
8817
+ paragraphChangeBefore: previous
8818
+ });
8819
+ tracked = true;
8820
+ });
8821
+ return tracked;
8822
+ }
8823
+ function isParagraph(node) {
8824
+ return 'paragraph' === node.type.name || 'heading' === node.type.name;
8825
+ }
8826
+ function sameContentIgnoringMarks(before, after) {
8827
+ return JSON.stringify(childContentIgnoringMarks(before)) === JSON.stringify(childContentIgnoringMarks(after));
8828
+ }
8829
+ function childContentIgnoringMarks(node) {
8830
+ const content = [];
8831
+ node.forEach((child)=>{
8832
+ content.push(contentIgnoringMarks(child));
8833
+ });
8834
+ return content;
8835
+ }
8836
+ function contentIgnoringMarks(node) {
8837
+ if (node.isText) return {
8838
+ type: node.type.name,
8839
+ text: node.text ?? ''
8840
+ };
8841
+ const content = childContentIgnoringMarks(node);
8842
+ return {
8843
+ type: node.type.name,
8844
+ ...Object.keys(node.attrs).length ? {
8845
+ attrs: node.attrs
8846
+ } : {},
8847
+ ...content.length ? {
8848
+ content
8849
+ } : {}
8850
+ };
8851
+ }
8852
+ function trackDocumentFormattingTransaction(transaction, state, type, options, pluginKey) {
8853
+ if (!options.isTracking() || state.doc.eq(transaction.doc)) return;
8854
+ const sync = transaction.getMeta(ySyncPluginKey);
8855
+ if (transaction.getMeta(pluginKey) || sync?.isChangeOrigin || isHistoryTransaction(transaction)) return;
8856
+ const ranges = formattingStepRanges(transaction);
8857
+ const formattedDocument = transaction.doc;
8858
+ let identity = null;
8859
+ for (const range of ranges)for (const segment of formattingSegments(state.doc, formattedDocument, range)){
8860
+ const beforeMarks = textMarksAt(state.doc, segment.from, segment.to);
8861
+ const afterMarks = textMarksAt(formattedDocument, segment.from, segment.to);
8862
+ if (!beforeMarks || !afterMarks) continue;
8863
+ if (state.doc.textBetween(segment.from, segment.to) !== formattedDocument.textBetween(segment.from, segment.to)) continue;
8864
+ const before = serializeDocumentCharacterFormatting(beforeMarks);
8865
+ const after = serializeDocumentCharacterFormatting(afterMarks);
8866
+ if (!(before === after || documentChangeMark(afterMarks))) {
8867
+ identity ??= options.createChange('formatting');
8868
+ transaction.addMark(segment.from, segment.to, type.create({
8869
+ kind: 'formatting',
8870
+ id: identity.id,
8871
+ actorId: identity.actorId ?? '',
8872
+ author: identity.author || 'A3S Work',
8873
+ date: identity.date || new Date().toISOString(),
8874
+ before
8875
+ }));
8876
+ }
8877
+ }
8878
+ const paragraphFormatting = trackDocumentParagraphFormattingTransaction(transaction, state, {
8879
+ createChange: ()=>options.createChange('paragraph-formatting')
8880
+ });
8881
+ if (identity || paragraphFormatting) transaction.setMeta(pluginKey, {
8882
+ ...identity ? {
8883
+ formatting: true
8884
+ } : {},
8885
+ ...paragraphFormatting ? {
8886
+ paragraphFormatting: true
8887
+ } : {}
8888
+ });
8889
+ }
8890
+ function formattingStepRanges(transaction) {
8891
+ if (transaction.steps.some((step)=>step instanceof ReplaceStep)) return [];
8892
+ const ranges = [];
8893
+ for (const step of transaction.steps)if ((step instanceof AddMarkStep || step instanceof RemoveMarkStep) && isDocumentCharacterFormatMark(step.mark.type.name) && step.from < step.to) ranges.push({
8894
+ from: step.from,
8895
+ to: step.to
8896
+ });
8897
+ return mergeFormattingRanges(ranges);
8898
+ }
8899
+ function mergeFormattingRanges(ranges) {
8900
+ const merged = [];
8901
+ for (const range of ranges.sort((left, right)=>left.from - right.from)){
8902
+ const previous = merged.at(-1);
8903
+ if (!previous || range.from > previous.to) {
8904
+ merged.push({
8905
+ ...range
8906
+ });
8907
+ continue;
8908
+ }
8909
+ previous.to = Math.max(previous.to, range.to);
8910
+ }
8911
+ return merged;
8912
+ }
8913
+ function formattingSegments(before, after, range) {
8914
+ const boundaries = new Set([
8915
+ range.from,
8916
+ range.to
8917
+ ]);
8918
+ collectFormattingBoundaries(before, range, boundaries);
8919
+ collectFormattingBoundaries(after, range, boundaries);
8920
+ const ordered = Array.from(boundaries).sort((left, right)=>left - right);
8921
+ return ordered.slice(0, -1).flatMap((from, index)=>{
8922
+ const to = ordered[index + 1];
8923
+ return void 0 !== to && from < to ? [
8924
+ {
8925
+ from,
8926
+ to
8927
+ }
8928
+ ] : [];
8929
+ });
8930
+ }
8931
+ function collectFormattingBoundaries(document1, range, boundaries) {
8932
+ document1.nodesBetween(range.from, range.to, (node, position)=>{
8933
+ if (!node.isText) return;
8934
+ boundaries.add(Math.max(range.from, position));
8935
+ boundaries.add(Math.min(range.to, position + node.nodeSize));
8936
+ });
8937
+ }
8938
+ function textMarksAt(document1, from, to) {
8939
+ let marks = null;
8940
+ document1.nodesBetween(from, to, (node, position)=>{
8941
+ if (marks || !node.isText || position > from || position + node.nodeSize < to) return;
8942
+ marks = node.marks;
8943
+ });
8944
+ return marks;
8945
+ }
8946
+ function documentChangeMark(marks) {
8947
+ return marks.find((mark)=>'documentChange' === mark.type.name);
8948
+ }
8385
8949
  const documentChangePluginKey = new PluginKey('documentChangeTracking');
8386
8950
  const CONTINUOUS_INSERTION_WINDOW_MS = 30000;
8387
8951
  const DocumentChange = Mark.create({
@@ -8404,7 +8968,11 @@ const DocumentChange = Mark.create({
8404
8968
  return {
8405
8969
  kind: {
8406
8970
  default: 'insertion',
8407
- parseHTML: (element)=>'del' === element.tagName.toLowerCase() ? 'deletion' : 'insertion',
8971
+ parseHTML: (element)=>{
8972
+ const declared = element.getAttribute('data-change-kind');
8973
+ if ('formatting' === declared) return 'formatting';
8974
+ return 'del' === element.tagName.toLowerCase() ? 'deletion' : 'insertion';
8975
+ },
8408
8976
  renderHTML: (attributes)=>({
8409
8977
  'data-change-kind': attributes.kind
8410
8978
  })
@@ -8436,9 +9004,34 @@ const DocumentChange = Mark.create({
8436
9004
  renderHTML: (attributes)=>({
8437
9005
  'data-change-date': attributes.date
8438
9006
  })
9007
+ },
9008
+ before: {
9009
+ default: '',
9010
+ parseHTML: (element)=>element.getAttribute('data-change-before') ?? '',
9011
+ renderHTML: (attributes)=>attributes.before ? {
9012
+ 'data-change-before': attributes.before
9013
+ } : {}
8439
9014
  }
8440
9015
  };
8441
9016
  },
9017
+ addGlobalAttributes () {
9018
+ return [
9019
+ {
9020
+ types: [
9021
+ 'paragraph',
9022
+ 'heading'
9023
+ ],
9024
+ attributes: {
9025
+ paragraphChangeKind: paragraphChangeAttribute('kind', 'data-change-kind'),
9026
+ paragraphChangeId: paragraphChangeAttribute('id', 'data-change-id'),
9027
+ paragraphChangeActorId: paragraphChangeAttribute('actorId', 'data-change-actor-id'),
9028
+ paragraphChangeAuthor: paragraphChangeAttribute('author', 'data-change-author'),
9029
+ paragraphChangeDate: paragraphChangeAttribute('date', 'data-change-date'),
9030
+ paragraphChangeBefore: paragraphChangeAttribute('before', 'data-change-before')
9031
+ }
9032
+ }
9033
+ ];
9034
+ },
8442
9035
  parseHTML () {
8443
9036
  return [
8444
9037
  {
@@ -8446,12 +9039,16 @@ const DocumentChange = Mark.create({
8446
9039
  },
8447
9040
  {
8448
9041
  tag: 'del[data-document-change]'
9042
+ },
9043
+ {
9044
+ tag: 'span[data-document-change][data-change-kind="formatting"]'
8449
9045
  }
8450
9046
  ];
8451
9047
  },
8452
9048
  renderHTML ({ mark, HTMLAttributes }) {
9049
+ const tag = 'deletion' === mark.attrs.kind ? 'del' : 'formatting' === mark.attrs.kind ? 'span' : 'ins';
8453
9050
  return [
8454
- 'deletion' === mark.attrs.kind ? 'del' : 'ins',
9051
+ tag,
8455
9052
  mergeAttributes(HTMLAttributes, {
8456
9053
  'data-document-change': 'true'
8457
9054
  }),
@@ -8491,6 +9088,19 @@ const DocumentChange = Mark.create({
8491
9088
  return [
8492
9089
  new Plugin({
8493
9090
  key: documentChangePluginKey,
9091
+ filterTransaction: (transaction, state)=>{
9092
+ trackDocumentFormattingTransaction(transaction, state, changeType, {
9093
+ isTracking: options.isTracking,
9094
+ createChange: (kind)=>{
9095
+ const identity = options.createChange(kind);
9096
+ return {
9097
+ ...identity,
9098
+ id: identity.id || createDocumentChangeId()
9099
+ };
9100
+ }
9101
+ }, documentChangePluginKey);
9102
+ return true;
9103
+ },
8494
9104
  props: {
8495
9105
  handleTextInput: (view, from, to, text)=>{
8496
9106
  if (!options.isTracking()) return false;
@@ -8536,8 +9146,31 @@ const DocumentChange = Mark.create({
8536
9146
  function collectDocumentChanges(document1) {
8537
9147
  const changes = new Map();
8538
9148
  document1.descendants((node, position)=>{
9149
+ if (('paragraph' === node.type.name || 'heading' === node.type.name) && 'paragraph-formatting' === node.attrs.paragraphChangeKind) {
9150
+ const id = work_document_changes_stringAttribute(node.attrs.paragraphChangeId) || `paragraph-change-at-${position}`;
9151
+ const key = `paragraph-formatting:${id}`;
9152
+ const from = position + 1;
9153
+ const to = from + node.content.size;
9154
+ const current = changes.get(key);
9155
+ if (current) {
9156
+ current.from = Math.min(current.from, from);
9157
+ current.to = Math.max(current.to, to);
9158
+ current.text = `${current.text}\n${node.textContent}`;
9159
+ } else changes.set(key, {
9160
+ id,
9161
+ kind: 'paragraph-formatting',
9162
+ ...work_document_changes_stringAttribute(node.attrs.paragraphChangeActorId) ? {
9163
+ actorId: work_document_changes_stringAttribute(node.attrs.paragraphChangeActorId)
9164
+ } : {},
9165
+ author: work_document_changes_stringAttribute(node.attrs.paragraphChangeAuthor) || '未知审阅者',
9166
+ date: work_document_changes_stringAttribute(node.attrs.paragraphChangeDate),
9167
+ from,
9168
+ to,
9169
+ text: node.textContent
9170
+ });
9171
+ }
8539
9172
  if (!node.isText || !node.text) return;
8540
- const mark = documentChangeMark(node.marks);
9173
+ const mark = work_document_changes_documentChangeMark(node.marks);
8541
9174
  if (!mark) return;
8542
9175
  const kind = changeKind(mark.attrs.kind);
8543
9176
  const id = work_document_changes_stringAttribute(mark.attrs.id) || `change-at-${position}`;
@@ -8566,16 +9199,39 @@ function collectDocumentChanges(document1) {
8566
9199
  }
8567
9200
  function resolveDocumentChangesCommand({ state, tr }, type, decision, ids) {
8568
9201
  const segments = documentChangeSegments(state.doc, type).filter((segment)=>!ids || ids.has(segment.id));
8569
- if (!segments.length) return 0;
8570
- const removals = [];
8571
- const deletions = [];
9202
+ const paragraphSegments = paragraphChangeSegments(state.doc).filter((segment)=>!ids || ids.has(segment.id));
9203
+ if (!segments.length && !paragraphSegments.length) return 0;
9204
+ if (paragraphSegments.some((segment)=>!parseDocumentParagraphFormatting(segment.before)) || 'reject' === decision && segments.some((segment)=>'formatting' === segment.kind && !parseDocumentCharacterFormatting(segment.before))) return 0;
9205
+ closeHistory(tr);
9206
+ tr.setMeta(documentChangePluginKey, {
9207
+ decision
9208
+ });
9209
+ const markRemovals = [];
9210
+ const contentDeletions = [];
9211
+ const formattingRejections = [];
8572
9212
  for (const segment of segments){
8573
- const remove = 'accept' === decision && 'insertion' === segment.kind || 'reject' === decision && 'deletion' === segment.kind;
8574
- (remove ? removals : deletions).push(segment);
8575
- }
8576
- for (const segment of removals)tr.removeMark(segment.from, segment.to, type);
8577
- for (const segment of deletions.sort((left, right)=>right.from - left.from))tr.delete(segment.from, segment.to);
8578
- return tr.docChanged ? new Set(segments.map((segment)=>segment.id)).size : 0;
9213
+ if ('formatting' === segment.kind) {
9214
+ markRemovals.push(segment);
9215
+ if ('reject' === decision) formattingRejections.push(segment);
9216
+ continue;
9217
+ }
9218
+ const removeMark = 'accept' === decision && 'insertion' === segment.kind || 'reject' === decision && 'deletion' === segment.kind;
9219
+ (removeMark ? markRemovals : contentDeletions).push(segment);
9220
+ }
9221
+ for (const segment of formattingRejections)restoreDocumentCharacterFormatting(tr, state.schema, segment.from, segment.to, segment.before);
9222
+ for (const segment of paragraphSegments){
9223
+ const node = tr.doc.nodeAt(segment.position);
9224
+ if (!node || 'paragraph' !== node.type.name && 'heading' !== node.type.name) return 0;
9225
+ const attributes = 'reject' === decision ? restoredDocumentParagraphAttributes(node.attrs, segment.before) : clearDocumentParagraphChangeAttributes(node.attrs);
9226
+ if (!attributes) return 0;
9227
+ tr.setNodeMarkup(segment.position, void 0, attributes);
9228
+ }
9229
+ for (const segment of markRemovals)tr.removeMark(segment.from, segment.to, type);
9230
+ for (const segment of contentDeletions.sort((left, right)=>right.from - left.from))tr.delete(segment.from, segment.to);
9231
+ return tr.docChanged ? new Set([
9232
+ ...segments,
9233
+ ...paragraphSegments
9234
+ ].map((segment)=>segment.id)).size : 0;
8579
9235
  }
8580
9236
  function trackedReplacement(transaction, document1, type, from, to, text, createChange) {
8581
9237
  if (from !== to) trackDeletion(transaction, document1, type, from, to, changeMark(type, 'deletion', createChange));
@@ -8622,7 +9278,23 @@ function documentChangeSegments(document1, type) {
8622
9278
  id: work_document_changes_stringAttribute(mark.attrs.id) || `change-at-${position}`,
8623
9279
  kind: changeKind(mark.attrs.kind),
8624
9280
  from: position,
8625
- to: position + node.nodeSize
9281
+ to: position + node.nodeSize,
9282
+ before: work_document_changes_stringAttribute(mark.attrs.before)
9283
+ });
9284
+ });
9285
+ return segments;
9286
+ }
9287
+ function paragraphChangeSegments(document1) {
9288
+ const segments = [];
9289
+ document1.descendants((node, position)=>{
9290
+ if ('paragraph' !== node.type.name && 'heading' !== node.type.name || 'paragraph-formatting' !== node.attrs.paragraphChangeKind) return;
9291
+ segments.push({
9292
+ id: work_document_changes_stringAttribute(node.attrs.paragraphChangeId) || `paragraph-change-at-${position}`,
9293
+ kind: 'paragraph-formatting',
9294
+ position,
9295
+ from: position + 1,
9296
+ to: position + 1 + node.content.size,
9297
+ before: work_document_changes_stringAttribute(node.attrs.paragraphChangeBefore)
8626
9298
  });
8627
9299
  });
8628
9300
  return segments;
@@ -8653,14 +9325,15 @@ function adjacentTextRange(document1, position, direction) {
8653
9325
  to: position + character.length
8654
9326
  };
8655
9327
  }
8656
- function changeMark(type, kind, createChange) {
9328
+ function changeMark(type, kind, createChange, before = '') {
8657
9329
  const identity = createChange(kind);
8658
9330
  return type.create({
8659
9331
  kind,
8660
9332
  id: identity.id || createDocumentChangeId(),
8661
9333
  actorId: identity.actorId ?? '',
8662
9334
  author: identity.author || 'A3S Work',
8663
- date: identity.date || new Date().toISOString()
9335
+ date: identity.date || new Date().toISOString(),
9336
+ before
8664
9337
  });
8665
9338
  }
8666
9339
  function continuousInsertionMark(document1, type, position, createChange) {
@@ -8674,11 +9347,33 @@ function continuousInsertionMark(document1, type, position, createChange) {
8674
9347
  if (!Number.isFinite(previousTime) || !Number.isFinite(nextTime) || Math.abs(nextTime - previousTime) > CONTINUOUS_INSERTION_WINDOW_MS) return next;
8675
9348
  return previous;
8676
9349
  }
8677
- function documentChangeMark(marks) {
9350
+ function work_document_changes_documentChangeMark(marks) {
8678
9351
  return marks.find((mark)=>'documentChange' === mark.type.name);
8679
9352
  }
8680
9353
  function changeKind(value) {
8681
- return 'deletion' === value ? 'deletion' : 'insertion';
9354
+ if ('deletion' === value || 'formatting' === value) return value;
9355
+ return 'insertion';
9356
+ }
9357
+ function paragraphChangeAttribute(field, htmlName) {
9358
+ const modelName = `paragraphChange${field[0]?.toUpperCase() ?? ''}${field.slice(1)}`;
9359
+ return {
9360
+ default: 'kind' === field ? null : '',
9361
+ parseHTML: (element)=>{
9362
+ if ('true' !== element.getAttribute('data-document-change') || 'paragraph-formatting' !== element.getAttribute('data-change-kind')) return 'kind' === field ? null : '';
9363
+ return 'kind' === field ? 'paragraph-formatting' : element.getAttribute(htmlName) ?? '';
9364
+ },
9365
+ renderHTML: (attributes)=>{
9366
+ if ('paragraph-formatting' !== attributes.paragraphChangeKind) return {};
9367
+ if ('kind' === field) return {
9368
+ 'data-document-change': 'true',
9369
+ 'data-change-kind': 'paragraph-formatting'
9370
+ };
9371
+ const value = work_document_changes_stringAttribute(attributes[modelName]);
9372
+ return value ? {
9373
+ [htmlName]: value
9374
+ } : {};
9375
+ }
9376
+ };
8682
9377
  }
8683
9378
  function work_document_changes_stringAttribute(value) {
8684
9379
  return 'string' == typeof value ? value : '';
@@ -11134,7 +11829,7 @@ const DocumentPageBreak = core_Node.create({
11134
11829
  });
11135
11830
  const DOCUMENT_INDENT_STEP_PX = 24;
11136
11831
  const MAX_DOCUMENT_INDENT_LEVEL = 8;
11137
- const MAX_DOCUMENT_INDENT_PX = DOCUMENT_INDENT_STEP_PX * MAX_DOCUMENT_INDENT_LEVEL;
11832
+ const work_document_paragraph_formatting_MAX_DOCUMENT_INDENT_PX = DOCUMENT_INDENT_STEP_PX * MAX_DOCUMENT_INDENT_LEVEL;
11138
11833
  const DOCUMENT_WORD_SINGLE_LINE_HEIGHT = 1.15;
11139
11834
  const DocumentParagraphFormatting = Extension.create({
11140
11835
  name: 'documentParagraphFormatting',
@@ -11148,9 +11843,9 @@ const DocumentParagraphFormatting = Extension.create({
11148
11843
  attributes: {
11149
11844
  lineHeight: {
11150
11845
  default: null,
11151
- parseHTML: (element)=>normalizedLineHeight(element.style.lineHeight),
11846
+ parseHTML: (element)=>work_document_paragraph_formatting_normalizedLineHeight(element.style.lineHeight),
11152
11847
  renderHTML: (attributes)=>{
11153
- const lineHeight = normalizedLineHeight(attributes.lineHeight);
11848
+ const lineHeight = work_document_paragraph_formatting_normalizedLineHeight(attributes.lineHeight);
11154
11849
  return lineHeight ? {
11155
11850
  style: `line-height: ${lineHeight}`
11156
11851
  } : {};
@@ -11275,7 +11970,7 @@ function documentParagraphIndent(editor) {
11275
11970
  });
11276
11971
  }
11277
11972
  function documentParagraphPagination(editor) {
11278
- const attributes = activeParagraphAttributes(editor);
11973
+ const attributes = work_document_paragraph_formatting_activeParagraphAttributes(editor);
11279
11974
  return {
11280
11975
  keepLines: directBoolean(attributes.keepLines) ?? false,
11281
11976
  keepWithNext: directBoolean(attributes.keepWithNext) ?? editor.isActive('heading'),
@@ -11284,15 +11979,15 @@ function documentParagraphPagination(editor) {
11284
11979
  };
11285
11980
  }
11286
11981
  function documentParagraphDirection(editor) {
11287
- const attributes = editor.isActive('listItem') ? editor.getAttributes('listItem') : activeParagraphAttributes(editor);
11982
+ const attributes = editor.isActive('listItem') ? editor.getAttributes('listItem') : work_document_paragraph_formatting_activeParagraphAttributes(editor);
11288
11983
  return normalizeDocumentParagraphDirection(attributes.paragraphDirection) ?? 'ltr';
11289
11984
  }
11290
11985
  function documentParagraphSpacing(editor) {
11291
- const attributes = activeParagraphAttributes(editor);
11986
+ const attributes = work_document_paragraph_formatting_activeParagraphAttributes(editor);
11292
11987
  return {
11293
11988
  before: normalizedPointSpacing(attributes.spaceBefore),
11294
11989
  after: normalizedPointSpacing(attributes.spaceAfter),
11295
- lineHeight: normalizedLineHeight(attributes.lineHeight),
11990
+ lineHeight: work_document_paragraph_formatting_normalizedLineHeight(attributes.lineHeight),
11296
11991
  lineRule: normalizedLineRule(attributes.lineRule)
11297
11992
  };
11298
11993
  }
@@ -11310,7 +12005,7 @@ function normalizeDocumentParagraphDirection(value) {
11310
12005
  return 'ltr' === normalized || 'rtl' === normalized ? normalized : null;
11311
12006
  }
11312
12007
  function setDocumentLineHeightCommand({ chain }, lineHeight) {
11313
- const value = normalizedLineHeight(lineHeight);
12008
+ const value = work_document_paragraph_formatting_normalizedLineHeight(lineHeight);
11314
12009
  const lineRule = value ? lineRuleForLineHeight(value) : null;
11315
12010
  const attributes = {
11316
12011
  lineHeight: value,
@@ -11338,7 +12033,7 @@ function setDocumentIndentLevelCommand(props, indentLevel, options) {
11338
12033
  }, options);
11339
12034
  }
11340
12035
  function setDocumentParagraphIndentCommand({ chain, editor }, indent, options) {
11341
- const nodeTypes = activeParagraphNodeTypes(editor);
12036
+ const nodeTypes = work_document_paragraph_formatting_activeParagraphNodeTypes(editor);
11342
12037
  if (!nodeTypes.length) return false;
11343
12038
  const normalized = normalizeDocumentParagraphIndent(indent);
11344
12039
  const attributes = {
@@ -11363,7 +12058,7 @@ function setDocumentParagraphDirectionCommand({ chain, editor }, direction, opti
11363
12058
  return commandChain.run();
11364
12059
  }
11365
12060
  function setDocumentParagraphPaginationCommand({ chain, editor }, pagination, options) {
11366
- const nodeTypes = activeParagraphNodeTypes(editor);
12061
+ const nodeTypes = work_document_paragraph_formatting_activeParagraphNodeTypes(editor);
11367
12062
  if (!nodeTypes.length) return false;
11368
12063
  const attributes = {};
11369
12064
  for (const key of documentParagraphPaginationKeys)if (Object.hasOwn(pagination, key)) attributes[key] = Boolean(pagination[key]);
@@ -11374,7 +12069,7 @@ function setDocumentParagraphPaginationCommand({ chain, editor }, pagination, op
11374
12069
  return commandChain.run();
11375
12070
  }
11376
12071
  function clearDocumentParagraphPaginationCommand({ chain, editor }, options) {
11377
- const nodeTypes = activeParagraphNodeTypes(editor);
12072
+ const nodeTypes = work_document_paragraph_formatting_activeParagraphNodeTypes(editor);
11378
12073
  if (!nodeTypes.length) return false;
11379
12074
  const attributes = {
11380
12075
  keepLines: null,
@@ -11388,9 +12083,9 @@ function clearDocumentParagraphPaginationCommand({ chain, editor }, options) {
11388
12083
  return commandChain.run();
11389
12084
  }
11390
12085
  function setDocumentParagraphSpacingCommand({ chain, editor }, spacing, options) {
11391
- const nodeTypes = activeParagraphNodeTypes(editor);
12086
+ const nodeTypes = work_document_paragraph_formatting_activeParagraphNodeTypes(editor);
11392
12087
  if (!nodeTypes.length) return false;
11393
- const lineHeight = normalizedLineHeight(spacing.lineHeight);
12088
+ const lineHeight = work_document_paragraph_formatting_normalizedLineHeight(spacing.lineHeight);
11394
12089
  const lineRule = normalizedLineRule(spacing.lineRule) ?? (lineHeight ? lineRuleForLineHeight(lineHeight) : null);
11395
12090
  const attributes = {
11396
12091
  spaceBefore: normalizedPointSpacing(spacing.before),
@@ -11405,7 +12100,8 @@ function setDocumentParagraphSpacingCommand({ chain, editor }, spacing, options)
11405
12100
  return commandChain.run();
11406
12101
  }
11407
12102
  function clearDocumentFormattingCommand({ chain, editor }) {
11408
- let commandChain = chain().focus().unsetAllMarks();
12103
+ let commandChain = chain().focus();
12104
+ for (const mark of DOCUMENT_CHARACTER_FORMAT_MARKS)if (editor.schema.marks[mark]) commandChain = commandChain.unsetMark(mark);
11409
12105
  if (!editor.isActive('listItem')) commandChain = commandChain.setParagraph();
11410
12106
  return commandChain.unsetTextAlign().updateAttributes('paragraph', {
11411
12107
  indentLevel: 0,
@@ -11440,7 +12136,7 @@ function normalizedIndentLevel(value) {
11440
12136
  if (!Number.isFinite(number)) return 0;
11441
12137
  return Math.min(MAX_DOCUMENT_INDENT_LEVEL, Math.max(0, Math.round(4 * number) / 4));
11442
12138
  }
11443
- function normalizedLineHeight(value) {
12139
+ function work_document_paragraph_formatting_normalizedLineHeight(value) {
11444
12140
  if ('string' != typeof value) return null;
11445
12141
  const normalized = value.trim();
11446
12142
  if (!normalized || 'normal' === normalized) return null;
@@ -11475,7 +12171,7 @@ function renderDocumentAutoLineHeight(lineHeight, autoLineHeight = documentAutoL
11475
12171
  };
11476
12172
  }
11477
12173
  function lineHeightMultiple(value) {
11478
- const normalized = normalizedLineHeight(value);
12174
+ const normalized = work_document_paragraph_formatting_normalizedLineHeight(value);
11479
12175
  if (!normalized) return null;
11480
12176
  const percentage = /^(\d+(?:\.\d+)?)%$/.exec(normalized);
11481
12177
  const multiple = percentage ? Number(percentage[1]) / 100 : /^\d+(?:\.\d+)?$/.test(normalized) ? Number(normalized) : NaN;
@@ -11547,20 +12243,20 @@ function parsedSignedIndentPixels(dataValue, cssValue) {
11547
12243
  function normalizedIndentPixels(value) {
11548
12244
  const number = Number(value);
11549
12245
  if (!Number.isFinite(number)) return 0;
11550
- return Math.min(MAX_DOCUMENT_INDENT_PX, Math.max(0, Math.round(number)));
12246
+ return Math.min(work_document_paragraph_formatting_MAX_DOCUMENT_INDENT_PX, Math.max(0, Math.round(number)));
11551
12247
  }
11552
12248
  function normalizedSignedIndentPixels(value) {
11553
12249
  const number = Number(value);
11554
12250
  if (!Number.isFinite(number)) return 0;
11555
- return Math.min(MAX_DOCUMENT_INDENT_PX, Math.max(-MAX_DOCUMENT_INDENT_PX, Math.round(number)));
12251
+ return Math.min(work_document_paragraph_formatting_MAX_DOCUMENT_INDENT_PX, Math.max(-work_document_paragraph_formatting_MAX_DOCUMENT_INDENT_PX, Math.round(number)));
11556
12252
  }
11557
12253
  function normalizedFirstLineIndent(value, leftIndent) {
11558
- return Math.max(-leftIndent, Math.min(MAX_DOCUMENT_INDENT_PX, normalizedSignedIndentPixels(value)));
12254
+ return Math.max(-leftIndent, Math.min(work_document_paragraph_formatting_MAX_DOCUMENT_INDENT_PX, normalizedSignedIndentPixels(value)));
11559
12255
  }
11560
12256
  function formatPixelValue(value) {
11561
12257
  return Number(value.toFixed(2)).toString();
11562
12258
  }
11563
- function activeParagraphAttributes(editor) {
12259
+ function work_document_paragraph_formatting_activeParagraphAttributes(editor) {
11564
12260
  return editor.isActive('heading') ? editor.getAttributes('heading') : editor.getAttributes('paragraph');
11565
12261
  }
11566
12262
  function paragraphDirectionAttribute() {
@@ -11615,7 +12311,7 @@ function directBoolean(value) {
11615
12311
  if (false === value || 'false' === value || '0' === value) return false;
11616
12312
  return null;
11617
12313
  }
11618
- function activeParagraphNodeTypes(editor) {
12314
+ function work_document_paragraph_formatting_activeParagraphNodeTypes(editor) {
11619
12315
  const nodeTypes = new Set();
11620
12316
  if (editor.isActive('paragraph')) nodeTypes.add('paragraph');
11621
12317
  if (editor.isActive('heading')) nodeTypes.add('heading');
@@ -11632,7 +12328,7 @@ function activeParagraphDirectionNodeTypes(editor) {
11632
12328
  const { from, to } = editor.state.selection;
11633
12329
  if (from === to) return editor.isActive('listItem') ? [
11634
12330
  'listItem'
11635
- ] : activeParagraphNodeTypes(editor);
12331
+ ] : work_document_paragraph_formatting_activeParagraphNodeTypes(editor);
11636
12332
  const nodeTypes = new Set();
11637
12333
  editor.state.doc.nodesBetween(from, to, (node, _position, parent)=>{
11638
12334
  if ('listItem' === node.type.name) nodeTypes.add('listItem');
@@ -11726,108 +12422,6 @@ function elementForNode(editor, position) {
11726
12422
  if (!node || node.nodeType !== Node.ELEMENT_NODE) return null;
11727
12423
  return node;
11728
12424
  }
11729
- const MAX_DOCUMENT_TAB_POSITION_PX = 4096;
11730
- const MAX_DOCUMENT_TAB_STOPS = 64;
11731
- const DocumentParagraphTabStops = Extension.create({
11732
- name: 'documentParagraphTabStops',
11733
- addGlobalAttributes () {
11734
- return [
11735
- {
11736
- types: [
11737
- 'paragraph',
11738
- 'heading'
11739
- ],
11740
- attributes: {
11741
- tabStops: {
11742
- default: null,
11743
- parseHTML: (element)=>normalizeDocumentTabStops(element.dataset.officeTabStops),
11744
- renderHTML: (attributes)=>{
11745
- const tabStops = normalizeDocumentTabStops(attributes.tabStops);
11746
- return tabStops.length ? {
11747
- 'data-office-tab-stops': serializeDocumentTabStops(tabStops)
11748
- } : {};
11749
- }
11750
- }
11751
- }
11752
- }
11753
- ];
11754
- },
11755
- addCommands () {
11756
- return {
11757
- setDocumentParagraphTabStops: (tabStops, options = {})=>({ chain, editor })=>{
11758
- const nodeTypes = work_document_tab_stops_activeParagraphNodeTypes(editor);
11759
- if (!nodeTypes.length) return false;
11760
- const normalized = normalizeDocumentTabStops(tabStops);
11761
- let commandChain = chain();
11762
- if (false !== options.restoreFocus) commandChain = commandChain.focus();
11763
- for (const nodeType of nodeTypes)commandChain = commandChain.updateAttributes(nodeType, {
11764
- tabStops: normalized.length ? normalized : null
11765
- });
11766
- return commandChain.run();
11767
- }
11768
- };
11769
- }
11770
- });
11771
- function documentParagraphTabStops(editor) {
11772
- return normalizeDocumentTabStops(work_document_tab_stops_activeParagraphAttributes(editor).tabStops);
11773
- }
11774
- function normalizeDocumentTabStops(value) {
11775
- const source = parsedTabStopSource(value);
11776
- const byPosition = new Map();
11777
- for (const candidate of source.slice(0, 4 * MAX_DOCUMENT_TAB_STOPS)){
11778
- if (!work_document_tab_stops_isRecord(candidate)) continue;
11779
- const rawPosition = Number(candidate.position);
11780
- if (!Number.isFinite(rawPosition) || rawPosition <= 0) continue;
11781
- const position = normalizedTabPosition(rawPosition);
11782
- if (!(position <= 0)) byPosition.set(position, {
11783
- position,
11784
- alignment: normalizedTabAlignment(candidate.alignment),
11785
- leader: normalizedTabLeader(candidate.leader)
11786
- });
11787
- }
11788
- return Array.from(byPosition.values()).sort((left, right)=>left.position - right.position).slice(0, MAX_DOCUMENT_TAB_STOPS);
11789
- }
11790
- function serializeDocumentTabStops(value) {
11791
- return JSON.stringify(normalizeDocumentTabStops(value));
11792
- }
11793
- function normalizedTabPosition(value) {
11794
- if (!Number.isFinite(value)) return 0;
11795
- return Math.min(MAX_DOCUMENT_TAB_POSITION_PX, Math.max(0, Math.round(100 * value) / 100));
11796
- }
11797
- function nextDocumentTabAlignment(alignment) {
11798
- if ('left' === alignment) return 'center';
11799
- if ('center' === alignment) return 'right';
11800
- if ('right' === alignment) return 'decimal';
11801
- return 'left';
11802
- }
11803
- function parsedTabStopSource(value) {
11804
- if (Array.isArray(value)) return value;
11805
- if ('string' != typeof value || !value.trim()) return [];
11806
- try {
11807
- const parsed = JSON.parse(value);
11808
- return Array.isArray(parsed) ? parsed : [];
11809
- } catch {
11810
- return [];
11811
- }
11812
- }
11813
- function normalizedTabAlignment(value) {
11814
- return 'center' === value || 'right' === value || 'decimal' === value ? value : 'left';
11815
- }
11816
- function normalizedTabLeader(value) {
11817
- return 'dot' === value || 'hyphen' === value || 'underscore' === value || 'middleDot' === value ? value : 'none';
11818
- }
11819
- function work_document_tab_stops_activeParagraphAttributes(editor) {
11820
- return editor.isActive('heading') ? editor.getAttributes('heading') : editor.getAttributes('paragraph');
11821
- }
11822
- function work_document_tab_stops_activeParagraphNodeTypes(editor) {
11823
- const types = [];
11824
- if (editor.isActive('paragraph')) types.push('paragraph');
11825
- if (editor.isActive('heading')) types.push('heading');
11826
- return types;
11827
- }
11828
- function work_document_tab_stops_isRecord(value) {
11829
- return 'object' == typeof value && null !== value && !Array.isArray(value);
11830
- }
11831
12425
  const MAX_DOCUMENT_TEXT_LAYOUT_PARAGRAPHS = 16384;
11832
12426
  const MAX_DOCUMENT_TEXT_LAYOUT_RUNS = 16384;
11833
12427
  const MAX_DOCUMENT_TEXT_LAYOUT_BYTES = 1048576;
@@ -16064,9 +16658,9 @@ function changeIdentity(decision) {
16064
16658
  return `${decision.changeKind}:${decision.changeId}`;
16065
16659
  }
16066
16660
  function office_document_collaboration_change_decisions_changeKind(value, shared) {
16067
- if ('insertion' === value || 'deletion' === value) return value;
16661
+ if ('insertion' === value || 'deletion' === value || 'formatting' === value || 'paragraph-formatting' === value) return value;
16068
16662
  if (shared) invalidSharedSidecars('tracked-change decision kind');
16069
- invalidInputSidecars('an insertion or deletion tracked-change kind');
16663
+ invalidInputSidecars('an insertion, deletion, formatting, or paragraph-formatting tracked-change kind');
16070
16664
  }
16071
16665
  function decisionAction(value, shared) {
16072
16666
  if ('accept' === value || 'reject' === value) return value;
@@ -16727,7 +17321,14 @@ function strictDocumentChanges(document1) {
16727
17321
  const changes = new Map();
16728
17322
  let valid = true;
16729
17323
  document1.descendants((node)=>{
16730
- if (!valid || !node.isText || !node.text) return;
17324
+ if (!valid) return;
17325
+ if ('paragraph' === node.type.name || 'heading' === node.type.name) {
17326
+ if (!strictParagraphFormattingChange(node)) {
17327
+ valid = false;
17328
+ return false;
17329
+ }
17330
+ }
17331
+ if (!node.isText || !node.text) return;
16731
17332
  const marks = node.marks.filter((mark)=>'documentChange' === mark.type.name);
16732
17333
  if (0 === marks.length) return;
16733
17334
  if (1 !== marks.length) {
@@ -16740,10 +17341,11 @@ function strictDocumentChanges(document1) {
16740
17341
  const author = strictString(mark.attrs.author);
16741
17342
  const date = strictString(mark.attrs.date);
16742
17343
  const actorId = optionalStrictString(mark.attrs.actorId);
16743
- if (!id || !kind || null === author || null === date || null === actorId) {
17344
+ if (!id || !kind || null === author || null === date || null === actorId || 'formatting' === kind && !parseDocumentCharacterFormatting(mark.attrs.before)) {
16744
17345
  valid = false;
16745
17346
  return false;
16746
17347
  }
17348
+ if ('formatting' === kind) return;
16747
17349
  const current = changes.get(id);
16748
17350
  const candidate = {
16749
17351
  id,
@@ -16769,7 +17371,7 @@ function documentSuggestionBaseline(node) {
16769
17371
  if (node.isText) {
16770
17372
  const change = node.marks.find((mark)=>'documentChange' === mark.type.name);
16771
17373
  if (change?.attrs.kind === 'insertion') return null;
16772
- const marks = node.marks.filter((mark)=>'documentChange' !== mark.type.name).map((mark)=>mark.toJSON());
17374
+ const marks = node.marks.filter((mark)=>'documentChange' !== mark.type.name || 'formatting' === mark.attrs.kind).map((mark)=>mark.toJSON());
16773
17375
  if (marks.length > 0) return {
16774
17376
  ...json,
16775
17377
  marks
@@ -16816,7 +17418,19 @@ function optionalStrictString(value) {
16816
17418
  return strictString(value);
16817
17419
  }
16818
17420
  function strictChangeKind(value) {
16819
- return 'insertion' === value || 'deletion' === value ? value : null;
17421
+ return 'insertion' === value || 'deletion' === value || 'formatting' === value ? value : null;
17422
+ }
17423
+ function strictParagraphFormattingChange(node) {
17424
+ const kind = node.attrs.paragraphChangeKind;
17425
+ const fields = [
17426
+ node.attrs.paragraphChangeId,
17427
+ node.attrs.paragraphChangeActorId,
17428
+ node.attrs.paragraphChangeAuthor,
17429
+ node.attrs.paragraphChangeDate,
17430
+ node.attrs.paragraphChangeBefore
17431
+ ];
17432
+ if ('paragraph-formatting' !== kind) return (null == kind || '' === kind) && fields.every((field)=>null == field || '' === field);
17433
+ return Boolean(strictString(node.attrs.paragraphChangeId) && null !== optionalStrictString(node.attrs.paragraphChangeActorId) && strictString(node.attrs.paragraphChangeAuthor) && strictString(node.attrs.paragraphChangeDate) && parseDocumentParagraphFormatting(node.attrs.paragraphChangeBefore));
16820
17434
  }
16821
17435
  const DOCUMENT_CONTENT_ROOT = 'document.content';
16822
17436
  const MAX_DOCUMENT_COMMENT_HISTORY = 100;
@@ -17468,4 +18082,4 @@ function capturePages(surface) {
17468
18082
  width: surface.pageWidth
17469
18083
  }));
17470
18084
  }
17471
- export { DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DEFAULT_DOCUMENT_TABLE_GEOMETRY, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, DOCUMENT_PAGE_BORDER_EDGES, DOCUMENT_PAGE_MARGIN_KEYS, DOCUMENT_PARAGRAPH_BORDER_EDGES, DOCUMENT_PARAGRAPH_BORDER_STYLES, DOCUMENT_PARAGRAPH_SHADING_PATTERNS, DOCUMENT_TABLE_ROW_ID_ATTRIBUTE, DOCUMENT_TABLE_ROW_TEXT_ID_ATTRIBUTE, DOCUMENT_TABLE_STYLE_OPTIONS, DocumentEquation, DocumentImage, DocumentParagraphFormatting, DocumentParagraphIdentity, DocumentSubscript, DocumentSuperscript, DocumentTableRowIdentity, DocxThemePatchCollector, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, MAX_DOCUMENT_NUMBERING_START, activeDocumentBookmark, activeDocumentSection, activeDocumentTableStyle, applyDocumentImageCropToElement, applyDocumentImageIdentityToElement, applyDocumentImageLayerToElement, applyDocumentImageWrapContourToElement, applyDocumentPageGeometry, applyDocumentParagraphIdentityToElement, applyDocumentTableGeometryToElement, applyDocumentTableRowIdentityToElement, canChangeDocumentIndent, canInsertDocumentComment, canSetDocumentTableRowRepeatHeader, clampDocumentMargin, collectDocumentChanges, collectDocumentCommentAnchors, collectDocumentNotes, collectDocumentTextLayoutParagraphs, createDocumentBibliography, createDocumentEquationElement, createDocumentImageIdentityRegistry, createDocumentNoteElement, createDocumentParagraphIdentityRegistry, createWorkDocumentExtensions, createWorkDocumentModel, createWorkDocumentModelFromContent, createWorkOfficeDocumentCollaborationBinding as createOfficeDocumentCollaborationBinding, defaultDocumentImageWrapContour, documentAutoLineHeight, documentBookmarkNameExists, documentBookmarkReferenceInstruction, documentBulletListStyle, documentCaptionKind, documentCaptionLabel, documentCitationCount, documentCitationInstruction, documentCitationStyle, documentCitationStyleDetails, documentCitationTags, documentCitationTagsFromInstruction, documentCommentDraftRange, documentCommentViews, documentContentLayoutProperties, documentEquationFromElement, documentEquationText, documentImageCropFromElement, documentImageIdentityFromElement, documentImageLayerFromElement, documentImageLayoutFromElement, documentImageLayoutOptions, documentImagePositionFromElement, documentImageProperties, documentImageWrapContourFromElement, documentInitialSectionLayout, documentModelForContent, documentNoteKey, documentNoteKind, documentOrderedListState, documentPageBordersVisible, documentPageChromeLegacyFields, documentPageGeometryForLayout, documentPageHorizontalMarginTwips, documentPageMarginBody, documentPageMarginsForLayout, documentPageMetrics, documentParagraphBordersDomAttributes, documentParagraphDirection, documentParagraphIdentityFromElement, documentParagraphIndent, documentParagraphPagination, documentParagraphShadingDomAttributes, documentParagraphSpacing, documentParagraphTabStops, documentSectionById, documentSectionDomAttributes, documentSections, documentTabLeaderLabel, documentTableBordersFromElement, documentTableCellFormat, documentTableCellMarginOverridesFromElement, documentTableColumnPercentagesFromElement, documentTableGeometryFromElement, documentTableHorizontalAlignment, documentTableRowIdentityFromElement, documentTableRowOptions, documentTableSizing, documentTextLayoutBatches, documentWordLineHeightFactor, docxBookmarkReferenceTarget, docxDocumentFieldKind, editorDocumentBookmarkReferenceTargets, editorDocumentCaptionTargets, initializeWorkOfficeDocumentCollaboration as initializeOfficeDocumentCollaboration, isContourImageLayout, isDocumentParagraphArtBorderStyle, isValidDocumentCitationTag, materializeWorkDocumentContent, measureDocumentLayoutBlocksIncrementally, millimetersToPixels, mountWorkLiveDocumentCapture, nextDocumentTabAlignment, normalizeDocumentBookmarkName, normalizeDocumentBookmarkNativeId, normalizeDocumentBookmarkReferencesHtml, normalizeDocumentBookmarksHtml, normalizeDocumentCaptionsHtml, normalizeDocumentCitationsHtml, normalizeDocumentColumns, normalizeDocumentEquation, normalizeDocumentFieldsHtml, normalizeDocumentHtml, normalizeDocumentImageAlignment, normalizeDocumentImageCrop, normalizeDocumentImageIdentity, normalizeDocumentImageLayer, normalizeDocumentImageLayoutOptions, normalizeDocumentImagePosition, normalizeDocumentImageWrapContour, normalizeDocumentImageWrapSide, normalizeDocumentNotesHtml, normalizeDocumentPageBorders, normalizeDocumentPageChrome, normalizeDocumentPageGeometry, normalizeDocumentPageMargins, normalizeDocumentPaperSource, normalizeDocumentParagraphBorder, normalizeDocumentParagraphBorders, normalizeDocumentParagraphId, normalizeDocumentParagraphIdentity, normalizeDocumentParagraphIndent, normalizeDocumentTabStops, normalizeDocumentTableBorderStyle, normalizeDocumentTableBorderWidth, normalizeDocumentTableRowHeightRule, normalizeDocumentTableRowIdentity, normalizeDocumentTableVerticalAlign, normalizeTableColor, normalizedTabPosition, pageTwipsToMillimeters, parseDocumentParagraphBordersElement, parseDocumentParagraphShadingElement, parseDocxThemeReference, patchDocxThemeReferences, positionWorkLiveDocumentCapture, readWorkOfficeDocumentCollaboration as readOfficeDocumentCollaboration, renderDocumentAutoLineHeight, renderDocumentTableBorders, renderDocumentTableCellMarginOverrides, resolveDocumentPageBorders, resolveDocumentPageChrome, resolveDocumentPageMargins, resolveDocumentPageSize, resolveWorkDocumentEditorInput, retainAnchoredDocumentComments, sanitizeDocumentPageChromeHtml, serializeDocumentTabStops, serializeDocxThemeReference, serializeWorkDocumentNode, setCustomDocumentColumns, supportedDocxBookmarkReferenceInstruction, syncDocumentContentFromHtml, uniqueDocumentImageIdentity, uniqueDocumentParagraphIdentity, updateDocumentColumnWidth, updateDocumentCustomPageMillimeters, updateDocumentGutterPosition, updateDocumentMirrorMargins, updateDocumentPageChromeVariant, updateDocumentPageMarginMillimeters, updateDocumentPageMarginMode, updateDocumentPageOrientation, updateDocumentPaperSizePreset, validateDocumentBookmarkName, workDocumentSchema, workOfficeDocumentCollaborationFragment as officeDocumentCollaborationFragment, work_document_page_margins_twipsToMillimeters, wrapsBesideImage };
18085
+ export { DEFAULT_DOCUMENT_TABLE_CELL_FORMAT, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, DEFAULT_DOCUMENT_TABLE_GEOMETRY, DOCUMENT_BOOKMARK_DUPLICATE_MESSAGE, DOCUMENT_PAGE_BORDER_EDGES, DOCUMENT_PAGE_MARGIN_KEYS, DOCUMENT_PARAGRAPH_BORDER_EDGES, DOCUMENT_PARAGRAPH_BORDER_STYLES, DOCUMENT_PARAGRAPH_SHADING_PATTERNS, DOCUMENT_TABLE_ROW_ID_ATTRIBUTE, DOCUMENT_TABLE_ROW_TEXT_ID_ATTRIBUTE, DOCUMENT_TABLE_STYLE_OPTIONS, DocumentEquation, DocumentImage, DocumentParagraphFormatting, DocumentParagraphIdentity, DocumentSubscript, DocumentSuperscript, DocumentTableRowIdentity, DocxThemePatchCollector, MAX_DOCUMENT_IMAGE_RELATIVE_HEIGHT, MAX_DOCUMENT_NUMBERING_START, activeDocumentBookmark, activeDocumentSection, activeDocumentTableStyle, applyDocumentImageCropToElement, applyDocumentImageIdentityToElement, applyDocumentImageLayerToElement, applyDocumentImageWrapContourToElement, applyDocumentPageGeometry, applyDocumentParagraphIdentityToElement, applyDocumentTableGeometryToElement, applyDocumentTableRowIdentityToElement, canChangeDocumentIndent, canInsertDocumentComment, canSetDocumentTableRowRepeatHeader, clampDocumentMargin, collectDocumentChanges, collectDocumentCommentAnchors, collectDocumentNotes, collectDocumentTextLayoutParagraphs, createDocumentBibliography, createDocumentEquationElement, createDocumentImageIdentityRegistry, createDocumentNoteElement, createDocumentParagraphIdentityRegistry, createWorkDocumentExtensions, createWorkDocumentModel, createWorkDocumentModelFromContent, createWorkOfficeDocumentCollaborationBinding as createOfficeDocumentCollaborationBinding, defaultDocumentImageWrapContour, documentAutoLineHeight, documentBookmarkNameExists, documentBookmarkReferenceInstruction, documentBulletListStyle, documentCaptionKind, documentCaptionLabel, documentCitationCount, documentCitationInstruction, documentCitationStyle, documentCitationStyleDetails, documentCitationTags, documentCitationTagsFromInstruction, documentCommentDraftRange, documentCommentViews, documentContentLayoutProperties, documentEquationFromElement, documentEquationText, documentImageCropFromElement, documentImageIdentityFromElement, documentImageLayerFromElement, documentImageLayoutFromElement, documentImageLayoutOptions, documentImagePositionFromElement, documentImageProperties, documentImageWrapContourFromElement, documentInitialSectionLayout, documentModelForContent, documentNoteKey, documentNoteKind, documentOrderedListState, documentPageBordersVisible, documentPageChromeLegacyFields, documentPageGeometryForLayout, documentPageHorizontalMarginTwips, documentPageMarginBody, documentPageMarginsForLayout, documentPageMetrics, documentParagraphBordersDomAttributes, documentParagraphDirection, documentParagraphIdentityFromElement, documentParagraphIndent, documentParagraphPagination, documentParagraphShadingDomAttributes, documentParagraphSpacing, documentParagraphTabStops, documentSectionById, documentSectionDomAttributes, documentSections, documentTabLeaderLabel, documentTableBordersFromElement, documentTableCellFormat, documentTableCellMarginOverridesFromElement, documentTableColumnPercentagesFromElement, documentTableGeometryFromElement, documentTableHorizontalAlignment, documentTableRowIdentityFromElement, documentTableRowOptions, documentTableSizing, documentTextLayoutBatches, documentWordLineHeightFactor, docxBookmarkReferenceTarget, docxDocumentFieldKind, editorDocumentBookmarkReferenceTargets, editorDocumentCaptionTargets, importedDocumentCharacterFormatting, initializeWorkOfficeDocumentCollaboration as initializeOfficeDocumentCollaboration, isContourImageLayout, isDocumentParagraphArtBorderStyle, isValidDocumentCitationTag, materializeWorkDocumentContent, measureDocumentLayoutBlocksIncrementally, millimetersToPixels, mountWorkLiveDocumentCapture, nextDocumentTabAlignment, normalizeDocumentBookmarkName, normalizeDocumentBookmarkNativeId, normalizeDocumentBookmarkReferencesHtml, normalizeDocumentBookmarksHtml, normalizeDocumentCaptionsHtml, normalizeDocumentCitationsHtml, normalizeDocumentColumns, normalizeDocumentEquation, normalizeDocumentFieldsHtml, normalizeDocumentHtml, normalizeDocumentImageAlignment, normalizeDocumentImageCrop, normalizeDocumentImageIdentity, normalizeDocumentImageLayer, normalizeDocumentImageLayoutOptions, normalizeDocumentImagePosition, normalizeDocumentImageWrapContour, normalizeDocumentImageWrapSide, normalizeDocumentNotesHtml, normalizeDocumentPageBorders, normalizeDocumentPageChrome, normalizeDocumentPageGeometry, normalizeDocumentPageMargins, normalizeDocumentPaperSource, normalizeDocumentParagraphBorder, normalizeDocumentParagraphBorders, normalizeDocumentParagraphId, normalizeDocumentParagraphIdentity, normalizeDocumentParagraphIndent, normalizeDocumentTabStops, normalizeDocumentTableBorderStyle, normalizeDocumentTableBorderWidth, normalizeDocumentTableRowHeightRule, normalizeDocumentTableRowIdentity, normalizeDocumentTableVerticalAlign, normalizeTableColor, normalizedTabPosition, pageTwipsToMillimeters, parseDocumentCharacterFormatting, parseDocumentParagraphBordersElement, parseDocumentParagraphFormatting, parseDocumentParagraphShadingElement, parseDocxThemeReference, patchDocxThemeReferences, positionWorkLiveDocumentCapture, readWorkOfficeDocumentCollaboration as readOfficeDocumentCollaboration, renderDocumentAutoLineHeight, renderDocumentTableBorders, renderDocumentTableCellMarginOverrides, resolveDocumentPageBorders, resolveDocumentPageChrome, resolveDocumentPageMargins, resolveDocumentPageSize, resolveWorkDocumentEditorInput, retainAnchoredDocumentComments, sanitizeDocumentPageChromeHtml, serializeDocumentParagraphFormatting, serializeDocumentTabStops, serializeDocxThemeReference, serializeWorkDocumentNode, setCustomDocumentColumns, supportedDocxBookmarkReferenceInstruction, syncDocumentContentFromHtml, uniqueDocumentImageIdentity, uniqueDocumentParagraphIdentity, updateDocumentColumnWidth, updateDocumentCustomPageMillimeters, updateDocumentGutterPosition, updateDocumentMirrorMargins, updateDocumentPageChromeVariant, updateDocumentPageMarginMillimeters, updateDocumentPageMarginMode, updateDocumentPageOrientation, updateDocumentPaperSizePreset, validateDocumentBookmarkName, workDocumentSchema, workOfficeDocumentCollaborationFragment as officeDocumentCollaborationFragment, work_document_page_margins_twipsToMillimeters, wrapsBesideImage };