@stll/folio-core 0.35.1 → 0.36.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 (80) hide show
  1. package/dist/ai-edits/apply.js +370 -118
  2. package/dist/ai-edits/headless.js +16 -10
  3. package/dist/ai-edits/index.d.ts +2 -2
  4. package/dist/ai-edits/index.js +2 -2
  5. package/dist/ai-edits/snapshot.js +6 -1
  6. package/dist/ai-edits/types.d.ts +19 -6
  7. package/dist/ai-edits/word-diff.d.ts +18 -3
  8. package/dist/ai-edits/word-diff.js +556 -67
  9. package/dist/compare/compare.js +7 -16
  10. package/dist/compare/plan.js +8 -5
  11. package/dist/compare/verification.d.ts +8 -9
  12. package/dist/compare/verification.js +51 -46
  13. package/dist/compat/eigenpal.d.ts +2 -2
  14. package/dist/compat/eigenpal.js +2 -2
  15. package/dist/controller/headerFooterEditorManager.js +5 -5
  16. package/dist/controller/hiddenEditorApi.js +1 -1
  17. package/dist/controller/noteEditorManager.js +2 -2
  18. package/dist/document-operations.d.ts +5 -3
  19. package/dist/document-operations.js +32 -5
  20. package/dist/docx/commentParser.js +2 -4
  21. package/dist/docx/commentRangeIntegrity.js +2 -4
  22. package/dist/docx/documentClone.d.ts +2 -0
  23. package/dist/docx/documentClone.js +2 -0
  24. package/dist/docx/headerFooterParser.js +2 -4
  25. package/dist/docx/normalizeBaseDirection.js +5 -7
  26. package/dist/docx/paragraphParser.js +27 -29
  27. package/dist/docx/paragraphPropertySource.d.ts +49 -0
  28. package/dist/docx/paragraphPropertySource.js +113 -0
  29. package/dist/docx/runConsolidator.js +2 -4
  30. package/dist/docx/runParser.js +2 -15
  31. package/dist/docx/sectionParser.js +1 -15
  32. package/dist/docx/serializer/paragraphSerializer.js +287 -30
  33. package/dist/docx/serializer/runSerializer.js +2 -10
  34. package/dist/docx/serializer/sectionPropertiesSerializer.js +2 -10
  35. package/dist/docx/serializer/tableSerializer.js +4 -23
  36. package/dist/docx/serializer/trackedChangeAttributes.d.ts +9 -0
  37. package/dist/docx/serializer/trackedChangeAttributes.js +21 -0
  38. package/dist/docx/server/createBilingualDocument.js +8 -10
  39. package/dist/docx/server/evaluateDocxXmlPatchProposal.js +22 -13
  40. package/dist/docx/server/validateDocxConformance.js +17 -13
  41. package/dist/docx/tableParser.js +1 -37
  42. package/dist/docx/trackedChangeInfo.d.ts +11 -0
  43. package/dist/docx/trackedChangeInfo.js +38 -0
  44. package/dist/docx/verbatimCapture.d.ts +20 -9
  45. package/dist/docx/verbatimCapture.js +208 -8
  46. package/dist/docx/xmlParser.d.ts +3 -1
  47. package/dist/docx/xmlParser.js +6 -1
  48. package/dist/docx/xmlSafety.d.ts +1 -1
  49. package/dist/docx/xmlSafety.js +157 -0
  50. package/dist/index.d.ts +2 -2
  51. package/dist/index.js +2 -2
  52. package/dist/layout-bridge/convert/headerFooterLayout.js +4 -4
  53. package/dist/layout-bridge/convert/toFlowBlocks.js +12 -7
  54. package/dist/markdown/renderBlock.js +7 -10
  55. package/dist/prosemirror/attrs/index.js +15 -0
  56. package/dist/prosemirror/commands/comments.js +365 -32
  57. package/dist/prosemirror/commands/pageBreak.js +1 -1
  58. package/dist/prosemirror/commands/propertyChangeScope.d.ts +26 -4
  59. package/dist/prosemirror/commands/propertyChangeScope.js +65 -3
  60. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -4
  61. package/dist/prosemirror/conversion/fromProseDoc.js +130 -18
  62. package/dist/prosemirror/conversion/toProseDoc.js +27 -12
  63. package/dist/prosemirror/extensions/core/ParagraphExtension.js +48 -4
  64. package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +7 -1
  65. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +20 -7
  66. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  67. package/dist/prosemirror/paragraphAlignment.d.ts +12 -0
  68. package/dist/prosemirror/paragraphAlignment.js +13 -0
  69. package/dist/prosemirror/plugins/suggestionMode.js +1 -1
  70. package/dist/prosemirror/schema/marks.d.ts +2 -0
  71. package/dist/prosemirror/schema/nodes.d.ts +12 -1
  72. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  73. package/dist/redline.js +4 -1
  74. package/dist/server.d.ts +2 -2
  75. package/dist/server.js +2 -2
  76. package/dist/utils/mergeDocumentContent.js +3 -3
  77. package/dist/utils/replaceText.js +2 -1
  78. package/dist/version-comparison.js +6 -4
  79. package/dist/watermark/index.js +2 -4
  80. package/package.json +6 -1
