@a3s-lab/office 0.9.2 → 0.10.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.
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,265 @@ 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
+ function trackDocumentFormattingTransaction(transaction, state, type, options, pluginKey) {
8555
+ if (!options.isTracking() || state.doc.eq(transaction.doc)) return;
8556
+ const sync = transaction.getMeta(ySyncPluginKey);
8557
+ if (transaction.getMeta(pluginKey) || sync?.isChangeOrigin || isHistoryTransaction(transaction)) return;
8558
+ const ranges = formattingStepRanges(transaction);
8559
+ if (!ranges.length) return;
8560
+ const formattedDocument = transaction.doc;
8561
+ let identity = null;
8562
+ for (const range of ranges)for (const segment of formattingSegments(state.doc, formattedDocument, range)){
8563
+ const beforeMarks = textMarksAt(state.doc, segment.from, segment.to);
8564
+ const afterMarks = textMarksAt(formattedDocument, segment.from, segment.to);
8565
+ if (!beforeMarks || !afterMarks) continue;
8566
+ if (state.doc.textBetween(segment.from, segment.to) !== formattedDocument.textBetween(segment.from, segment.to)) continue;
8567
+ const before = serializeDocumentCharacterFormatting(beforeMarks);
8568
+ const after = serializeDocumentCharacterFormatting(afterMarks);
8569
+ if (!(before === after || documentChangeMark(afterMarks))) {
8570
+ identity ??= options.createChange();
8571
+ transaction.addMark(segment.from, segment.to, type.create({
8572
+ kind: 'formatting',
8573
+ id: identity.id,
8574
+ actorId: identity.actorId ?? '',
8575
+ author: identity.author || 'A3S Work',
8576
+ date: identity.date || new Date().toISOString(),
8577
+ before
8578
+ }));
8579
+ }
8580
+ }
8581
+ if (identity) transaction.setMeta(pluginKey, {
8582
+ formatting: true
8583
+ });
8584
+ }
8585
+ function formattingStepRanges(transaction) {
8586
+ if (transaction.steps.some((step)=>step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) return [];
8587
+ const ranges = [];
8588
+ for (const step of transaction.steps)if ((step instanceof AddMarkStep || step instanceof RemoveMarkStep) && isDocumentCharacterFormatMark(step.mark.type.name) && step.from < step.to) ranges.push({
8589
+ from: step.from,
8590
+ to: step.to
8591
+ });
8592
+ return mergeFormattingRanges(ranges);
8593
+ }
8594
+ function mergeFormattingRanges(ranges) {
8595
+ const merged = [];
8596
+ for (const range of ranges.sort((left, right)=>left.from - right.from)){
8597
+ const previous = merged.at(-1);
8598
+ if (!previous || range.from > previous.to) {
8599
+ merged.push({
8600
+ ...range
8601
+ });
8602
+ continue;
8603
+ }
8604
+ previous.to = Math.max(previous.to, range.to);
8605
+ }
8606
+ return merged;
8607
+ }
8608
+ function formattingSegments(before, after, range) {
8609
+ const boundaries = new Set([
8610
+ range.from,
8611
+ range.to
8612
+ ]);
8613
+ collectFormattingBoundaries(before, range, boundaries);
8614
+ collectFormattingBoundaries(after, range, boundaries);
8615
+ const ordered = Array.from(boundaries).sort((left, right)=>left - right);
8616
+ return ordered.slice(0, -1).flatMap((from, index)=>{
8617
+ const to = ordered[index + 1];
8618
+ return void 0 !== to && from < to ? [
8619
+ {
8620
+ from,
8621
+ to
8622
+ }
8623
+ ] : [];
8624
+ });
8625
+ }
8626
+ function collectFormattingBoundaries(document1, range, boundaries) {
8627
+ document1.nodesBetween(range.from, range.to, (node, position)=>{
8628
+ if (!node.isText) return;
8629
+ boundaries.add(Math.max(range.from, position));
8630
+ boundaries.add(Math.min(range.to, position + node.nodeSize));
8631
+ });
8632
+ }
8633
+ function textMarksAt(document1, from, to) {
8634
+ let marks = null;
8635
+ document1.nodesBetween(from, to, (node, position)=>{
8636
+ if (marks || !node.isText || position > from || position + node.nodeSize < to) return;
8637
+ marks = node.marks;
8638
+ });
8639
+ return marks;
8640
+ }
8641
+ function documentChangeMark(marks) {
8642
+ return marks.find((mark)=>'documentChange' === mark.type.name);
8643
+ }
8385
8644
  const documentChangePluginKey = new PluginKey('documentChangeTracking');
8386
8645
  const CONTINUOUS_INSERTION_WINDOW_MS = 30000;
8387
8646
  const DocumentChange = Mark.create({
@@ -8404,7 +8663,11 @@ const DocumentChange = Mark.create({
8404
8663
  return {
8405
8664
  kind: {
8406
8665
  default: 'insertion',
8407
- parseHTML: (element)=>'del' === element.tagName.toLowerCase() ? 'deletion' : 'insertion',
8666
+ parseHTML: (element)=>{
8667
+ const declared = element.getAttribute('data-change-kind');
8668
+ if ('formatting' === declared) return 'formatting';
8669
+ return 'del' === element.tagName.toLowerCase() ? 'deletion' : 'insertion';
8670
+ },
8408
8671
  renderHTML: (attributes)=>({
8409
8672
  'data-change-kind': attributes.kind
8410
8673
  })
@@ -8436,6 +8699,13 @@ const DocumentChange = Mark.create({
8436
8699
  renderHTML: (attributes)=>({
8437
8700
  'data-change-date': attributes.date
8438
8701
  })
8702
+ },
8703
+ before: {
8704
+ default: '',
8705
+ parseHTML: (element)=>element.getAttribute('data-change-before') ?? '',
8706
+ renderHTML: (attributes)=>attributes.before ? {
8707
+ 'data-change-before': attributes.before
8708
+ } : {}
8439
8709
  }
8440
8710
  };
8441
8711
  },
@@ -8446,12 +8716,16 @@ const DocumentChange = Mark.create({
8446
8716
  },
8447
8717
  {
8448
8718
  tag: 'del[data-document-change]'
8719
+ },
8720
+ {
8721
+ tag: 'span[data-document-change][data-change-kind="formatting"]'
8449
8722
  }
8450
8723
  ];
8451
8724
  },
8452
8725
  renderHTML ({ mark, HTMLAttributes }) {
8726
+ const tag = 'deletion' === mark.attrs.kind ? 'del' : 'formatting' === mark.attrs.kind ? 'span' : 'ins';
8453
8727
  return [
8454
- 'deletion' === mark.attrs.kind ? 'del' : 'ins',
8728
+ tag,
8455
8729
  mergeAttributes(HTMLAttributes, {
8456
8730
  'data-document-change': 'true'
8457
8731
  }),
@@ -8491,6 +8765,19 @@ const DocumentChange = Mark.create({
8491
8765
  return [
8492
8766
  new Plugin({
8493
8767
  key: documentChangePluginKey,
8768
+ filterTransaction: (transaction, state)=>{
8769
+ trackDocumentFormattingTransaction(transaction, state, changeType, {
8770
+ isTracking: options.isTracking,
8771
+ createChange: ()=>{
8772
+ const identity = options.createChange('formatting');
8773
+ return {
8774
+ ...identity,
8775
+ id: identity.id || createDocumentChangeId()
8776
+ };
8777
+ }
8778
+ }, documentChangePluginKey);
8779
+ return true;
8780
+ },
8494
8781
  props: {
8495
8782
  handleTextInput: (view, from, to, text)=>{
8496
8783
  if (!options.isTracking()) return false;
@@ -8537,7 +8824,7 @@ function collectDocumentChanges(document1) {
8537
8824
  const changes = new Map();
8538
8825
  document1.descendants((node, position)=>{
8539
8826
  if (!node.isText || !node.text) return;
8540
- const mark = documentChangeMark(node.marks);
8827
+ const mark = work_document_changes_documentChangeMark(node.marks);
8541
8828
  if (!mark) return;
8542
8829
  const kind = changeKind(mark.attrs.kind);
8543
8830
  const id = work_document_changes_stringAttribute(mark.attrs.id) || `change-at-${position}`;
@@ -8567,14 +8854,25 @@ function collectDocumentChanges(document1) {
8567
8854
  function resolveDocumentChangesCommand({ state, tr }, type, decision, ids) {
8568
8855
  const segments = documentChangeSegments(state.doc, type).filter((segment)=>!ids || ids.has(segment.id));
8569
8856
  if (!segments.length) return 0;
8570
- const removals = [];
8571
- const deletions = [];
8857
+ if ('reject' === decision && segments.some((segment)=>'formatting' === segment.kind && !parseDocumentCharacterFormatting(segment.before))) return 0;
8858
+ tr.setMeta(documentChangePluginKey, {
8859
+ decision
8860
+ });
8861
+ const markRemovals = [];
8862
+ const contentDeletions = [];
8863
+ const formattingRejections = [];
8572
8864
  for (const segment of segments){
8573
- const remove = 'accept' === decision && 'insertion' === segment.kind || 'reject' === decision && 'deletion' === segment.kind;
8574
- (remove ? removals : deletions).push(segment);
8865
+ if ('formatting' === segment.kind) {
8866
+ markRemovals.push(segment);
8867
+ if ('reject' === decision) formattingRejections.push(segment);
8868
+ continue;
8869
+ }
8870
+ const removeMark = 'accept' === decision && 'insertion' === segment.kind || 'reject' === decision && 'deletion' === segment.kind;
8871
+ (removeMark ? markRemovals : contentDeletions).push(segment);
8575
8872
  }
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);
8873
+ for (const segment of formattingRejections)restoreDocumentCharacterFormatting(tr, state.schema, segment.from, segment.to, segment.before);
8874
+ for (const segment of markRemovals)tr.removeMark(segment.from, segment.to, type);
8875
+ for (const segment of contentDeletions.sort((left, right)=>right.from - left.from))tr.delete(segment.from, segment.to);
8578
8876
  return tr.docChanged ? new Set(segments.map((segment)=>segment.id)).size : 0;
8579
8877
  }
8580
8878
  function trackedReplacement(transaction, document1, type, from, to, text, createChange) {
@@ -8622,7 +8920,8 @@ function documentChangeSegments(document1, type) {
8622
8920
  id: work_document_changes_stringAttribute(mark.attrs.id) || `change-at-${position}`,
8623
8921
  kind: changeKind(mark.attrs.kind),
8624
8922
  from: position,
8625
- to: position + node.nodeSize
8923
+ to: position + node.nodeSize,
8924
+ before: work_document_changes_stringAttribute(mark.attrs.before)
8626
8925
  });
8627
8926
  });
8628
8927
  return segments;
@@ -8653,14 +8952,15 @@ function adjacentTextRange(document1, position, direction) {
8653
8952
  to: position + character.length
8654
8953
  };
8655
8954
  }
8656
- function changeMark(type, kind, createChange) {
8955
+ function changeMark(type, kind, createChange, before = '') {
8657
8956
  const identity = createChange(kind);
8658
8957
  return type.create({
8659
8958
  kind,
8660
8959
  id: identity.id || createDocumentChangeId(),
8661
8960
  actorId: identity.actorId ?? '',
8662
8961
  author: identity.author || 'A3S Work',
8663
- date: identity.date || new Date().toISOString()
8962
+ date: identity.date || new Date().toISOString(),
8963
+ before
8664
8964
  });
8665
8965
  }
8666
8966
  function continuousInsertionMark(document1, type, position, createChange) {
@@ -8674,11 +8974,12 @@ function continuousInsertionMark(document1, type, position, createChange) {
8674
8974
  if (!Number.isFinite(previousTime) || !Number.isFinite(nextTime) || Math.abs(nextTime - previousTime) > CONTINUOUS_INSERTION_WINDOW_MS) return next;
8675
8975
  return previous;
8676
8976
  }
8677
- function documentChangeMark(marks) {
8977
+ function work_document_changes_documentChangeMark(marks) {
8678
8978
  return marks.find((mark)=>'documentChange' === mark.type.name);
8679
8979
  }
8680
8980
  function changeKind(value) {
8681
- return 'deletion' === value ? 'deletion' : 'insertion';
8981
+ if ('deletion' === value || 'formatting' === value) return value;
8982
+ return 'insertion';
8682
8983
  }
8683
8984
  function work_document_changes_stringAttribute(value) {
8684
8985
  return 'string' == typeof value ? value : '';
@@ -11405,7 +11706,8 @@ function setDocumentParagraphSpacingCommand({ chain, editor }, spacing, options)
11405
11706
  return commandChain.run();
11406
11707
  }
11407
11708
  function clearDocumentFormattingCommand({ chain, editor }) {
11408
- let commandChain = chain().focus().unsetAllMarks();
11709
+ let commandChain = chain().focus();
11710
+ for (const mark of DOCUMENT_CHARACTER_FORMAT_MARKS)if (editor.schema.marks[mark]) commandChain = commandChain.unsetMark(mark);
11409
11711
  if (!editor.isActive('listItem')) commandChain = commandChain.setParagraph();
11410
11712
  return commandChain.unsetTextAlign().updateAttributes('paragraph', {
11411
11713
  indentLevel: 0,
@@ -16064,9 +16366,9 @@ function changeIdentity(decision) {
16064
16366
  return `${decision.changeKind}:${decision.changeId}`;
16065
16367
  }
16066
16368
  function office_document_collaboration_change_decisions_changeKind(value, shared) {
16067
- if ('insertion' === value || 'deletion' === value) return value;
16369
+ if ('insertion' === value || 'deletion' === value || 'formatting' === value) return value;
16068
16370
  if (shared) invalidSharedSidecars('tracked-change decision kind');
16069
- invalidInputSidecars('an insertion or deletion tracked-change kind');
16371
+ invalidInputSidecars('an insertion, deletion, or formatting tracked-change kind');
16070
16372
  }
16071
16373
  function decisionAction(value, shared) {
16072
16374
  if ('accept' === value || 'reject' === value) return value;
@@ -16740,10 +17042,11 @@ function strictDocumentChanges(document1) {
16740
17042
  const author = strictString(mark.attrs.author);
16741
17043
  const date = strictString(mark.attrs.date);
16742
17044
  const actorId = optionalStrictString(mark.attrs.actorId);
16743
- if (!id || !kind || null === author || null === date || null === actorId) {
17045
+ if (!id || !kind || null === author || null === date || null === actorId || 'formatting' === kind && !parseDocumentCharacterFormatting(mark.attrs.before)) {
16744
17046
  valid = false;
16745
17047
  return false;
16746
17048
  }
17049
+ if ('formatting' === kind) return;
16747
17050
  const current = changes.get(id);
16748
17051
  const candidate = {
16749
17052
  id,
@@ -16769,7 +17072,7 @@ function documentSuggestionBaseline(node) {
16769
17072
  if (node.isText) {
16770
17073
  const change = node.marks.find((mark)=>'documentChange' === mark.type.name);
16771
17074
  if (change?.attrs.kind === 'insertion') return null;
16772
- const marks = node.marks.filter((mark)=>'documentChange' !== mark.type.name).map((mark)=>mark.toJSON());
17075
+ const marks = node.marks.filter((mark)=>'documentChange' !== mark.type.name || 'formatting' === mark.attrs.kind).map((mark)=>mark.toJSON());
16773
17076
  if (marks.length > 0) return {
16774
17077
  ...json,
16775
17078
  marks
@@ -16816,7 +17119,7 @@ function optionalStrictString(value) {
16816
17119
  return strictString(value);
16817
17120
  }
16818
17121
  function strictChangeKind(value) {
16819
- return 'insertion' === value || 'deletion' === value ? value : null;
17122
+ return 'insertion' === value || 'deletion' === value || 'formatting' === value ? value : null;
16820
17123
  }
16821
17124
  const DOCUMENT_CONTENT_ROOT = 'document.content';
16822
17125
  const MAX_DOCUMENT_COMMENT_HISTORY = 100;
@@ -17468,4 +17771,4 @@ function capturePages(surface) {
17468
17771
  width: surface.pageWidth
17469
17772
  }));
17470
17773
  }
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 };
17774
+ 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, 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 };
@@ -0,0 +1,9 @@
1
+ import type { Mark as ProseMirrorMark } from '@tiptap/pm/model';
2
+ import type { EditorState, PluginKey, Transaction } from '@tiptap/pm/state';
3
+ import type { WorkDocumentChangeIdentity } from './work-document-changes';
4
+ interface DocumentFormattingChangeTrackingOptions {
5
+ isTracking: () => boolean;
6
+ createChange: () => WorkDocumentChangeIdentity;
7
+ }
8
+ export declare function trackDocumentFormattingTransaction(transaction: Transaction, state: EditorState, type: ProseMirrorMark['type'], options: DocumentFormattingChangeTrackingOptions, pluginKey: PluginKey): void;
9
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { Mark, Schema } from '@tiptap/pm/model';
2
+ import type { Transaction } from '@tiptap/pm/state';
3
+ export declare const DOCUMENT_CHARACTER_FORMAT_MARKS: readonly ["bold", "italic", "underline", "strike", "subscript", "superscript", "textStyle", "highlight"];
4
+ export type DocumentCharacterFormatMarkName = (typeof DOCUMENT_CHARACTER_FORMAT_MARKS)[number];
5
+ export interface DocumentCharacterFormatMark {
6
+ type: DocumentCharacterFormatMarkName;
7
+ attrs?: Record<string, boolean | number | string>;
8
+ }
9
+ export declare function isDocumentCharacterFormatMark(value: string): boolean;
10
+ export declare function serializeDocumentCharacterFormatting(marks: readonly Mark[]): string;
11
+ export declare function parseDocumentCharacterFormatting(value: unknown): DocumentCharacterFormatMark[] | null;
12
+ export declare function restoreDocumentCharacterFormatting(transaction: Transaction, schema: Schema, from: number, to: number, serialized: unknown): boolean;
13
+ export declare function importedDocumentCharacterFormatting(formatting: {
14
+ bold?: boolean;
15
+ italic?: boolean;
16
+ underline?: boolean;
17
+ strike?: boolean;
18
+ subscript?: boolean;
19
+ superscript?: boolean;
20
+ fontFamily?: string;
21
+ wordLineHeightFactor?: number;
22
+ wordSnapToGrid?: boolean;
23
+ fontSize?: number;
24
+ color?: string;
25
+ backgroundColor?: string;
26
+ themeColor?: string;
27
+ themeFill?: string;
28
+ }): string;
@@ -0,0 +1,17 @@
1
+ interface DocxRunFormattingChangePatch {
2
+ start: string;
3
+ end: string;
4
+ id: number;
5
+ author: string;
6
+ date: string;
7
+ before: string;
8
+ }
9
+ export declare class DocxRunFormattingChangePatchCollector {
10
+ readonly patches: DocxRunFormattingChangePatch[];
11
+ register(element: HTMLElement, id: number): {
12
+ start: string;
13
+ end: string;
14
+ } | null;
15
+ }
16
+ export declare function patchDocxRunFormattingChanges(buffer: ArrayBuffer, patches: readonly DocxRunFormattingChangePatch[]): Promise<ArrayBuffer>;
17
+ export {};
@@ -7,6 +7,8 @@ export interface ImportedDocxRunFormatting {
7
7
  italic?: boolean;
8
8
  underline?: boolean;
9
9
  strike?: boolean;
10
+ subscript?: boolean;
11
+ superscript?: boolean;
10
12
  fontFamily?: string;
11
13
  wordLineHeightFactor?: number;
12
14
  wordSnapToGrid?: boolean;
@@ -20,6 +22,13 @@ export interface ImportedDocxRunFormattingMarker {
20
22
  startMarker: string;
21
23
  endMarker: string;
22
24
  formatting: ImportedDocxRunFormatting;
25
+ change?: ImportedDocxRunFormattingChange;
26
+ }
27
+ export interface ImportedDocxRunFormattingChange {
28
+ id: string;
29
+ author: string;
30
+ date: string;
31
+ before: string;
23
32
  }
24
33
  export interface ImportedDocxRunFormattingMarkers {
25
34
  runs: ImportedDocxRunFormattingMarker[];
@@ -27,3 +36,4 @@ export interface ImportedDocxRunFormattingMarkers {
27
36
  export declare function markDocxRunFormatting(document: Document, styleSource?: DocxParagraphStyleSource, themeSource?: DocxThemeSource, tableStyleSource?: DocxTableStyleSource): ImportedDocxRunFormattingMarkers;
28
37
  export declare function applyImportedDocxRunFormattingMarkers(document: Document, markers: ImportedDocxRunFormattingMarkers): void;
29
38
  export declare function hasImportedDocxRunFormattingMarkers(markers: ImportedDocxRunFormattingMarkers): boolean;
39
+ export declare function isSupportedDocxRunFormattingChange(change: Element): boolean;
@@ -106,7 +106,7 @@ export interface WorkDocumentContent {
106
106
  comments?: WorkDocumentComment[];
107
107
  bibliography?: WorkDocumentBibliography;
108
108
  }
109
- export type WorkDocumentChangeKind = 'insertion' | 'deletion';
109
+ export type WorkDocumentChangeKind = 'insertion' | 'deletion' | 'formatting';
110
110
  export type WorkDocumentChangeDecisionAction = 'accept' | 'reject';
111
111
  /**
112
112
  * Immutable audit record created when an editor accepts or rejects one
Binary file
package/dist/styles.css CHANGED
@@ -8543,6 +8543,10 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
8543
8543
  border-left-color: var(--a3s-red);
8544
8544
  }
8545
8545
 
8546
+ .work-document-change-item.formatting {
8547
+ border-left-color: #6d5bd0;
8548
+ }
8549
+
8546
8550
  .work-document-change-summary {
8547
8551
  min-width: 0;
8548
8552
  color: var(--a3s-ink);
@@ -8569,6 +8573,11 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
8569
8573
  background: #fff0ee;
8570
8574
  }
8571
8575
 
8576
+ .work-document-change-list .work-document-change-item.formatting .work-document-change-summary > span {
8577
+ color: #5746b5;
8578
+ background: #f0edff;
8579
+ }
8580
+
8572
8581
  .work-document-change-summary strong {
8573
8582
  text-overflow: ellipsis;
8574
8583
  white-space: nowrap;
@@ -9066,6 +9075,13 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
9066
9075
  text-decoration-thickness: 1px;
9067
9076
  }
9068
9077
 
9078
+ .work-document-editor span[data-document-change][data-change-kind="formatting"], .work-pdf-export-page.document span[data-document-change][data-change-kind="formatting"] {
9079
+ color: inherit;
9080
+ background: #f0edff;
9081
+ border-bottom: 1px dashed #6d5bd0;
9082
+ text-decoration: none;
9083
+ }
9084
+
9069
9085
  .work-document-list-tools {
9070
9086
  align-items: center;
9071
9087
  gap: 2px;
@@ -12019,6 +12035,10 @@ button.work-office-collaboration-participant:hover .work-office-collaboration-lo
12019
12035
  color: var(--a3s-red);
12020
12036
  }
12021
12037
 
12038
+ .work-document-change-decisions li[data-document-change-kind="formatting"] {
12039
+ border-left: 3px solid #6d5bd0;
12040
+ }
12041
+
12022
12042
  .work-document-change-decisions li > strong {
12023
12043
  text-overflow: ellipsis;
12024
12044
  white-space: nowrap;