@a3s-lab/office 0.10.0 → 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.
- package/COLLABORATION_ROADMAP.md +22 -12
- package/README.md +17 -14
- package/dist/{0~4705.js → 0~5093.js} +959 -10
- package/dist/0~document-editor.js +1 -0
- package/dist/0~work-docx-export.js +225 -6
- package/dist/0~work-docx-import.js +24 -753
- package/dist/0~work-office-diagnostics.js +6 -4
- package/dist/4104.js +1 -1
- package/dist/8928.js +448 -137
- package/dist/internal/features/work/work-document-format-change-tracking.d.ts +1 -1
- package/dist/internal/features/work/work-document-paragraph-format-change-tracking.d.ts +7 -0
- package/dist/internal/features/work/work-document-paragraph-format-changes.d.ts +8 -0
- package/dist/internal/features/work/work-docx-import.d.ts +3 -1
- package/dist/internal/features/work/work-docx-paragraph-alignment-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-paragraph-direction-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-paragraph-format-change-export.d.ts +13 -0
- package/dist/internal/features/work/work-docx-paragraph-format-change-import.d.ts +17 -0
- package/dist/internal/features/work/work-docx-paragraph-indent-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-paragraph-spacing-import.d.ts +1 -0
- package/dist/internal/features/work/work-docx-tab-stop-import.d.ts +1 -0
- package/dist/internal/features/work/work-types.d.ts +1 -1
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +8 -0
- package/docs/latest/en/browser-editor-architecture.md +18 -0
- package/package.json +5 -3
|
@@ -896,6 +896,7 @@ function documentChangeDecisionKey(changeKey, decision) {
|
|
|
896
896
|
function documentChangeKindLabel(kind) {
|
|
897
897
|
if ('insertion' === kind) return '插入';
|
|
898
898
|
if ('formatting' === kind) return '格式';
|
|
899
|
+
if ('paragraph-formatting' === kind) return '段落格式';
|
|
899
900
|
return '删除';
|
|
900
901
|
}
|
|
901
902
|
function documentChangeWindowKey(change) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import jszip from "jszip";
|
|
2
|
-
import { normalizeDocumentBookmarkName, applyDocumentImageIdentityToElement, DOCUMENT_PAGE_BORDER_EDGES, createDocumentImageIdentityRegistry, normalizeDocumentColumns, normalizeDocumentTableVerticalAlign, uniqueDocumentParagraphIdentity, documentTableColumnPercentagesFromElement, documentTableCellMarginOverridesFromElement, applyDocumentTableRowIdentityToElement, normalizeDocumentBookmarksHtml, documentImageIdentityFromElement, documentTableGeometryFromElement, normalizeDocumentTableRowHeightRule, documentNoteKey, normalizeDocumentParagraphBorders, normalizeDocumentTableBorderWidth, normalizeDocumentParagraphId, normalizeDocumentTableBorderStyle, normalizeDocumentBookmarkReferencesHtml, documentCitationInstruction, parseDocumentParagraphBordersElement, documentImageWrapContourFromElement, documentImagePositionFromElement, normalizeDocumentPageChrome, documentPageMarginsForLayout, normalizeDocumentImageLayer, documentBookmarkReferenceInstruction, documentImageCropFromElement, normalizeDocumentPageBorders, documentImageLayerFromElement, parseDocxThemeReference, documentCaptionLabel, documentCaptionKind, applyDocumentParagraphIdentityToElement, isContourImageLayout, normalizeDocumentImageIdentity, normalizeTableColor, documentTableBordersFromElement, documentSections, createDocumentParagraphIdentityRegistry, documentCitationTags, docxDocumentFieldKind, wrapsBesideImage, DocxThemePatchCollector, defaultDocumentImageWrapContour, normalizeDocumentParagraphIdentity, normalizeDocumentPaperSource, documentEquationFromElement, DOCUMENT_PARAGRAPH_BORDER_EDGES, parseDocumentCharacterFormatting, patchDocxThemeReferences, parseDocumentParagraphShadingElement, documentParagraphIdentityFromElement, normalizeDocumentEquation,
|
|
2
|
+
import { normalizeDocumentBookmarkName, applyDocumentImageIdentityToElement, DOCUMENT_PAGE_BORDER_EDGES, createDocumentImageIdentityRegistry, normalizeDocumentColumns, normalizeDocumentTableVerticalAlign, uniqueDocumentParagraphIdentity, documentTableColumnPercentagesFromElement, documentTableCellMarginOverridesFromElement, applyDocumentTableRowIdentityToElement, normalizeDocumentBookmarksHtml, documentImageIdentityFromElement, documentTableGeometryFromElement, normalizeDocumentTableRowHeightRule, documentNoteKey, normalizeDocumentParagraphBorders, normalizeDocumentTableBorderWidth, normalizeDocumentParagraphId, normalizeDocumentTableBorderStyle, normalizeDocumentBookmarkReferencesHtml, documentCitationInstruction, parseDocumentParagraphBordersElement, documentImageWrapContourFromElement, documentImagePositionFromElement, normalizeDocumentPageChrome, documentPageMarginsForLayout, normalizeDocumentImageLayer, documentBookmarkReferenceInstruction, documentImageCropFromElement, normalizeDocumentPageBorders, documentImageLayerFromElement, parseDocxThemeReference, documentCaptionLabel, documentCaptionKind, applyDocumentParagraphIdentityToElement, isContourImageLayout, normalizeDocumentImageIdentity, normalizeTableColor, documentTableBordersFromElement, documentSections, createDocumentParagraphIdentityRegistry, documentCitationTags, docxDocumentFieldKind, wrapsBesideImage, DocxThemePatchCollector, defaultDocumentImageWrapContour, normalizeDocumentParagraphIdentity, normalizeDocumentPaperSource, documentEquationFromElement, DOCUMENT_PARAGRAPH_BORDER_EDGES, parseDocumentCharacterFormatting, patchDocxThemeReferences, parseDocumentParagraphShadingElement, documentParagraphIdentityFromElement, normalizeDocumentEquation, parseDocumentParagraphFormatting, documentTableRowIdentityFromElement, normalizeDocumentBookmarkNativeId, collectDocumentNotes, DOCUMENT_PAGE_MARGIN_KEYS, uniqueDocumentImageIdentity, documentImageLayoutFromElement, documentPageHorizontalMarginTwips, documentPageGeometryForLayout, normalizeDocumentPageMargins, documentNoteKind } from "./8928.js";
|
|
3
3
|
import { serializeUtf8Xml, directChildren, xmlNamespacePrefix, parseXml, decodeXmlBytes, descendants, resolvePartTarget, directChild, attribute as work_ooxml_package_attribute } from "./5184.js";
|
|
4
4
|
import { assignDocxNoteIds, patchDocxPageColor, normalizeDocxCommentId, assignDocxCommentThreads } from "./0~4980.js";
|
|
5
5
|
import { paragraphTabStops, mergeDocxIgnorableExtensionsAtPairs, patchDocxBibliography, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, paragraphAlignment, paragraphSpacingOptions, xmlNamespaceUri, hasNonWhitespaceXmlText, cloneXmlElement, cssColorToHex, DocxParagraphDefaultCollapsedPatchCollector, assertXmlRoot, xmlDeclaredPrefix, paragraphIndent, domDirection, DOCX_WORDPROCESSING_NAMESPACES, paragraphBidirectional, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, patchDocxParagraphDefaultCollapsed, xmlAttributeNamespace, dataBoolean, mergeDocxIgnorableExtensions, parseDocxColorSchemeMappingElement, paragraphPaginationOptions, DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, xmlAttributeLocalName, cssFontSize, paragraphDirectionOptions, cssFontFamily } from "./0~2805.js";
|
|
@@ -3104,10 +3104,223 @@ async function patchDocxNumberingRestartRules(buffer, rules) {
|
|
|
3104
3104
|
function wordQualifiedName(root, localName) {
|
|
3105
3105
|
return `${xmlNamespacePrefix(root, work_docx_numbering_WORD_NAMESPACE) ?? root.prefix ?? 'w'}:${localName}`;
|
|
3106
3106
|
}
|
|
3107
|
+
const work_docx_paragraph_format_change_export_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
3108
|
+
const work_docx_paragraph_format_change_export_WORD_2012_NAMESPACE = 'http://schemas.microsoft.com/office/word/2012/wordml';
|
|
3109
|
+
const work_docx_paragraph_format_change_export_XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/';
|
|
3110
|
+
const MAX_PARAGRAPH_FORMATTING_CHANGE_PATCHES = 65536;
|
|
3111
|
+
const PARAGRAPH_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
|
|
3112
|
+
class DocxParagraphFormattingChangePatchCollector {
|
|
3113
|
+
patches = [];
|
|
3114
|
+
register(element, id) {
|
|
3115
|
+
if ('paragraph-formatting' !== element.dataset.changeKind || !element.hasAttribute('data-document-change')) return null;
|
|
3116
|
+
const key = element.dataset.changeId?.trim() ?? '';
|
|
3117
|
+
const author = element.dataset.changeAuthor?.trim() ?? '';
|
|
3118
|
+
const date = work_docx_paragraph_format_change_export_normalizedRevisionDate(element.dataset.changeDate);
|
|
3119
|
+
const before = element.dataset.changeBefore ?? '';
|
|
3120
|
+
if (!key || !author || author.length > 255 || !parseDocumentParagraphFormatting(before)) throw new Error('Document contains an invalid paragraph-formatting revision.');
|
|
3121
|
+
if (this.patches.length >= MAX_PARAGRAPH_FORMATTING_CHANGE_PATCHES) throw new Error('Document exceeds the paragraph-formatting revision limit.');
|
|
3122
|
+
const marker = `__A3S_WORK_PARAGRAPH_FORMAT_CHANGE_EXPORT_${this.patches.length + 1}__`;
|
|
3123
|
+
this.patches.push({
|
|
3124
|
+
marker,
|
|
3125
|
+
id,
|
|
3126
|
+
author,
|
|
3127
|
+
date,
|
|
3128
|
+
before
|
|
3129
|
+
});
|
|
3130
|
+
return marker;
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
async function patchDocxParagraphFormattingChanges(buffer, patches) {
|
|
3134
|
+
if (!patches.length) return buffer;
|
|
3135
|
+
if (patches.length > MAX_PARAGRAPH_FORMATTING_CHANGE_PATCHES) throw new Error('Document exceeds the paragraph-formatting revision limit.');
|
|
3136
|
+
const archive = await jszip.loadAsync(buffer);
|
|
3137
|
+
const byMarker = new Map(patches.map((patch)=>[
|
|
3138
|
+
patch.marker,
|
|
3139
|
+
patch
|
|
3140
|
+
]));
|
|
3141
|
+
const applied = new Set();
|
|
3142
|
+
for (const entry of Object.values(archive.files)){
|
|
3143
|
+
if (entry.dir || !PARAGRAPH_PART_PATTERN.test(entry.name)) continue;
|
|
3144
|
+
const document = parseXml(decodeXmlBytes(await entry.async('uint8array'), `generated DOCX ${entry.name}`), `generated DOCX ${entry.name}`);
|
|
3145
|
+
let changed = false;
|
|
3146
|
+
for (const paragraph of descendants(document, 'p').filter((element)=>element.namespaceURI === work_docx_paragraph_format_change_export_WORD_NAMESPACE)){
|
|
3147
|
+
const marker = paragraphFormattingMarker(paragraph, byMarker);
|
|
3148
|
+
if (marker) {
|
|
3149
|
+
setParagraphFormattingChange(document, paragraph, marker.patch);
|
|
3150
|
+
marker.run.remove();
|
|
3151
|
+
applied.add(marker.patch.marker);
|
|
3152
|
+
changed = true;
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
if (changed) archive.file(entry.name, serializeUtf8Xml(document));
|
|
3156
|
+
}
|
|
3157
|
+
const missing = patches.filter((patch)=>!applied.has(patch.marker));
|
|
3158
|
+
if (missing.length) throw new Error(`DOCX paragraph-formatting revision markers were not emitted: ${missing.map((patch)=>patch.marker).join(', ')}.`);
|
|
3159
|
+
return archive.generateAsync({
|
|
3160
|
+
type: 'arraybuffer'
|
|
3161
|
+
});
|
|
3162
|
+
}
|
|
3163
|
+
function paragraphFormattingMarker(paragraph, patches) {
|
|
3164
|
+
const matches = directChildren(paragraph, 'r').flatMap((run)=>{
|
|
3165
|
+
if (run.namespaceURI !== work_docx_paragraph_format_change_export_WORD_NAMESPACE) return [];
|
|
3166
|
+
const texts = directChildren(run, 't').filter((text)=>text.namespaceURI === work_docx_paragraph_format_change_export_WORD_NAMESPACE);
|
|
3167
|
+
if (1 !== texts.length || !work_docx_paragraph_format_change_export_runHasOnlyMarkerText(run, texts[0])) return [];
|
|
3168
|
+
const patch = patches.get(texts[0]?.textContent ?? '');
|
|
3169
|
+
return patch ? [
|
|
3170
|
+
{
|
|
3171
|
+
patch,
|
|
3172
|
+
run
|
|
3173
|
+
}
|
|
3174
|
+
] : [];
|
|
3175
|
+
});
|
|
3176
|
+
if (matches.length > 1) throw new Error('Generated DOCX paragraph has duplicate revision markers.');
|
|
3177
|
+
return matches[0] ?? null;
|
|
3178
|
+
}
|
|
3179
|
+
function work_docx_paragraph_format_change_export_runHasOnlyMarkerText(run, markerText) {
|
|
3180
|
+
return Boolean(markerText && directChildren(run).every((child)=>child === markerText || 'rPr' === child.localName && child.namespaceURI === work_docx_paragraph_format_change_export_WORD_NAMESPACE));
|
|
3181
|
+
}
|
|
3182
|
+
function setParagraphFormattingChange(document, paragraph, patch) {
|
|
3183
|
+
const propertyNodes = directChildren(paragraph, 'pPr').filter((element)=>element.namespaceURI === work_docx_paragraph_format_change_export_WORD_NAMESPACE);
|
|
3184
|
+
if (propertyNodes.length > 1) throw new Error('Generated DOCX paragraph contains duplicate properties.');
|
|
3185
|
+
const prefix = xmlNamespacePrefix(document.documentElement, work_docx_paragraph_format_change_export_WORD_NAMESPACE) ?? 'w';
|
|
3186
|
+
const properties = propertyNodes[0] ?? insertParagraphProperties(document, paragraph, prefix);
|
|
3187
|
+
if (directChildren(properties, 'pPrChange').some((element)=>element.namespaceURI === work_docx_paragraph_format_change_export_WORD_NAMESPACE)) throw new Error('Generated DOCX paragraph already contains a formatting revision.');
|
|
3188
|
+
const change = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'pPrChange');
|
|
3189
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, change, 'id', String(patch.id));
|
|
3190
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, change, 'author', patch.author);
|
|
3191
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, change, 'date', patch.date);
|
|
3192
|
+
const before = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'pPr');
|
|
3193
|
+
appendParagraphFormattingProperties(document, before, patch.before, prefix);
|
|
3194
|
+
change.append(before);
|
|
3195
|
+
properties.append(change);
|
|
3196
|
+
}
|
|
3197
|
+
function appendParagraphFormattingProperties(document, properties, serialized, prefix) {
|
|
3198
|
+
const parsed = parseDocumentParagraphFormatting(serialized);
|
|
3199
|
+
if (!parsed) throw new Error('Document contains an invalid paragraph-formatting revision.');
|
|
3200
|
+
const formatting = parsed;
|
|
3201
|
+
appendOnOff(document, properties, prefix, 'keepNext', formatting.keepWithNext);
|
|
3202
|
+
appendOnOff(document, properties, prefix, 'keepLines', formatting.keepLines);
|
|
3203
|
+
appendOnOff(document, properties, prefix, 'pageBreakBefore', formatting.pageBreakBefore);
|
|
3204
|
+
appendOnOff(document, properties, prefix, 'widowControl', formatting.widowControl);
|
|
3205
|
+
appendBorders(document, properties, prefix, formatting.paragraphBorders);
|
|
3206
|
+
appendShading(document, properties, prefix, formatting.paragraphShading);
|
|
3207
|
+
appendTabStops(document, properties, prefix, formatting.tabStops);
|
|
3208
|
+
if (formatting.paragraphDirection) appendOnOff(document, properties, prefix, 'bidi', 'rtl' === formatting.paragraphDirection);
|
|
3209
|
+
appendSpacing(document, properties, prefix, formatting);
|
|
3210
|
+
appendIndent(document, properties, prefix, formatting);
|
|
3211
|
+
appendOnOff(document, properties, prefix, 'contextualSpacing', formatting.contextualSpacing);
|
|
3212
|
+
if (formatting.textAlign) work_docx_paragraph_format_change_export_appendValuedProperty(document, properties, prefix, 'jc', 'justify' === formatting.textAlign ? 'both' : formatting.textAlign);
|
|
3213
|
+
if (null !== formatting.outlineLevel) work_docx_paragraph_format_change_export_appendValuedProperty(document, properties, prefix, 'outlineLvl', String(formatting.outlineLevel));
|
|
3214
|
+
appendDefaultCollapsed(document, properties, prefix, formatting.defaultCollapsed);
|
|
3215
|
+
}
|
|
3216
|
+
function appendSpacing(document, properties, prefix, formatting) {
|
|
3217
|
+
const spacing = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'spacing');
|
|
3218
|
+
if (null !== formatting.spaceBefore) work_docx_paragraph_format_change_export_setWordAttribute(document, spacing, 'before', String(Math.round(20 * formatting.spaceBefore)));
|
|
3219
|
+
if (null !== formatting.spaceAfter) work_docx_paragraph_format_change_export_setWordAttribute(document, spacing, 'after', String(Math.round(20 * formatting.spaceAfter)));
|
|
3220
|
+
if (formatting.lineHeight && formatting.lineRule) {
|
|
3221
|
+
const line = docxLineHeight(formatting.lineHeight, formatting.lineRule);
|
|
3222
|
+
if (null !== line) {
|
|
3223
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, spacing, 'line', String(line));
|
|
3224
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, spacing, 'lineRule', formatting.lineRule);
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
if (spacing.attributes.length) properties.append(spacing);
|
|
3228
|
+
}
|
|
3229
|
+
function docxLineHeight(value, rule) {
|
|
3230
|
+
if ('auto' === rule) {
|
|
3231
|
+
const multiple = Number(value.replace(/%$/, ''));
|
|
3232
|
+
if (!Number.isFinite(multiple)) return null;
|
|
3233
|
+
return Math.round((value.endsWith('%') ? multiple / 100 : multiple) * 240);
|
|
3234
|
+
}
|
|
3235
|
+
const length = /^(\d+(?:\.\d+)?)(px|pt)?$/i.exec(value);
|
|
3236
|
+
if (!length?.[1]) return null;
|
|
3237
|
+
const points = length[2]?.toLowerCase() === 'px' ? 0.75 * Number(length[1]) : Number(length[1]);
|
|
3238
|
+
return Math.round(20 * points);
|
|
3239
|
+
}
|
|
3240
|
+
function appendIndent(document, properties, prefix, formatting) {
|
|
3241
|
+
const indent = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'ind');
|
|
3242
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, indent, 'left', String(Math.round(24 * formatting.indentLevel * 15)));
|
|
3243
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, indent, 'right', String(Math.round(15 * formatting.rightIndent)));
|
|
3244
|
+
formatting.firstLineIndent < 0 ? work_docx_paragraph_format_change_export_setWordAttribute(document, indent, 'hanging', String(Math.round(15 * Math.abs(formatting.firstLineIndent)))) : work_docx_paragraph_format_change_export_setWordAttribute(document, indent, 'firstLine', String(Math.round(15 * formatting.firstLineIndent)));
|
|
3245
|
+
properties.append(indent);
|
|
3246
|
+
}
|
|
3247
|
+
function appendTabStops(document, properties, prefix, tabStops) {
|
|
3248
|
+
if (!tabStops?.length) return;
|
|
3249
|
+
const tabs = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'tabs');
|
|
3250
|
+
for (const stop of tabStops){
|
|
3251
|
+
const tab = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'tab');
|
|
3252
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, tab, 'val', stop.alignment);
|
|
3253
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, tab, 'pos', String(Math.round(15 * stop.position)));
|
|
3254
|
+
if ('none' !== stop.leader) work_docx_paragraph_format_change_export_setWordAttribute(document, tab, 'leader', stop.leader);
|
|
3255
|
+
tabs.append(tab);
|
|
3256
|
+
}
|
|
3257
|
+
properties.append(tabs);
|
|
3258
|
+
}
|
|
3259
|
+
function appendBorders(document, properties, prefix, borders) {
|
|
3260
|
+
if (!borders) return;
|
|
3261
|
+
const container = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'pBdr');
|
|
3262
|
+
for (const edge of DOCUMENT_PARAGRAPH_BORDER_EDGES){
|
|
3263
|
+
const border = borders[edge];
|
|
3264
|
+
if (!border) continue;
|
|
3265
|
+
const element = work_docx_paragraph_format_change_export_wordElement(document, prefix, edge);
|
|
3266
|
+
setDocxBorderAttributes(document, element, border);
|
|
3267
|
+
container.append(element);
|
|
3268
|
+
}
|
|
3269
|
+
if (container.children.length) properties.append(container);
|
|
3270
|
+
}
|
|
3271
|
+
function appendShading(document, properties, prefix, shading) {
|
|
3272
|
+
if (!shading) return;
|
|
3273
|
+
const element = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'shd');
|
|
3274
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, element, 'val', shading.pattern);
|
|
3275
|
+
appendShadingColor(document, element, 'color', shading.color);
|
|
3276
|
+
appendShadingColor(document, element, 'fill', shading.fill);
|
|
3277
|
+
properties.append(element);
|
|
3278
|
+
}
|
|
3279
|
+
function appendShadingColor(document, element, kind, color) {
|
|
3280
|
+
if (!color) return;
|
|
3281
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, element, kind, 'auto' === color.value ? 'auto' : color.value.slice(1).toUpperCase());
|
|
3282
|
+
if (!color.theme) return;
|
|
3283
|
+
const themeName = 'color' === kind ? 'themeColor' : 'themeFill';
|
|
3284
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, element, themeName, color.theme.theme);
|
|
3285
|
+
if (color.theme.tint) work_docx_paragraph_format_change_export_setWordAttribute(document, element, `${themeName}Tint`, color.theme.tint);
|
|
3286
|
+
if (color.theme.shade) work_docx_paragraph_format_change_export_setWordAttribute(document, element, `${themeName}Shade`, color.theme.shade);
|
|
3287
|
+
}
|
|
3288
|
+
function appendDefaultCollapsed(document, properties, wordPrefix, value) {
|
|
3289
|
+
if (null === value) return;
|
|
3290
|
+
const element = document.createElementNS(work_docx_paragraph_format_change_export_WORD_2012_NAMESPACE, 'w15:collapsed');
|
|
3291
|
+
element.setAttributeNS(work_docx_paragraph_format_change_export_XMLNS_NAMESPACE, 'xmlns:w15', work_docx_paragraph_format_change_export_WORD_2012_NAMESPACE);
|
|
3292
|
+
element.setAttributeNS(work_docx_paragraph_format_change_export_WORD_NAMESPACE, `${wordPrefix}:val`, value ? '1' : '0');
|
|
3293
|
+
properties.append(element);
|
|
3294
|
+
}
|
|
3295
|
+
function appendOnOff(document, properties, prefix, name, value) {
|
|
3296
|
+
if (null === value) return;
|
|
3297
|
+
work_docx_paragraph_format_change_export_appendValuedProperty(document, properties, prefix, name, value ? '1' : '0');
|
|
3298
|
+
}
|
|
3299
|
+
function work_docx_paragraph_format_change_export_appendValuedProperty(document, properties, prefix, name, value) {
|
|
3300
|
+
const element = work_docx_paragraph_format_change_export_wordElement(document, prefix, name);
|
|
3301
|
+
work_docx_paragraph_format_change_export_setWordAttribute(document, element, 'val', value);
|
|
3302
|
+
properties.append(element);
|
|
3303
|
+
}
|
|
3304
|
+
function insertParagraphProperties(document, paragraph, prefix) {
|
|
3305
|
+
const properties = work_docx_paragraph_format_change_export_wordElement(document, prefix, 'pPr');
|
|
3306
|
+
paragraph.insertBefore(properties, paragraph.firstChild);
|
|
3307
|
+
return properties;
|
|
3308
|
+
}
|
|
3309
|
+
function work_docx_paragraph_format_change_export_wordElement(document, prefix, name) {
|
|
3310
|
+
return document.createElementNS(work_docx_paragraph_format_change_export_WORD_NAMESPACE, `${prefix}:${name}`);
|
|
3311
|
+
}
|
|
3312
|
+
function work_docx_paragraph_format_change_export_setWordAttribute(document, element, name, value) {
|
|
3313
|
+
const prefix = xmlNamespacePrefix(document.documentElement, work_docx_paragraph_format_change_export_WORD_NAMESPACE) ?? 'w';
|
|
3314
|
+
element.setAttributeNS(work_docx_paragraph_format_change_export_WORD_NAMESPACE, `${prefix}:${name}`, value);
|
|
3315
|
+
}
|
|
3316
|
+
function work_docx_paragraph_format_change_export_normalizedRevisionDate(value) {
|
|
3317
|
+
const time = Date.parse(value?.trim() ?? '');
|
|
3318
|
+
return Number.isFinite(time) ? new Date(time).toISOString() : new Date().toISOString();
|
|
3319
|
+
}
|
|
3107
3320
|
const work_docx_paragraph_identity_WORD_2010_NAMESPACE = 'http://schemas.microsoft.com/office/word/2010/wordml';
|
|
3108
3321
|
const work_docx_paragraph_identity_MARKUP_COMPATIBILITY_NAMESPACE = 'http://schemas.openxmlformats.org/markup-compatibility/2006';
|
|
3109
3322
|
const MAX_PARAGRAPH_IDENTITY_PATCHES = 65536;
|
|
3110
|
-
const
|
|
3323
|
+
const work_docx_paragraph_identity_PARAGRAPH_PART_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
|
|
3111
3324
|
class DocxParagraphIdentityPatchCollector {
|
|
3112
3325
|
source;
|
|
3113
3326
|
patches = [];
|
|
@@ -3157,7 +3370,7 @@ async function patchDocxParagraphIdentities(buffer, patches) {
|
|
|
3157
3370
|
patch
|
|
3158
3371
|
]));
|
|
3159
3372
|
const applied = new Set();
|
|
3160
|
-
const entries = Object.values(archive.files).filter((entry)=>!entry.dir &&
|
|
3373
|
+
const entries = Object.values(archive.files).filter((entry)=>!entry.dir && work_docx_paragraph_identity_PARAGRAPH_PART_PATTERN.test(entry.name));
|
|
3161
3374
|
for (const entry of entries){
|
|
3162
3375
|
const document = parseXml(decodeXmlBytes(await entry.async('uint8array'), `generated DOCX ${entry.name}`), `generated DOCX ${entry.name}`);
|
|
3163
3376
|
if (!isParagraphPartRoot(document.documentElement, entry.name)) continue;
|
|
@@ -7103,7 +7316,8 @@ async function createDocxBlob(content, sourcePackage) {
|
|
|
7103
7316
|
paragraphDefaultCollapsedPatches: new DocxParagraphDefaultCollapsedPatchCollector(),
|
|
7104
7317
|
paragraphIdentityPatches: new DocxParagraphIdentityPatchCollector(JSON.stringify(normalizedContent)),
|
|
7105
7318
|
equationPatches: new DocxEquationPatchCollector(JSON.stringify(normalizedContent)),
|
|
7106
|
-
formattingChangePatches: new DocxRunFormattingChangePatchCollector()
|
|
7319
|
+
formattingChangePatches: new DocxRunFormattingChangePatchCollector(),
|
|
7320
|
+
paragraphFormattingChangePatches: new DocxParagraphFormattingChangePatchCollector()
|
|
7107
7321
|
};
|
|
7108
7322
|
const commentRecords = createDocxCommentRecords(commentThreads, docx, noteContext.commentIds);
|
|
7109
7323
|
const sections = [];
|
|
@@ -7165,7 +7379,8 @@ async function createDocxBlob(content, sourcePackage) {
|
|
|
7165
7379
|
const bookmarkPatched = await patchDocxBookmarks(imageIdentityPatched, noteContext.bookmarkPatches.patches);
|
|
7166
7380
|
const paragraphDefaultCollapsedPatched = await patchDocxParagraphDefaultCollapsed(bookmarkPatched, noteContext.paragraphDefaultCollapsedPatches.patches);
|
|
7167
7381
|
const paragraphIdentityPatched = await patchDocxParagraphIdentities(paragraphDefaultCollapsedPatched, noteContext.paragraphIdentityPatches.patches);
|
|
7168
|
-
const
|
|
7382
|
+
const paragraphFormattingChangesPatched = await patchDocxParagraphFormattingChanges(paragraphIdentityPatched, noteContext.paragraphFormattingChangePatches.patches);
|
|
7383
|
+
const equationPatched = await patchDocxEquations(paragraphFormattingChangesPatched, noteContext.equationPatches.patches);
|
|
7169
7384
|
const patched = await patchDocxPageColor(equationPatched, normalizedContent.pageColor);
|
|
7170
7385
|
const preserved = sourcePackage ? await preserveDocxSourcePackage(patched, sourcePackage, {
|
|
7171
7386
|
numberingIdentities: noteContext.numberingSourceIdentities
|
|
@@ -7331,8 +7546,12 @@ async function pageChromeBlocks(html, docx, noteContext) {
|
|
|
7331
7546
|
async function paragraphRuns(element, docx, noteContext) {
|
|
7332
7547
|
const identityMarker = noteContext.paragraphIdentityPatches.marker(element);
|
|
7333
7548
|
noteContext.paragraphDefaultCollapsedPatches.register(identityMarker, element);
|
|
7549
|
+
const paragraphFormattingChangeMarker = element.hasAttribute('data-document-change') && 'paragraph-formatting' === element.dataset.changeKind ? noteContext.paragraphFormattingChangePatches.register(element, docxRevisionId(element, noteContext)) : null;
|
|
7334
7550
|
return [
|
|
7335
7551
|
new docx.TextRun(identityMarker),
|
|
7552
|
+
...paragraphFormattingChangeMarker ? [
|
|
7553
|
+
new docx.TextRun(paragraphFormattingChangeMarker)
|
|
7554
|
+
] : [],
|
|
7336
7555
|
...await work_docx_export_inlineRuns(element, docx, noteContext)
|
|
7337
7556
|
];
|
|
7338
7557
|
}
|
|
@@ -7496,7 +7715,7 @@ function docxRevisionId(element, context) {
|
|
|
7496
7715
|
}
|
|
7497
7716
|
function documentHasTrackedChanges(html) {
|
|
7498
7717
|
const document = new DOMParser().parseFromString(html, 'text/html');
|
|
7499
|
-
return Boolean(document.body.querySelector('ins[data-document-change], del[data-document-change], span[data-document-change][data-change-kind="formatting"]'));
|
|
7718
|
+
return Boolean(document.body.querySelector('ins[data-document-change], del[data-document-change], span[data-document-change][data-change-kind="formatting"], [data-document-change][data-change-kind="paragraph-formatting"]'));
|
|
7500
7719
|
}
|
|
7501
7720
|
function anchoredDocumentComments(content) {
|
|
7502
7721
|
const document = new DOMParser().parseFromString(content.html, 'text/html');
|