@@ -1,8 +1,165 @@
1
1
  import { XMLValidator } from "fast-xml-parser";
2
2
  //#region src/docx/xmlSafety.ts
3
3
  const DOCTYPE_PATTERN = /<!DOCTYPE(?:\s|>)/iu;
4
+ const BUILT_IN_ENTITIES = /* @__PURE__ */ new Set([
5
+ "amp",
6
+ "apos",
7
+ "gt",
8
+ "lt",
9
+ "quot"
10
+ ]);
11
+ const DECIMAL_CHARACTER_REFERENCE = /^#[0-9]+$/u;
12
+ const HEX_CHARACTER_REFERENCE = /^#[xX][0-9A-Fa-f]+$/u;
13
+ const NCNAME = /^[\p{L}_][\p{L}\p{N}._\-\u00b7\p{M}]*$/u;
14
+ const BYTE_ORDER_MARK = "";
15
+ const ENCODING_NAME = String.raw`[A-Za-z][A-Za-z0-9._-]*`;
16
+ const XML_DECLARATION = new RegExp(String.raw`^<\?xml[ \t\r\n]+version[ \t\r\n]*=[ \t\r\n]*(?:"1\.0"|'1\.0')(?:[ \t\r\n]+encoding[ \t\r\n]*=[ \t\r\n]*(?:"${ENCODING_NAME}"|'${ENCODING_NAME}'))?(?:[ \t\r\n]+standalone[ \t\r\n]*=[ \t\r\n]*(?:"(?:yes|no)"|'(?:yes|no)'))?[ \t\r\n]*\?>$`, "u");
17
+ const isXmlCharacter = (codePoint) => codePoint === 9 || codePoint === 10 || codePoint === 13 || codePoint >= 32 && codePoint <= 55295 || codePoint >= 57344 && codePoint <= 65533 || codePoint >= 65536 && codePoint <= 1114111;
18
+ const validEntity = (entity) => {
19
+ if (BUILT_IN_ENTITIES.has(entity)) return true;
20
+ if (!DECIMAL_CHARACTER_REFERENCE.test(entity) && !HEX_CHARACTER_REFERENCE.test(entity)) return false;
21
+ const digits = entity[1]?.toLowerCase() === "x" ? entity.slice(2) : entity.slice(1);
22
+ const significantDigits = digits.replace(/^0+/u, "") || "0";
23
+ const hexadecimal = entity[1]?.toLowerCase() === "x";
24
+ if (digits.length === 0 || significantDigits.length > (hexadecimal ? 6 : 7)) return false;
25
+ return isXmlCharacter(Number.parseInt(significantDigits, hexadecimal ? 16 : 10));
26
+ };
27
+ const hasForbiddenEntity = (xml) => {
28
+ let cursor = 0;
29
+ while (cursor < xml.length) {
30
+ if (xml.startsWith("<!--", cursor)) {
31
+ const end = xml.indexOf("-->", cursor + 4);
32
+ cursor = end === -1 ? xml.length : end + 3;
33
+ continue;
34
+ }
35
+ if (xml.startsWith("<![CDATA[", cursor)) {
36
+ const end = xml.indexOf("]]>", cursor + 9);
37
+ cursor = end === -1 ? xml.length : end + 3;
38
+ continue;
39
+ }
40
+ if (xml.startsWith("<?", cursor)) {
41
+ const end = xml.indexOf("?>", cursor + 2);
42
+ cursor = end === -1 ? xml.length : end + 2;
43
+ continue;
44
+ }
45
+ if (xml[cursor] !== "&") {
46
+ cursor += 1;
47
+ continue;
48
+ }
49
+ const end = xml.indexOf(";", cursor + 1);
50
+ if (end === -1) return true;
51
+ if (!validEntity(xml.slice(cursor + 1, end))) return true;
52
+ cursor = end + 1;
53
+ }
54
+ return false;
55
+ };
56
+ const isValidQName = (name) => {
57
+ const parts = name.split(":");
58
+ return parts.length <= 2 && parts.every((part) => NCNAME.test(part));
59
+ };
60
+ const containsOnlyXmlCharacters = (xml) => {
61
+ for (const character of xml) {
62
+ const codePoint = character.codePointAt(0);
63
+ if (codePoint === void 0 || !isXmlCharacter(codePoint)) return false;
64
+ }
65
+ return true;
66
+ };
67
+ const isWhitespace = (character) => character === " " || character === " " || character === "\r" || character === "\n";
68
+ const scanName = (xml, start) => {
69
+ let cursor = start;
70
+ while (cursor < xml.length && !isWhitespace(xml[cursor]) && xml[cursor] !== ">" && xml[cursor] !== "/" && xml[cursor] !== "=" && xml[cursor] !== "?") cursor += 1;
71
+ const name = xml.slice(start, cursor);
72
+ return name !== "" && isValidQName(name) ? {
73
+ name,
74
+ next: cursor
75
+ } : null;
76
+ };
77
+ /**
78
+ * Reject lexical forms that fast-xml-parser's permissive validator repairs.
79
+ * This is deliberately a small XML lexer, not a second tree parser: structural
80
+ * nesting remains XMLValidator's job.
81
+ */
82
+ const hasInvalidXmlLexicalForm = (xml) => {
83
+ if (!containsOnlyXmlCharacters(xml)) return true;
84
+ const byteOrderMark = xml.indexOf(BYTE_ORDER_MARK);
85
+ if (byteOrderMark > 0 || byteOrderMark === 0 && xml.indexOf(BYTE_ORDER_MARK, 1) !== -1) return true;
86
+ let cursor = 0;
87
+ while (cursor < xml.length) {
88
+ const opening = xml.indexOf("<", cursor);
89
+ const textEnd = opening === -1 ? xml.length : opening;
90
+ if (xml.slice(cursor, textEnd).includes("]]>") || opening === -1) return xml.slice(cursor, textEnd).includes("]]>");
91
+ if (xml.startsWith("<!--", opening)) {
92
+ const end = xml.indexOf("-->", opening + 4);
93
+ if (end === -1) return true;
94
+ const body = xml.slice(opening + 4, end);
95
+ if (body.includes("--") || body.endsWith("-")) return true;
96
+ cursor = end + 3;
97
+ continue;
98
+ }
99
+ if (xml.startsWith("<![CDATA[", opening)) {
100
+ const end = xml.indexOf("]]>", opening + 9);
101
+ if (end === -1) return true;
102
+ cursor = end + 3;
103
+ continue;
104
+ }
105
+ if (xml.startsWith("<?", opening)) {
106
+ const end = xml.indexOf("?>", opening + 2);
107
+ if (end === -1) return true;
108
+ let targetEnd = opening + 2;
109
+ while (targetEnd < end && !isWhitespace(xml[targetEnd]) && xml[targetEnd] !== "?") targetEnd += 1;
110
+ const target = xml.slice(opening + 2, targetEnd);
111
+ if (!NCNAME.test(target)) return true;
112
+ if (target.toLowerCase() === "xml") {
113
+ if (opening !== (xml.startsWith(BYTE_ORDER_MARK) ? 1 : 0) || target !== "xml" || !XML_DECLARATION.test(xml.slice(opening, end + 2))) return true;
114
+ }
115
+ cursor = end + 2;
116
+ continue;
117
+ }
118
+ if (xml.startsWith("<!", opening)) return true;
119
+ let tagCursor = opening + 1;
120
+ const closing = xml[tagCursor] === "/";
121
+ if (closing) tagCursor += 1;
122
+ const tagName = scanName(xml, tagCursor);
123
+ if (!tagName) return true;
124
+ tagCursor = tagName.next;
125
+ if (closing) {
126
+ while (isWhitespace(xml[tagCursor])) tagCursor += 1;
127
+ if (xml[tagCursor] !== ">") return true;
128
+ cursor = tagCursor + 1;
129
+ continue;
130
+ }
131
+ while (tagCursor < xml.length) {
132
+ while (isWhitespace(xml[tagCursor])) tagCursor += 1;
133
+ if (xml[tagCursor] === ">") {
134
+ cursor = tagCursor + 1;
135
+ break;
136
+ }
137
+ if (xml[tagCursor] === "/" && xml[tagCursor + 1] === ">") {
138
+ cursor = tagCursor + 2;
139
+ break;
140
+ }
141
+ const attribute = scanName(xml, tagCursor);
142
+ if (!attribute) return true;
143
+ if (attribute.name.startsWith("xmlns:") && (!NCNAME.test(attribute.name.slice(6)) || attribute.name.slice(6).includes(":"))) return true;
144
+ tagCursor = attribute.next;
145
+ while (isWhitespace(xml[tagCursor])) tagCursor += 1;
146
+ if (xml[tagCursor] !== "=") return true;
147
+ tagCursor += 1;
148
+ while (isWhitespace(xml[tagCursor])) tagCursor += 1;
149
+ const quote = xml[tagCursor];
150
+ if (quote !== "\"" && quote !== "'") return true;
151
+ const valueEnd = xml.indexOf(quote, tagCursor + 1);
152
+ if (valueEnd === -1 || xml.slice(tagCursor + 1, valueEnd).includes("<")) return true;
153
+ tagCursor = valueEnd + 1;
154
+ }
155
+ if (tagCursor >= xml.length && cursor !== xml.length) return true;
156
+ }
157
+ return false;
158
+ };
4
159
  const getDocxXmlSafetyIssue = (xml) => {
5
160
  if (DOCTYPE_PATTERN.test(xml)) return "doctype-forbidden";
161
+ if (hasForbiddenEntity(xml)) return "entity-forbidden";
162
+ if (hasInvalidXmlLexicalForm(xml)) return "not-well-formed";
6
163
  return XMLValidator.validate(xml) === true ? null : "not-well-formed";
7
164
  };
