@a3s-lab/office 0.48.1 → 0.50.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 +14 -6
- package/README.md +33 -0
- package/dist/{0~3320.js → 0~5600.js} +271 -13
- package/dist/0~controlled-editor-composition.js +167 -15
- package/dist/0~document-editor.js +354 -90
- package/dist/0~work-docx-export.js +143 -9
- package/dist/0~work-docx-import.js +5 -120
- package/dist/0~work-office-diagnostics.js +16 -5
- package/dist/4174.js +93 -8
- package/dist/internal/features/work/editors/controlled-editor-composition.d.ts +53 -7
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +3 -1
- package/dist/internal/features/work/work-document-changes.d.ts +4 -2
- package/dist/internal/features/work/work-document-compare-identities.d.ts +28 -0
- package/dist/internal/features/work/work-document-compare-moves.d.ts +60 -0
- package/dist/internal/features/work/work-document-compare.d.ts +2 -13
- package/dist/internal/features/work/work-docx-change-import.d.ts +10 -1
- package/dist/internal/features/work/work-docx-move-revision-export.d.ts +35 -0
- package/dist/internal/features/work/work-types.d.ts +3 -1
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +9 -0
- package/docs/latest/en/browser-editor-architecture.md +21 -5
- package/package.json +11 -3
|
@@ -4128,6 +4128,131 @@ function directListItemContentRoot(item) {
|
|
|
4128
4128
|
for (const child of item.childNodes)if (!(child instanceof HTMLElement) || 'ol' !== child.tagName.toLowerCase() && 'ul' !== child.tagName.toLowerCase()) root.append(child.cloneNode(true));
|
|
4129
4129
|
return root;
|
|
4130
4130
|
}
|
|
4131
|
+
const work_docx_move_revision_export_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
4132
|
+
const work_docx_move_revision_export_STORY_PATTERN = /^word\/(?:document|header\d*|footer\d*|footnotes|endnotes|comments)\.xml$/i;
|
|
4133
|
+
const MAX_MOVE_REVISION_PATCHES = 65536;
|
|
4134
|
+
const MAX_MOVE_TEXT_LENGTH = 1000000;
|
|
4135
|
+
class DocxMoveRevisionPatchCollector {
|
|
4136
|
+
patches = [];
|
|
4137
|
+
registrations = new WeakMap();
|
|
4138
|
+
nextWireId = -1;
|
|
4139
|
+
register(element, id, revisionDate = work_docx_move_revision_export_normalizedRevisionDate(element.dataset.changeDate)) {
|
|
4140
|
+
if (!element.hasAttribute('data-document-change') || 'move' !== element.dataset.changeKind) return null;
|
|
4141
|
+
const existing = this.registrations.get(element);
|
|
4142
|
+
if (existing) return existing;
|
|
4143
|
+
const role = moveRole(element.dataset.changeMoveRole);
|
|
4144
|
+
const author = element.dataset.changeAuthor?.trim() ?? '';
|
|
4145
|
+
const date = revisionDate;
|
|
4146
|
+
const key = element.dataset.changeId?.trim() ?? '';
|
|
4147
|
+
const text = element.textContent ?? '';
|
|
4148
|
+
if (!role || !key || key.length > 255 || /[\u0000-\u001f\u007f]/.test(key) || !Number.isSafeInteger(id) || id < 0 || !author || author.length > 255 || /[\u0000-\u001f\u007f]/.test(author) || !text || text.length > MAX_MOVE_TEXT_LENGTH || element.querySelector('[data-document-change]') || element.querySelector('[data-document-equation], [data-document-field], [data-document-note-reference], [data-document-content-control], img, br')) throw new Error('Document contains an invalid move revision.');
|
|
4149
|
+
if (this.patches.length >= MAX_MOVE_REVISION_PATCHES) throw new Error('Document exceeds the move revision limit.');
|
|
4150
|
+
const wireId = this.nextWireId;
|
|
4151
|
+
this.nextWireId -= 1;
|
|
4152
|
+
const registration = {
|
|
4153
|
+
kind: 'from' === role ? 'move-from' : 'move-to',
|
|
4154
|
+
wireId,
|
|
4155
|
+
id,
|
|
4156
|
+
author,
|
|
4157
|
+
date
|
|
4158
|
+
};
|
|
4159
|
+
this.registrations.set(element, registration);
|
|
4160
|
+
this.patches.push({
|
|
4161
|
+
wireId,
|
|
4162
|
+
id,
|
|
4163
|
+
role,
|
|
4164
|
+
author,
|
|
4165
|
+
date
|
|
4166
|
+
});
|
|
4167
|
+
return registration;
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
async function patchDocxMoveRevisions(buffer, patches) {
|
|
4171
|
+
if (!patches.length) return buffer;
|
|
4172
|
+
if (patches.length > MAX_MOVE_REVISION_PATCHES) throw new Error('Document exceeds the move revision limit.');
|
|
4173
|
+
const archive = await jszip.loadAsync(buffer);
|
|
4174
|
+
const byWireId = new Map();
|
|
4175
|
+
const logicalSides = new Map();
|
|
4176
|
+
for (const patch of patches){
|
|
4177
|
+
if (byWireId.has(patch.wireId)) throw new Error('Generated DOCX move revision wire IDs are duplicated.');
|
|
4178
|
+
byWireId.set(patch.wireId, patch);
|
|
4179
|
+
const logicalKey = `${patch.id}\u0000${patch.author}\u0000${patch.date}`;
|
|
4180
|
+
const sides = logicalSides.get(logicalKey) ?? {
|
|
4181
|
+
from: [],
|
|
4182
|
+
to: []
|
|
4183
|
+
};
|
|
4184
|
+
sides[patch.role].push(patch);
|
|
4185
|
+
logicalSides.set(logicalKey, sides);
|
|
4186
|
+
}
|
|
4187
|
+
for (const sides of logicalSides.values())if (!sides.from.length || !sides.to.length) throw new Error('A DOCX move revision must contain both moveFrom and moveTo sides.');
|
|
4188
|
+
const applied = new Map();
|
|
4189
|
+
const emittedText = new Map();
|
|
4190
|
+
for (const entry of Object.values(archive.files)){
|
|
4191
|
+
if (entry.dir || !work_docx_move_revision_export_STORY_PATTERN.test(entry.name)) continue;
|
|
4192
|
+
const document = parseXml(decodeXmlBytes(await entry.async('uint8array'), `generated DOCX ${entry.name}`), `generated DOCX ${entry.name}`);
|
|
4193
|
+
let changed = false;
|
|
4194
|
+
const wrappers = [
|
|
4195
|
+
...descendants(document, 'ins'),
|
|
4196
|
+
...descendants(document, 'del')
|
|
4197
|
+
];
|
|
4198
|
+
for (const wrapper of wrappers){
|
|
4199
|
+
if (!wrapper.parentNode) continue;
|
|
4200
|
+
if (!DOCX_WORDPROCESSING_NAMESPACES.has(wrapper.namespaceURI ?? '')) continue;
|
|
4201
|
+
const wireId = numericWordAttribute(wrapper, 'id');
|
|
4202
|
+
if (null === wireId) continue;
|
|
4203
|
+
const patch = byWireId.get(wireId);
|
|
4204
|
+
if (!patch) continue;
|
|
4205
|
+
const expectedName = 'from' === patch.role ? 'del' : 'ins';
|
|
4206
|
+
if (wrapper.localName !== expectedName) throw new Error(`Generated DOCX move revision ${patch.wireId} has the wrong wrapper kind.`);
|
|
4207
|
+
const replacement = document.createElementNS(wrapper.namespaceURI, `${xmlNamespacePrefix(wrapper, wrapper.namespaceURI) ?? 'w'}:${'from' === patch.role ? 'moveFrom' : 'moveTo'}`);
|
|
4208
|
+
for (const child of Array.from(wrapper.attributes)){
|
|
4209
|
+
const namespace = xmlAttributeNamespace(wrapper, child);
|
|
4210
|
+
if (namespace) replacement.setAttributeNS(namespace, child.name, child.value);
|
|
4211
|
+
else replacement.setAttribute(child.name, child.value);
|
|
4212
|
+
}
|
|
4213
|
+
work_docx_move_revision_export_setWordAttribute(replacement, 'id', String(patch.id));
|
|
4214
|
+
work_docx_move_revision_export_setWordAttribute(replacement, 'author', patch.author);
|
|
4215
|
+
work_docx_move_revision_export_setWordAttribute(replacement, 'date', patch.date);
|
|
4216
|
+
const text = Array.from(wrapper.querySelectorAll('*')).filter((element)=>'from' === patch.role ? 'delText' === element.localName : 't' === element.localName).map((element)=>element.textContent ?? '').join('');
|
|
4217
|
+
emittedText.set(patch.wireId, `${emittedText.get(patch.wireId) ?? ''}${text}`);
|
|
4218
|
+
while(wrapper.firstChild)replacement.append(wrapper.firstChild);
|
|
4219
|
+
wrapper.replaceWith(replacement);
|
|
4220
|
+
applied.set(patch.wireId, (applied.get(patch.wireId) ?? 0) + 1);
|
|
4221
|
+
changed = true;
|
|
4222
|
+
}
|
|
4223
|
+
if (changed) archive.file(entry.name, serializeUtf8Xml(document));
|
|
4224
|
+
}
|
|
4225
|
+
const missing = patches.filter((patch)=>!applied.has(patch.wireId));
|
|
4226
|
+
if (missing.length) throw new Error(`DOCX move revision markers were not emitted: ${missing.map((patch)=>patch.wireId).join(', ')}.`);
|
|
4227
|
+
for (const sides of logicalSides.values()){
|
|
4228
|
+
const from = sides.from.map((patch)=>emittedText.get(patch.wireId) ?? '').join('');
|
|
4229
|
+
const to = sides.to.map((patch)=>emittedText.get(patch.wireId) ?? '').join('');
|
|
4230
|
+
if (!from || !to || from !== to) throw new Error('A DOCX move revision source and destination must contain the same text.');
|
|
4231
|
+
}
|
|
4232
|
+
return archive.generateAsync({
|
|
4233
|
+
type: 'arraybuffer'
|
|
4234
|
+
});
|
|
4235
|
+
}
|
|
4236
|
+
function moveRole(value) {
|
|
4237
|
+
return 'from' === value || 'to' === value ? value : null;
|
|
4238
|
+
}
|
|
4239
|
+
function numericWordAttribute(element, localName) {
|
|
4240
|
+
const namespace = element.namespaceURI;
|
|
4241
|
+
if (!namespace) return null;
|
|
4242
|
+
const attributes = Array.from(element.attributes).filter((candidate)=>xmlAttributeLocalName(candidate) === localName && xmlAttributeNamespace(element, candidate) === namespace);
|
|
4243
|
+
if (1 !== attributes.length) return null;
|
|
4244
|
+
const value = Number(attributes[0]?.value);
|
|
4245
|
+
return Number.isSafeInteger(value) ? value : null;
|
|
4246
|
+
}
|
|
4247
|
+
function work_docx_move_revision_export_setWordAttribute(element, localName, value) {
|
|
4248
|
+
const namespace = element.namespaceURI ?? work_docx_move_revision_export_WORD_NAMESPACE;
|
|
4249
|
+
const prefix = xmlNamespacePrefix(element, namespace) ?? element.prefix ?? 'w';
|
|
4250
|
+
element.setAttributeNS(namespace, `${prefix}:${localName}`, value);
|
|
4251
|
+
}
|
|
4252
|
+
function work_docx_move_revision_export_normalizedRevisionDate(value) {
|
|
4253
|
+
const time = Date.parse(value ?? '');
|
|
4254
|
+
return Number.isFinite(time) ? new Date(time).toISOString() : new Date().toISOString();
|
|
4255
|
+
}
|
|
4131
4256
|
const DRAWINGML_NAMESPACES = new Set([
|
|
4132
4257
|
'http://schemas.openxmlformats.org/drawingml/2006/main',
|
|
4133
4258
|
'http://purl.oclc.org/ooxml/drawingml/main'
|
|
@@ -8526,6 +8651,8 @@ async function createDocxBlob(content, sourcePackage) {
|
|
|
8526
8651
|
usedOpenTypeMarkers: new Set(),
|
|
8527
8652
|
paragraphFormattingChangePatches: new DocxParagraphFormattingChangePatchCollector(),
|
|
8528
8653
|
numberingChangePatches: new DocxNumberingChangePatchCollector(),
|
|
8654
|
+
moveRevisionPatches: new DocxMoveRevisionPatchCollector(),
|
|
8655
|
+
moveRevisionDefaultDate: new Date().toISOString(),
|
|
8529
8656
|
tableOfContentsPatches: new DocxTableOfContentsPatchCollector(),
|
|
8530
8657
|
indexPatches: new DocxIndexPatchCollector(),
|
|
8531
8658
|
hasExplicitZeroCharacterSpacing: false,
|
|
@@ -8606,7 +8733,8 @@ async function createDocxBlob(content, sourcePackage) {
|
|
|
8606
8733
|
const indexPatched = await patchDocxIndexes(tableOfContentsPatched, noteContext.indexPatches.patches);
|
|
8607
8734
|
const paragraphFormattingChangesPatched = await patchDocxParagraphFormattingChanges(indexPatched, noteContext.paragraphFormattingChangePatches.patches);
|
|
8608
8735
|
const numberingChangesPatched = await patchDocxNumberingChanges(paragraphFormattingChangesPatched, noteContext.numberingChangePatches.patches);
|
|
8609
|
-
const
|
|
8736
|
+
const moveRevisionsPatched = await patchDocxMoveRevisions(numberingChangesPatched, noteContext.moveRevisionPatches.patches);
|
|
8737
|
+
const equationPatched = await patchDocxEquations(moveRevisionsPatched, noteContext.equationPatches.patches);
|
|
8610
8738
|
const patched = await patchDocxPageColor(equationPatched, normalizedContent.pageColor);
|
|
8611
8739
|
const contentControlsPatched = await patchDocxContentControls(patched, noteContext.contentControlPatches.patches);
|
|
8612
8740
|
const preserved = sourcePackage ? await preserveDocxSourcePackage(contentControlsPatched, sourcePackage, {
|
|
@@ -8987,19 +9115,19 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
|
|
|
8987
9115
|
markDocxRunStyleMarkersUsed(inherited.style, noteContext);
|
|
8988
9116
|
markDocxRunBorderUsed(inherited.border, noteContext);
|
|
8989
9117
|
markDocxRunShadingUsed(inherited.shading, noteContext);
|
|
8990
|
-
if (revision?.kind === 'insertion') return [
|
|
9118
|
+
if (revision?.kind === 'insertion' || revision?.kind === 'move-to') return [
|
|
8991
9119
|
new docx.InsertedTextRun({
|
|
8992
9120
|
...inherited,
|
|
8993
|
-
id: revision.id,
|
|
9121
|
+
id: revision.wireId ?? revision.id,
|
|
8994
9122
|
author: revision.author,
|
|
8995
9123
|
date: revision.date,
|
|
8996
9124
|
text: node.textContent
|
|
8997
9125
|
})
|
|
8998
9126
|
];
|
|
8999
|
-
if (revision?.kind === 'deletion') return [
|
|
9127
|
+
if (revision?.kind === 'deletion' || revision?.kind === 'move-from') return [
|
|
9000
9128
|
new docx.DeletedTextRun({
|
|
9001
9129
|
...inherited,
|
|
9002
|
-
id: revision.id,
|
|
9130
|
+
id: revision.wireId ?? revision.id,
|
|
9003
9131
|
author: revision.author,
|
|
9004
9132
|
date: revision.date,
|
|
9005
9133
|
text: node.textContent
|
|
@@ -9050,7 +9178,7 @@ async function work_docx_export_inlineRuns(root, docx, noteContext) {
|
|
|
9050
9178
|
for (const child of node.childNodes)children.push(...await visit(child, inherited, revision));
|
|
9051
9179
|
return docxContentControlRuns(node, docx, noteContext.contentControlPatches, children);
|
|
9052
9180
|
}
|
|
9053
|
-
const textRevisionKind = 'del' === tag ? 'deletion' : 'ins' === tag ? 'insertion' : null;
|
|
9181
|
+
const textRevisionKind = 'del' === tag ? 'move' === node.dataset.changeKind ? 'move-from' : 'deletion' : 'ins' === tag ? 'move' === node.dataset.changeKind ? 'move-to' : 'insertion' : null;
|
|
9054
9182
|
const change = node.hasAttribute('data-document-change') && textRevisionKind ? docxTextRevision(node, textRevisionKind, noteContext) : revision;
|
|
9055
9183
|
const formattingChange = node.hasAttribute('data-document-change') && 'formatting' === node.dataset.changeKind ? noteContext.formattingChangePatches.register(node, docxRevisionId(node, noteContext)) : null;
|
|
9056
9184
|
const commentBoundary = node.hasAttribute('data-document-comment') ? nextDocxCommentBoundary(node.dataset.commentId, noteContext) : null;
|
|
@@ -9273,12 +9401,18 @@ function docxTextRevision(element, kind, context) {
|
|
|
9273
9401
|
const id = docxRevisionId(element, context);
|
|
9274
9402
|
const sourceDate = element.dataset.changeDate?.trim() ?? '';
|
|
9275
9403
|
const time = Date.parse(sourceDate);
|
|
9276
|
-
|
|
9404
|
+
const revision = {
|
|
9277
9405
|
kind,
|
|
9278
9406
|
id,
|
|
9279
9407
|
author: element.dataset.changeAuthor?.trim() || 'A3S Work',
|
|
9280
|
-
date: Number.isFinite(time) ? new Date(time).toISOString() : new Date().toISOString()
|
|
9408
|
+
date: Number.isFinite(time) ? new Date(time).toISOString() : 'move-from' === kind || 'move-to' === kind ? context.moveRevisionDefaultDate : new Date().toISOString()
|
|
9281
9409
|
};
|
|
9410
|
+
if ('move-from' === kind || 'move-to' === kind) {
|
|
9411
|
+
const registration = context.moveRevisionPatches.register(element, id, revision.date);
|
|
9412
|
+
if (!registration) throw new Error('Document contains an invalid move revision.');
|
|
9413
|
+
revision.wireId = registration.wireId;
|
|
9414
|
+
}
|
|
9415
|
+
return revision;
|
|
9282
9416
|
}
|
|
9283
9417
|
function docxRevisionId(element, context, suffix) {
|
|
9284
9418
|
const baseKey = element.dataset.changeId?.trim() || `change-${context.nextChangeId}`;
|
|
@@ -9293,7 +9427,7 @@ function docxRevisionId(element, context, suffix) {
|
|
|
9293
9427
|
}
|
|
9294
9428
|
function documentHasTrackedChanges(html) {
|
|
9295
9429
|
const document = new DOMParser().parseFromString(html, 'text/html');
|
|
9296
|
-
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"], [data-document-change][data-change-kind="numbering"]'));
|
|
9430
|
+
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"], [data-document-change][data-change-kind="numbering"], [data-document-change][data-change-kind="move"]'));
|
|
9297
9431
|
}
|
|
9298
9432
|
function anchoredDocumentComments(content) {
|
|
9299
9433
|
const document = new DOMParser().parseFromString(content.html, 'text/html');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import jszip from "jszip";
|
|
2
2
|
import { documentRunBorderDomAttributes, contentTypeForPart, bytesToDataUrl, OoxmlPackage, normalizeDocumentIndexesHtml, firstDescendant, normalizeDocumentParagraphId, applyDocumentParagraphIdentityToElement, descendants, documentHighlightDomAttributes, attribute as work_ooxml_package_attribute, documentHighlightFromDocxValue, serializeDocxThemeReference, normalizeDocumentTableOfContentsHtml, directChildren, documentParagraphShadingDomAttributes, documentProofingDomAttributes, documentParagraphBordersDomAttributes, directChild, documentScriptFontSegments, normalizeDocumentParagraphIdentity, documentRunShadingDomAttributes } from "./6968.js";
|
|
3
3
|
import { normalizeDocumentBookmarkName, renderDocumentTableCellMarginOverrides, applyDocumentImageIdentityToElement, documentCharacterPositionDomAttributes, createDocumentImageIdentityRegistry, normalizeDocumentColumns, documentStrikeDomAttributes, normalizeDocumentImageWrapContour, DOCUMENT_TABLE_ROW_ID_ATTRIBUTE, normalizeDocumentBookmarksHtml, applyDocumentTableRowIdentityToElement, normalizeDocumentCaptionsHtml, documentCharacterSpacingDomAttributes, normalizeDocumentImageAlignment, applyDocumentImageLayerToElement, normalizeDocumentNotesHtml, normalizeDocumentBookmarkReferencesHtml, documentCitationTagsFromInstruction, applyDocumentImageWrapContourToElement, documentUnderlineDomAttributes, documentHiddenTextDomAttributes, normalizeDocumentPageChrome, normalizeDocumentImageLayoutOptions, applyDocumentImageCropToElement, documentPageMarginsForLayout, applyDocumentPageGeometry, createDocumentNoteElement, normalizeDocumentImageLayer, DOCUMENT_TABLE_ROW_TEXT_ID_ATTRIBUTE, documentBookmarkReferenceInstruction, applyDocumentImageTransformToElement, documentInitialSectionLayout, normalizeDocumentFieldsHtml, documentCaptionLabel, documentTableBordersFromElement, isContourImageLayout, normalizeDocumentCitationsHtml, normalizeDocumentImageIdentity, normalizeDocumentImageWrapSide, supportedDocxDocumentFieldInstruction, documentKerningDomAttributes, docxDocumentFieldKind, renderDocumentTableBorders, docxBookmarkReferenceTarget, normalizeDocumentImagePosition, wrapsBesideImage, documentPageChromeLegacyFields, documentCharacterScaleDomAttributes, DEFAULT_DOCUMENT_TABLE_GEOMETRY, documentSectionDomAttributes, DEFAULT_DOCUMENT_TABLE_CELL_MARGINS, documentPageMarginBody, documentLegacyTextEffectsDomAttributes, normalizeDocumentTableRowIdentity, normalizeDocumentBookmarkNativeId, documentOpenTypeDomAttributes, uniqueDocumentImageIdentity, applyDocumentTableGeometryToElement, normalizeDocumentImageCrop, documentContentLayoutProperties, documentEmphasisMarkDomAttributes, docxDocumentFieldTarget } from "./4174.js";
|
|
4
|
-
import { hasImportedDocxIndexMarkers, markDocxRunFormattingIntoState, applyImportedDocxParagraphSpacingMarkers, hasImportedDocxParagraphDirectionMarkers, hasImportedDocxParagraphIndentMarkers, resolveDocxParagraphBordersForParagraph, applyImportedDocxTextBoxMarkers, applyImportedDocxNumberingChangeMarkers, applyImportedDocxParagraphShadingMarkers, markDocxParagraphSpacing, docxCaptionBookmark, docxFieldResultText, applyImportedDocxContentControlMarkers, createDocxParagraphStyleResolver, markDocxTextBoxes, docxTableCellStyleLayers,
|
|
4
|
+
import { hasImportedDocxIndexMarkers, markDocxRunFormattingIntoState, applyImportedDocxParagraphSpacingMarkers, hasImportedDocxParagraphDirectionMarkers, hasImportedDocxParagraphIndentMarkers, resolveDocxParagraphBordersForParagraph, applyImportedDocxTextBoxMarkers, applyImportedDocxNumberingChangeMarkers, applyImportedDocxParagraphShadingMarkers, applyImportedDocxChangeMarkers, markDocxParagraphSpacing, docxCaptionBookmark, docxFieldResultText, applyImportedDocxContentControlMarkers, createDocxParagraphStyleResolver, markDocxTextBoxes, docxTableCellStyleLayers, markDocxTextChanges, markDocxContentControls, createImportedDocxRunFormattingMarkerState, parseDocxPaperSource, resolveDocxLegacyTextEffects, markDocxTablesOfContents, applyImportedDocxIndexMarkers, docxTablePropertySources, applyImportedDocxTableOfContentsMarkers, markDocxIndexes, parseDirectDocxParagraphShading, markDocxPackageEquations, hasImportedDocxParagraphSpacingMarkers, markDocxParagraphIndents, parseDocxPageMargins, resolveDocxRunBorder, parseDocxPageGeometry, docxCaptionReferenceTarget, applyImportedDocxEquationMarkers, hasImportedDocxParagraphPaginationMarkers, createDocxTableStyleResolver, hasImportedDocxParagraphShadingMarkers, isDocxEquationLikeRoot, importedDocxStrike, docxTableRunPropertySources, hasImportedDocxNumberingChangeMarkers, inspectDocxPageMarginSettings, hasImportedDocxRunFormattingMarkers, hasImportedDocxTableOfContentsMarkers, applyImportedDocxParagraphFormattingChangeMarkers, hasImportedDocxContentControlMarkers, hasImportedDocxParagraphTabStopMarkers, resolveDocxRunShading, docxCaptionSequenceKind, applyImportedDocxRunFormattingMarkers, markDocxParagraphAlignments, markDocxParagraphDirections, hasImportedDocxParagraphBorderMarkers, hasImportedDocxParagraphFormattingChangeMarkers, resolveDocxHiddenText, docxEquationHtml, docxFieldOccurrences, hasImportedDocxParagraphAlignmentMarkers, markDocxParagraphTabStops, applyImportedDocxParagraphIndentMarkers, applyImportedDocxParagraphDirectionMarkers, applyImportedDocxParagraphAlignmentMarkers, resolveDocxTableStyleResolver, hasImportedDocxTextBoxMarkers, importedDocxUnderline, markDocxParagraphBorders, markDocxNumberingChanges, markDocxParagraphPagination, hasImportedDocxChangeMarkers, docxFieldOccurrenceIsInlineEditable, applyImportedDocxParagraphBorderMarkers, applyImportedDocxParagraphPaginationMarkers, applyImportedDocxParagraphTabStopMarkers, docxRunPropertySources, markDocxParagraphFormattingChanges, markDocxParagraphShading, parseDocxPageBorders } from "./0~5600.js";
|
|
5
5
|
import { readDocxBibliography, resolveDocxProofing, XMLNS_NAMESPACE, docxCharacterScalePercentFromProperties, docxCharacterSpacingTwipsFromProperties, parseBoundedDocxInteger, resolveDocxOpenTypeFeatures, xmlAttributeLocalName, resolveDocxEmphasisMark, createDocxThemeResolver, docxCharacterPositionHalfPointsFromProperties, readDocxImageTransform, docxThemeColor, parseDocxParagraphDefaultCollapsed, resolveDocxKerningThresholdHalfPoints, resolveDocxThemeResolver, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace } from "./0~3534.js";
|
|
6
6
|
import { importDocxPageColor, importedDocumentNoteId } from "./0~4980.js";
|
|
7
7
|
const WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
@@ -428,121 +428,6 @@ function work_docx_caption_import_textNodes(root) {
|
|
|
428
428
|
while(walker.nextNode())nodes.push(walker.currentNode);
|
|
429
429
|
return nodes;
|
|
430
430
|
}
|
|
431
|
-
const work_docx_change_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
432
|
-
const work_docx_change_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
|
|
433
|
-
function markDocxTextChanges(document) {
|
|
434
|
-
const changes = [];
|
|
435
|
-
const revisions = [
|
|
436
|
-
...descendants(document, 'ins'),
|
|
437
|
-
...descendants(document, 'del')
|
|
438
|
-
].sort(compareDocumentOrder);
|
|
439
|
-
for (const revision of revisions){
|
|
440
|
-
if (!revision.parentNode || closestRevision(revision.parentElement)) continue;
|
|
441
|
-
const kind = 'del' === revision.localName ? 'deletion' : 'insertion';
|
|
442
|
-
if (!revisionText(revision, kind)) continue;
|
|
443
|
-
if ('deletion' === kind) convertDeletedText(document, revision);
|
|
444
|
-
const index = changes.length + 1;
|
|
445
|
-
const sourceId = work_ooxml_package_attribute(revision, 'id')?.trim() ?? '';
|
|
446
|
-
const id = uniqueChangeId(sourceId ? `docx-change-${sourceId}` : `docx-change-${index}`, changes);
|
|
447
|
-
const marker = {
|
|
448
|
-
id,
|
|
449
|
-
kind,
|
|
450
|
-
author: work_ooxml_package_attribute(revision, 'author')?.trim() || '未知审阅者',
|
|
451
|
-
date: normalizeDate(work_ooxml_package_attribute(revision, 'date')),
|
|
452
|
-
start: `__A3S_WORK_CHANGE_START_${index}__`,
|
|
453
|
-
end: `__A3S_WORK_CHANGE_END_${index}__`
|
|
454
|
-
};
|
|
455
|
-
unwrapRevision(document, revision, marker.start, marker.end);
|
|
456
|
-
changes.push(marker);
|
|
457
|
-
}
|
|
458
|
-
return {
|
|
459
|
-
changes
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
function applyImportedDocxChangeMarkers(document, markers) {
|
|
463
|
-
for (const marker of markers.changes){
|
|
464
|
-
const element = document.createElement('deletion' === marker.kind ? 'del' : 'ins');
|
|
465
|
-
element.dataset.documentChange = 'true';
|
|
466
|
-
element.dataset.changeKind = marker.kind;
|
|
467
|
-
element.dataset.changeId = marker.id;
|
|
468
|
-
element.dataset.changeAuthor = marker.author;
|
|
469
|
-
element.dataset.changeDate = marker.date;
|
|
470
|
-
wrapMarkerRange(document.body, marker.start, marker.end, element);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
function hasImportedDocxChangeMarkers(markers) {
|
|
474
|
-
return markers.changes.length > 0;
|
|
475
|
-
}
|
|
476
|
-
function revisionText(revision, kind) {
|
|
477
|
-
const names = 'deletion' === kind ? [
|
|
478
|
-
'delText',
|
|
479
|
-
't'
|
|
480
|
-
] : [
|
|
481
|
-
't'
|
|
482
|
-
];
|
|
483
|
-
return names.flatMap((name)=>descendants(revision, name)).map((element)=>element.textContent ?? '').join('');
|
|
484
|
-
}
|
|
485
|
-
function convertDeletedText(document, revision) {
|
|
486
|
-
for (const deleted of descendants(revision, 'delText')){
|
|
487
|
-
const text = document.createElementNS(work_docx_change_import_WORD_NAMESPACE, 'w:t');
|
|
488
|
-
const preserve = deleted.getAttributeNS(work_docx_change_import_XML_NAMESPACE, 'space') ?? deleted.getAttribute('xml:space');
|
|
489
|
-
if (preserve) text.setAttributeNS(work_docx_change_import_XML_NAMESPACE, 'xml:space', preserve);
|
|
490
|
-
text.textContent = deleted.textContent;
|
|
491
|
-
deleted.replaceWith(text);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
function unwrapRevision(document, revision, start, end) {
|
|
495
|
-
const parent = revision.parentNode;
|
|
496
|
-
if (!parent) return;
|
|
497
|
-
parent.insertBefore(work_docx_change_import_markerRun(document, start), revision);
|
|
498
|
-
while(revision.firstChild)parent.insertBefore(revision.firstChild, revision);
|
|
499
|
-
parent.insertBefore(work_docx_change_import_markerRun(document, end), revision);
|
|
500
|
-
revision.remove();
|
|
501
|
-
}
|
|
502
|
-
function work_docx_change_import_markerRun(document, value) {
|
|
503
|
-
const run = document.createElementNS(work_docx_change_import_WORD_NAMESPACE, 'w:r');
|
|
504
|
-
const text = document.createElementNS(work_docx_change_import_WORD_NAMESPACE, 'w:t');
|
|
505
|
-
text.setAttributeNS(work_docx_change_import_XML_NAMESPACE, 'xml:space', 'preserve');
|
|
506
|
-
text.textContent = value;
|
|
507
|
-
run.append(text);
|
|
508
|
-
return run;
|
|
509
|
-
}
|
|
510
|
-
function wrapMarkerRange(root, start, end, wrapper) {
|
|
511
|
-
const html = root.innerHTML;
|
|
512
|
-
const startIndex = html.indexOf(start);
|
|
513
|
-
const endIndex = html.indexOf(end, startIndex + start.length);
|
|
514
|
-
if (startIndex < 0 || endIndex < 0) return false;
|
|
515
|
-
const closingTag = `</${wrapper.localName}>`;
|
|
516
|
-
const serializedWrapper = wrapper.outerHTML;
|
|
517
|
-
if (!serializedWrapper.endsWith(closingTag)) return false;
|
|
518
|
-
const openingTag = serializedWrapper.slice(0, -closingTag.length);
|
|
519
|
-
root.innerHTML = `${html.slice(0, startIndex)}${openingTag}${html.slice(startIndex + start.length, endIndex)}${closingTag}${html.slice(endIndex + end.length)}`;
|
|
520
|
-
return true;
|
|
521
|
-
}
|
|
522
|
-
function closestRevision(element) {
|
|
523
|
-
let current = element;
|
|
524
|
-
while(current){
|
|
525
|
-
if ('ins' === current.localName || 'del' === current.localName) return current;
|
|
526
|
-
current = current.parentElement;
|
|
527
|
-
}
|
|
528
|
-
return null;
|
|
529
|
-
}
|
|
530
|
-
function uniqueChangeId(base, changes) {
|
|
531
|
-
const ids = new Set(changes.map((change)=>change.id));
|
|
532
|
-
if (!ids.has(base)) return base;
|
|
533
|
-
let suffix = 2;
|
|
534
|
-
while(ids.has(`${base}-${suffix}`))suffix += 1;
|
|
535
|
-
return `${base}-${suffix}`;
|
|
536
|
-
}
|
|
537
|
-
function normalizeDate(value) {
|
|
538
|
-
if (!value) return '';
|
|
539
|
-
const time = Date.parse(value);
|
|
540
|
-
return Number.isFinite(time) ? new Date(time).toISOString() : '';
|
|
541
|
-
}
|
|
542
|
-
function compareDocumentOrder(left, right) {
|
|
543
|
-
if (left === right) return 0;
|
|
544
|
-
return left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
545
|
-
}
|
|
546
431
|
const work_docx_citation_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
547
432
|
const work_docx_citation_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
|
|
548
433
|
function markDocxCitationFields(document) {
|
|
@@ -744,7 +629,7 @@ async function markDocxComments(document, archive) {
|
|
|
744
629
|
const workIds = new Map();
|
|
745
630
|
const ranges = [];
|
|
746
631
|
const comments = [];
|
|
747
|
-
const starts = descendants(document, 'commentRangeStart').sort(
|
|
632
|
+
const starts = descendants(document, 'commentRangeStart').sort(compareDocumentOrder);
|
|
748
633
|
for (const start of starts){
|
|
749
634
|
const sourceId = work_ooxml_package_attribute(start, 'id')?.trim() ?? '';
|
|
750
635
|
if (!sourceId) continue;
|
|
@@ -794,7 +679,7 @@ async function readCommentDefinitions(archive) {
|
|
|
794
679
|
return {
|
|
795
680
|
sourceId: work_ooxml_package_attribute(comment, 'id')?.trim() ?? '',
|
|
796
681
|
author: work_ooxml_package_attribute(comment, 'author')?.trim() || '未知审阅者',
|
|
797
|
-
date:
|
|
682
|
+
date: normalizeDate(work_ooxml_package_attribute(comment, 'date')),
|
|
798
683
|
text: commentText(comment),
|
|
799
684
|
paraId,
|
|
800
685
|
parentParaId: metadata?.parentParaId ?? '',
|
|
@@ -922,12 +807,12 @@ function uniqueWorkCommentId(base, comments) {
|
|
|
922
807
|
while(ids.has(`${base}-${suffix}`))suffix += 1;
|
|
923
808
|
return `${base}-${suffix}`;
|
|
924
809
|
}
|
|
925
|
-
function
|
|
810
|
+
function normalizeDate(value) {
|
|
926
811
|
if (!value) return '';
|
|
927
812
|
const time = Date.parse(value);
|
|
928
813
|
return Number.isFinite(time) ? new Date(time).toISOString() : '';
|
|
929
814
|
}
|
|
930
|
-
function
|
|
815
|
+
function compareDocumentOrder(left, right) {
|
|
931
816
|
if (left === right) return 0;
|
|
932
817
|
return left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
933
818
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __webpack_require__ } from "./0~rslib-runtime.js";
|
|
2
2
|
import { contentTypeForPart, directChildren, OoxmlPackage, parseXml, firstDescendant, isDocumentParagraphArtBorderStyle, descendants, directChild, xmlContainsAnyElement, attribute, documentRunBorderIsVisible } from "./6968.js";
|
|
3
3
|
import { normalizeDocumentBookmarkName, docxBookmarkReferenceTarget, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, normalizeDocumentBookmarkNativeId, supportedDocxDocumentFieldInstruction, supportedDocxBookmarkReferenceInstruction, documentCitationTagsFromInstruction, docxDocumentFieldKind, docxDocumentFieldTarget } from "./4174.js";
|
|
4
|
-
import { isSupportedDocxEquationPlacement, inspectDocxPageSize, inspectDocxContentControls, hasInvalidDocxFieldStructure, createDocxTableStyleResolver, inspectDocxRunBorder, inspectDocxEquation, inspectDocxPageMarginSettings, inspectDocxRunShading, supportedDocxIndexField, docxCaptionSequenceKind, inspectDocxPageBorders, docxCaptionBookmark, inspectDocxLegacyTextEffects, inspectDocxPageMargins, inspectDocxPaperSource, createDocxParagraphStyleResolver, inspectDocxRunFonts, supportedDocxTableOfContentsField, docxFieldOccurrences, supportedDocxIndexEntryField, inspectDocxTextBoxes, markDocxParagraphBorders, isSupportedDocxParagraphFormattingChange, docxFieldOccurrenceIsInlineEditable, inspectDocxHiddenText, isSupportedDocxRunFormattingChange, isSupportedDocxNumberingChange, markDocxParagraphShading, docxFieldInstructions } from "./0~
|
|
4
|
+
import { isSupportedDocxEquationPlacement, inspectDocxPageSize, inspectDocxContentControls, hasInvalidDocxFieldStructure, createDocxTableStyleResolver, inspectDocxRunBorder, inspectDocxEquation, inspectDocxPageMarginSettings, inspectDocxRunShading, supportedDocxMovePairCount, supportedDocxIndexField, docxCaptionSequenceKind, inspectDocxPageBorders, isSupportedDocxMoveChange, docxCaptionBookmark, inspectDocxLegacyTextEffects, inspectDocxPageMargins, inspectDocxPaperSource, createDocxParagraphStyleResolver, inspectDocxRunFonts, supportedDocxTableOfContentsField, docxFieldOccurrences, supportedDocxIndexEntryField, inspectDocxTextBoxes, markDocxParagraphBorders, isSupportedDocxParagraphFormattingChange, docxFieldOccurrenceIsInlineEditable, inspectDocxHiddenText, isSupportedDocxRunFormattingChange, isSupportedDocxNumberingChange, markDocxParagraphShading, docxFieldInstructions } from "./0~5600.js";
|
|
5
5
|
import { normalizeDocumentHref } from "./0~work-document-links.js";
|
|
6
6
|
import { xmlAttributeLocalName, resolveDocxOpenTypeFeatures, inspectDocxProofingLanguages, readDocxBibliography, inspectDocxEmphasisMark, createDocxThemeResolver, DOCX_WORD_2010_NAMESPACE, inspectDocxNoProof, parseDocxParagraphDefaultCollapsed, readDocxImageTransform, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace, inspectDocxKerningThresholdHalfPoints } from "./0~3534.js";
|
|
7
7
|
import { updateSpreadsheetWorksheetCompatibilitySummary, inspectXlsxPivotTables, isSupportedXlsxChartLegend, isSupportedXlsxChartPlotLayout, xlsxChartNodeUsesStackedGrouping, isSupportedXlsxChartSeriesFormatting, readXlsxFormulaFeaturesFromPackage, inspectXlsxHeaderFooterText, emptySpreadsheetWorksheetCompatibilitySummary, isSupportedXlsxWorksheetImageContentType, MAX_XLSX_WORKSHEET_IMAGE_BYTES, xlsxChartSeriesFormattingShapeProperties, diagnoseXlsxProtection, isEditableXlsxPaperSizeCode, isSupportedXlsxCombinationChartNodes } from "./4166.js";
|
|
@@ -2223,6 +2223,14 @@ async function analyzeDocxCompatibility(file, messages, sourcePackage) {
|
|
|
2223
2223
|
...descendants(document, 'ins'),
|
|
2224
2224
|
...descendants(document, 'del')
|
|
2225
2225
|
];
|
|
2226
|
+
const moveFromRevisions = descendants(document, 'moveFrom');
|
|
2227
|
+
const moveToRevisions = descendants(document, 'moveTo');
|
|
2228
|
+
const moveRevisionCount = moveFromRevisions.length + moveToRevisions.length;
|
|
2229
|
+
const supportedMovePairCount = supportedDocxMovePairCount(document);
|
|
2230
|
+
const supportedMoveRevisionCount = [
|
|
2231
|
+
...moveFromRevisions,
|
|
2232
|
+
...moveToRevisions
|
|
2233
|
+
].filter(isSupportedDocxMoveChange).length;
|
|
2226
2234
|
const runFormattingRevisions = descendants(document, 'rPrChange');
|
|
2227
2235
|
const paragraphFormattingRevisions = descendants(document, 'pPrChange');
|
|
2228
2236
|
const numberingRevisions = descendants(document, 'numberingChange');
|
|
@@ -2233,14 +2241,17 @@ async function analyzeDocxCompatibility(file, messages, sourcePackage) {
|
|
|
2233
2241
|
if (supportedRunFormattingRevisionCount) issues.push(work_office_diagnostics_issue('docx.revisions.formatting', 'Character-formatting revisions', `${supportedRunFormattingRevisionCount} bounded character-formatting revision(s) preserve author, date, current formatting, and prior bold, italic, underline, strike, text case, hidden text, outline, shadow, emboss, imprint, subscript, superscript, font, size, color, highlight, character borders, character shading, character scale, spacing, kerning threshold, emphasis mark, baseline position, grid state, proofing languages, and explicit proofing state. They remain reviewable in Work and round-trip as native w:rPrChange records.`, 'info'));
|
|
2234
2242
|
if (supportedParagraphFormattingRevisionCount) issues.push(work_office_diagnostics_issue('docx.revisions.paragraph-formatting', 'Paragraph-formatting revisions', `${supportedParagraphFormattingRevisionCount} bounded paragraph-formatting revision(s) preserve author, date, current formatting, and prior alignment, direction, indentation, spacing, pagination, outline, tab-stop, border, shading, and collapsed state. They remain reviewable in Work and round-trip as native w:pPrChange records.`, 'info'));
|
|
2235
2243
|
if (supportedNumberingRevisionCount) issues.push(work_office_diagnostics_issue('docx.revisions.numbering', 'Numbering revisions', `${supportedNumberingRevisionCount} bounded ordered-list numbering revision(s) preserve author, date, prior start, and common decimal, letter, or Roman formats. Contiguous list-item records remain reviewable as one Work change and round-trip as native w:numberingChange records.`, 'info'));
|
|
2236
|
-
if (
|
|
2237
|
-
|
|
2238
|
-
'
|
|
2244
|
+
if (supportedMovePairCount) issues.push(work_office_diagnostics_issue('docx.revisions.move', 'Move revisions', `${supportedMovePairCount} bounded text move revision(s) preserve author, date, source and destination text, remain reviewable as one atomic Work change, and round-trip as native w:moveFrom and w:moveTo records. Rich content, range markers, and relationship-bound moves remain on the compatibility path.`, 'info'));
|
|
2245
|
+
if (textRevisions.some((revision)=>!descendants(revision, 't').length && !descendants(revision, 'delText').length) || supportedRunFormattingRevisionCount !== runFormattingRevisions.length || supportedParagraphFormattingRevisionCount !== paragraphFormattingRevisions.length || supportedNumberingRevisionCount !== numberingRevisions.length || supportedMoveRevisionCount !== moveRevisionCount || supportedMoveRevisionCount !== 2 * supportedMovePairCount || [
|
|
2246
|
+
'moveFromRangeStart',
|
|
2247
|
+
'moveFromRangeEnd',
|
|
2248
|
+
'moveToRangeStart',
|
|
2249
|
+
'moveToRangeEnd',
|
|
2239
2250
|
'tblPrChange',
|
|
2240
2251
|
'trPrChange',
|
|
2241
2252
|
'tcPrChange',
|
|
2242
2253
|
'sectPrChange'
|
|
2243
|
-
].some((name)=>descendants(document, name).length)) issues.push(work_office_diagnostics_issue('docx.revisions.structural', 'Structural revisions', 'Moved content plus unsupported character formatting, paragraph formatting, numbering, section, row, cell, and table-property revisions may be normalized; Work currently reviews body-text insertions/deletions and bounded character-, paragraph-, and ordered-list-numbering subsets.'));
|
|
2254
|
+
].some((name)=>descendants(document, name).length)) issues.push(work_office_diagnostics_issue('docx.revisions.structural', 'Structural revisions', 'Moved content plus unsupported character formatting, paragraph formatting, numbering, section, row, cell, and table-property revisions may be normalized; Work currently reviews body-text insertions/deletions and bounded text moves, character-, paragraph-, and ordered-list-numbering subsets.'));
|
|
2244
2255
|
if (captionDiagnostics.hasUnsupportedFields) issues.push(work_office_diagnostics_issue('docx.fields', 'Fields', 'Fields beyond supported body fields, citations, bibliographies, caption SEQ fields, and bookmark or caption REF fields are converted to their current displayed value.'));
|
|
2245
2256
|
const sectionProperties = descendants(document, 'sectPr');
|
|
2246
2257
|
const columnProperties = descendants(document, 'cols');
|