8
165
  //#endregion
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { document_d_exports } from "./types/document.js";
2
2
  import { FolioAIBlock, FolioAIBlockAnchor, FolioAIBlockKind, FolioAIBlockPreviewRun, FolioAIBlockTableLocation, FolioAIComment, FolioAIEditAppliedOperation, FolioAIEditApplyMode, FolioAIEditApplyResult, FolioAIEditNormalization, FolioAIEditNormalizationCode, FolioAIEditOperation, FolioAIEditPrecondition, FolioAIEditReviewMeta, FolioAIEditSeverity, FolioAIEditSkipReason, FolioAIEditSkippedOperation, FolioAIEditSnapshot, FolioAISignatureParty } from "./ai-edits/types.js";
3
3
  import { WORD_DIFF_GRANULARITIES, WordDiffGranularity, WordDiffNormalization, WordDiffOptions, WordDiffSegment, diffWordSegments } from "./ai-edits/word-diff.js";
4
4
  import { FolioAIEditApplyOutcome, FolioRevisionStamp, FolioWordDiffOptions, applyFolioAIEditOperations } from "./ai-edits/apply.js";
5
- import { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
5
+ import { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
6
6
  import { createFolioAIEditSnapshot, hashFolioAIBlockText, isFolioAIContentBlock, normalizeFolioAIBlockText } from "./ai-edits/snapshot.js";
7
7
  import { DeriveBlockIdInput, FolioBlockId, currentFolioBlockId, deriveBlockId, getFolioParaIdFromBlockId, isFolioBlockId, isSequentialFolioBlockId } from "./types/block-id.js";
8
8
  import "./ai-edits/index.js";
@@ -38,4 +38,4 @@ import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled
38
38
  import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
39
39
  type Document = document_d_exports.Document;
40
40
  type DocxConformanceClass = document_d_exports.DocxConformanceClass;
41
- export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFormatRange, type CompareResult, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
41
+ export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type BlockRect, COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, type CompareChange, type CompareChangeLocation, CompareDocxApplyError, type CompareDocxError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, type CompareDocxOptions, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, type CompareFormatRange, type CompareResult, type CompareUnsupportedPart, type CompareUnsupportedReason, type CompareVerification, type CompareVerificationCause, type CompareVerificationFailure, type CompareVerificationInvariant, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocumentPreset, type DocumentStyleCatalog, type DocumentStyleCatalogEntry, type DocumentStyleSet, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, type ExtractDocumentStyleSetOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, type FinalParagraphMarkRevision, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIBlockTableLocation, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyOutcome, type FolioAIEditApplyResult, type FolioAIEditNormalization, type FolioAIEditNormalizationCode, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationResultBase, type FolioDocumentOperationStatus, type FolioDocumentOperationStory, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioRevisionStamp, type FolioWordDiffOptions, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, STELLA_STYLE_SET_NAME, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, type WordDiffGranularity, type WordDiffNormalization, type WordDiffOptions, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { DEFAULT_AI_SUGGESTION_PRESETS } from "./ai-suggestions/types.js";
8
8
  import { MAX_COMPARE_OPERATIONS, compareDocx } from "./compare/compare.js";
9
9
  import { COMPARE_UNSUPPORTED_REASONS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, InvalidCompareDocxOptionsError } from "./compare/types.js";
10
10
  import { COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS } from "./compare/verification.js";
11
- import { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
11
+ import { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
12
12
  import { inspectDocxCompatibility } from "./docx/compatibility.js";
13
13
  import { createDocx } from "./docx/rezip.js";
14
14
  import { buildEmbeddedFontFamilyMap, extractEmbeddedFonts, getEmbeddedFontFaces, scopeEmbeddedFontFamily } from "./fonts/embeddedFonts.js";
@@ -31,4 +31,4 @@ import { createEmptyDocument } from "./utils/createDocument.js";
31
31
  import { getGoogleFontsEnabled, setEmbeddedFontFamilyMap, setGoogleFontsEnabled } from "./utils/fontResolver.js";
32
32
  import { mergeDocumentContent } from "./utils/mergeDocumentContent.js";
33
33
  import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
34
- export { COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
34
+ export { COMPARE_UNSUPPORTED_REASONS, COMPARE_VERIFICATION_CAUSES, COMPARE_VERIFICATION_INVARIANTS, CompareDocxApplyError, CompareDocxFinalParagraphMarkError, CompareDocxOperationLimitError, CompareDocxParseError, CompareDocxRoundTripError, CompareDocxSerializeError, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCUMENT_PRESET_VERSION, DOCUMENT_STYLE_SET_VERSION, DOCX_CONFORMANCE_CLASSES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidCompareDocxOptionsError, InvalidFolioDocumentOperationBatchError, MAX_COMPARE_OPERATIONS, STELLA_STYLE_SET_NAME, UnsupportedFolioDocumentOperationVersionError, WORD_DIFF_GRANULARITIES, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildEmbeddedFontFamilyMap, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, compareDocx, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, createStellaStyleDocumentPreset, createStellaStyleSet, currentFolioBlockId, deriveBlockId, diffWordSegments, extractDocumentStyleSet, extractDocumentStyleSetFromDocx, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocumentStyles, inspectDocumentStylesFromDocx, inspectDocxCompatibility, isFolioAIContentBlock, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, mergeDocumentContent, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scopeEmbeddedFontFamily, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setEmbeddedFontFamilyMap, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
@@ -1,3 +1,4 @@
1
+ import { cloneParagraphWithPropertySource } from "../../docx/paragraphPropertySource.js";
1
2
  import { isFloatingImageRun, isFloatingTextBoxBlock } from "../../layout-engine/types.js";
2
3
  import { headerFooterToProseDoc } from "../../prosemirror/conversion/toProseDoc.js";
3
4
  import { emuToPixels } from "../../utils/units.js";
@@ -7,10 +8,9 @@ const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
7
8
  const headerFooterToProseDocWithDetachedWatermarkHost = (headerFooter, options) => {
8
9
  return headerFooterToProseDoc(headerFooter.content.map((block, blockIndex) => {
9
10
  if (blockIndex !== headerFooter.watermarkBlockIndex || block.type !== "paragraph") return block;
10
- return {
11
- ...block,
12
- [DETACHED_WATERMARK_HOST]: true
13
- };
11
+ const marked = cloneParagraphWithPropertySource(block, {});
12
+ Reflect.set(marked, DETACHED_WATERMARK_HOST, true);
13
+ return marked;
14
14
  }), options);
15
15
  };
16
16
  function isAnchoredImageRun(run) {
@@ -717,15 +717,20 @@ function applyDeletedListMarkerAttrs(attrs, change, listCounterState, theme, fon
717
717
  if (previousListAttrs.listMarkerAlignment) attrs.listMarkerAlignment = previousListAttrs.listMarkerAlignment;
718
718
  if (previousListAttrs.listMarkerSuffix) attrs.listMarkerSuffix = previousListAttrs.listMarkerSuffix;
719
719
  }
720
+ const FLOW_ALIGNMENT_BY_PARAGRAPH_ALIGNMENT = {
721
+ left: "left",
722
+ center: "center",
723
+ right: "right",
724
+ both: "justify",
725
+ distribute: "justify",
726
+ mediumKashida: "justify",
727
+ highKashida: "justify",
728
+ lowKashida: "justify",
729
+ thaiDistribute: "justify"
730
+ };
720
731
  function convertParagraphAttrs(pmAttrs, { theme, fontAlternates, listCounterStreams, defaultTabStopTwips }) {
721
732
  const attrs = {};
722
- if (pmAttrs.alignment) {
723
- const align = pmAttrs.alignment;
724
- if (align === "both" || align === "distribute") attrs.alignment = "justify";
725
- else if (align === "left") attrs.alignment = "left";
726
- else if (align === "center") attrs.alignment = "center";
727
- else if (align === "right") attrs.alignment = "right";
728
- }
733
+ if (pmAttrs.alignment) attrs.alignment = FLOW_ALIGNMENT_BY_PARAGRAPH_ALIGNMENT[pmAttrs.alignment];
729
734
  if (typeof pmAttrs.outlineLevel === "number") attrs.outlineLevel = pmAttrs.outlineLevel;
730
735
  const spaceBefore = pmAttrs.spaceBefore;
731
736
  const spaceAfter = pmAttrs.spaceAfter;
@@ -1,3 +1,4 @@
1
+ import { cloneParagraphWithoutPropertySource } from "../docx/paragraphPropertySource.js";
1
2
  import { renderParagraph } from "./renderParagraph.js";
2
3
  import { renderTable } from "./renderTable.js";
3
4
  //#region src/markdown/renderBlock.ts
@@ -16,17 +17,13 @@ function mergeAcceptedParagraphBreaks(blocks) {
16
17
  for (const block of blocks) {
17
18
  const prev = merged.at(-1);
18
19
  if (prev?.type === "paragraph" && prev.pPrMark?.kind === "del" && block.type === "paragraph") {
19
- const { pPrMark: _resolved, ...base } = prev;
20
20
  const next = block.pPrMark;
21
- const content = [...prev.content, ...block.content];
22
- merged[merged.length - 1] = next ? {
23
- ...base,
24
- content,
25
- pPrMark: next
26
- } : {
27
- ...base,
28
- content
29
- };
21
+ const joined = cloneParagraphWithoutPropertySource(prev, {
22
+ content: [...prev.content, ...block.content],
23
+ ...next ? { pPrMark: next } : {}
24
+ });
25
+ if (!next) Reflect.deleteProperty(joined, "pPrMark");
26
+ merged[merged.length - 1] = joined;
30
27
  continue;
31
28
  }
32
29
  merged.push(block);
@@ -148,6 +148,7 @@ const readParagraphAttrs = (node) => {
148
148
  optionalString(attrs, "paraId", "paragraph.attrs.paraId", issues);
149
149
  optionalString(attrs, "textId", "paragraph.attrs.textId", issues);
150
150
  optionalOneOf(attrs, "alignment", "paragraph.attrs.alignment", issues, PARAGRAPH_ALIGNMENT_VALUES);
151
+ optionalOneOf(attrs, "alignmentFromStyle", "paragraph.attrs.alignmentFromStyle", issues, PARAGRAPH_ALIGNMENT_VALUES);
151
152
  optionalString(attrs, "styleId", "paragraph.attrs.styleId", issues);
152
153
  optionalNumber(attrs, "_tableOfContentsLevel", "paragraph.attrs._tableOfContentsLevel", issues);
153
154
  optionalBoolean(attrs, "kinsoku", "paragraph.attrs.kinsoku", issues);
@@ -655,6 +656,7 @@ const readTrackedChangeMarkAttrs = (mark) => {
655
656
  requiredNumber(attrs, "revisionId", `${mark.type.name}.attrs.revisionId`, issues);
656
657
  requiredString(attrs, "author", `${mark.type.name}.attrs.author`, issues);
657
658
  optionalString(attrs, "date", `${mark.type.name}.attrs.date`, issues);
659
+ optionalString(attrs, "utcDate", `${mark.type.name}.attrs.utcDate`, issues);
658
660
  optionalString(attrs, "initials", `${mark.type.name}.attrs.initials`, issues);
659
661
  optionalOneOf(attrs, "moveKind", `${mark.type.name}.attrs.moveKind`, issues, TRACKED_CHANGE_MOVE_KINDS);
660
662
  optionalOneOf(attrs, "provenance", `${mark.type.name}.attrs.provenance`, issues, TRACKED_CHANGE_PROVENANCE_VALUES);
@@ -1005,6 +1007,7 @@ const optionalTableRowRevision = (attrs, key, issues) => {
1005
1007
  requiredNumber(value, "revisionId", `${path}.revisionId`, issues);
1006
1008
  requiredString(value, "author", `${path}.author`, issues);
1007
1009
  optionalString(value, "date", `${path}.date`, issues);
1010
+ optionalString(value, "utcDate", `${path}.utcDate`, issues);
1008
1011
  optionalString(value, "initials", `${path}.initials`, issues);
1009
1012
  optionalOneOf(value, "provenance", `${path}.provenance`, issues, TRACKED_CHANGE_PROVENANCE_VALUES);
1010
1013
  optionalString(value, "suggestionId", `${path}.suggestionId`, issues);
@@ -1036,6 +1039,7 @@ const optionalTableCellRevision = (attrs, issues) => {
1036
1039
  requiredNumber(info, "revisionId", `${path}.info.revisionId`, issues);
1037
1040
  requiredString(info, "author", `${path}.info.author`, issues);
1038
1041
  optionalString(info, "date", `${path}.info.date`, issues);
1042
+ optionalString(info, "utcDate", `${path}.info.utcDate`, issues);
1039
1043
  optionalString(info, "initials", `${path}.info.initials`, issues);
1040
1044
  if (value["kind"] === "merge") {
1041
1045
  if (info["provenance"] !== void 0) issues.push({
@@ -1568,7 +1572,18 @@ const validatePropertyChangeInfo = (value, path, issues) => {
1568
1572
  requiredNumber(value, "id", `${path}.id`, issues);
1569
1573
  requiredString(value, "author", `${path}.author`, issues);
1570
1574
  optionalString(value, "date", `${path}.date`, issues);
1575
+ const utcDate = value["utcDate"];
1576
+ if (utcDate !== void 0) if (!isRecord(utcDate)) issues.push({
1577
+ path: `${path}.utcDate`,
1578
+ message: "Expected an object."
1579
+ });
1580
+ else {
1581
+ requiredString(utcDate, "attribute", `${path}.utcDate.attribute`, issues);
1582
+ requiredString(utcDate, "value", `${path}.utcDate.value`, issues);
1583
+ }
1571
1584
  optionalString(value, "rsid", `${path}.rsid`, issues);
1585
+ optionalOneOf(value, "provenance", `${path}.provenance`, issues, TRACKED_CHANGE_PROVENANCE_VALUES);
1586
+ optionalString(value, "suggestionId", `${path}.suggestionId`, issues);
1572
1587
  };
1573
1588
  const optionalImagePosition = (attrs, key, path, issues) => {
1574
1589
  const value = attrs[key];