@a3s-lab/office 0.48.0 → 0.49.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 +26 -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 +65 -10
- 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-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 +42 -0
- package/docs/latest/en/browser-editor-architecture.md +14 -2
- package/package.json +11 -3
package/COLLABORATION_ROADMAP.md
CHANGED
|
@@ -110,8 +110,8 @@ Redis/NATS fan-out plus a distributed writer/lock policy.
|
|
|
110
110
|
|
|
111
111
|
Status: browser collaboration foundation, participant roster, remote
|
|
112
112
|
selection/caret projection, participant navigation, durable review-only
|
|
113
|
-
comment and suggestion modes, character
|
|
114
|
-
immutable decision audit, and native text/options/bounded structural
|
|
113
|
+
comment and suggestion modes, character-, paragraph-formatting, numbering, and
|
|
114
|
+
text-only move revisions, immutable decision audit, and native text/options/bounded structural
|
|
115
115
|
paragraph/comment/suggestion mutations implemented; rich native mutation
|
|
116
116
|
parity remains pending.
|
|
117
117
|
|
|
@@ -182,6 +182,14 @@ parity remains pending.
|
|
|
182
182
|
level, tab stops, borders, shading, and collapsed state without changing
|
|
183
183
|
text. Supported strict or transitional DOCX `w:pPrChange` records use the
|
|
184
184
|
same model and export natively.
|
|
185
|
+
- Text-only move revisions create one paired `move` identity with `from` and
|
|
186
|
+
`to` roles. Matching strict/transitional `w:moveFrom`/`w:moveTo` records are
|
|
187
|
+
imported and exported natively; accept removes the source, reject removes the
|
|
188
|
+
destination, and one immutable decision audit record covers both sides. The
|
|
189
|
+
browser review binding and Yrs projection validate exact text, identity,
|
|
190
|
+
author, and date, while rich/range/relationship-bound or unpaired moves fail
|
|
191
|
+
closed as structural diagnostics. The closed native suggestion mutations
|
|
192
|
+
remain insertion/deletion-only.
|
|
185
193
|
- Rust, CLI, MCP, and A3S Code expose `document-comment-create`,
|
|
186
194
|
`document-comment-reply`, `document-comment-set-resolved`,
|
|
187
195
|
`document-comment-delete`, `document-suggestion-create`, and
|
|
@@ -199,10 +207,10 @@ parity remains pending.
|
|
|
199
207
|
content, structure, options, non-suggestion formatting, authorship, order,
|
|
200
208
|
claims, anchors, foreign deletion, or foreign suggestion changes fail before
|
|
201
209
|
the durable store changes.
|
|
202
|
-
- Native Yrs validation admits only the bounded character-
|
|
203
|
-
|
|
204
|
-
duplicate/reordered delivery, exposes `formatting`
|
|
205
|
-
`
|
|
210
|
+
- Native Yrs validation admits only the bounded character-, paragraph-formatting,
|
|
211
|
+
numbering, and move schemas, preserves them across restart and
|
|
212
|
+
duplicate/reordered delivery, exposes `formatting`, `paragraph-formatting`,
|
|
213
|
+
`numbering`, and `move` in immutable decision projections, and makes
|
|
206
214
|
`suggest` updates retain existing formatting revisions byte-semantically.
|
|
207
215
|
Formatting revisions are Document change kinds, not native
|
|
208
216
|
insertion/deletion suggestion kinds; the current closed
|
package/README.md
CHANGED
|
@@ -309,6 +309,32 @@ and [CLI reference](./docs/latest/en/cli-reference.md).
|
|
|
309
309
|
|
|
310
310
|
## Current release
|
|
311
311
|
|
|
312
|
+
Version `0.49.0` adds bounded native Writer move revisions and hardens the
|
|
313
|
+
local PDF workflow:
|
|
314
|
+
|
|
315
|
+
- Strict and transitional DOCX `w:moveFrom`/`w:moveTo` text pairs import as one
|
|
316
|
+
atomic `move` review item. Accept/reject resolves both source and destination
|
|
317
|
+
sides together, the immutable collaboration audit records the single final
|
|
318
|
+
decision, and export/reopen restores native move records with no private
|
|
319
|
+
marker leakage.
|
|
320
|
+
- Rich, range-marker, relationship-bound, malformed, and unpaired moves remain
|
|
321
|
+
visible as diagnosed compatibility boundaries. The review pane labels moves
|
|
322
|
+
distinctly and navigates to the destination range without selecting the text
|
|
323
|
+
between the two sides.
|
|
324
|
+
- The Playground now serves the pinned PDFium WebAssembly asset from a stable
|
|
325
|
+
origin-relative path, keeping direct PDF imports ready in desktop and compact
|
|
326
|
+
layouts.
|
|
327
|
+
|
|
328
|
+
Version `0.48.1` fixes the Writer floating selection toolbar's split emphasis
|
|
329
|
+
controls without changing the document model or public command contract:
|
|
330
|
+
|
|
331
|
+
- Underline and strikethrough controls now reset browser-native button
|
|
332
|
+
appearance and use the same compact themed states as the surrounding
|
|
333
|
+
actions, including one-pixel grouping dividers and keyboard focus treatment.
|
|
334
|
+
- The fix is covered by a browser visual contract in both desktop and compact
|
|
335
|
+
viewports; formatting commands, accessibility names, and split menus remain
|
|
336
|
+
unchanged.
|
|
337
|
+
|
|
312
338
|
Version `0.48.0` adds bounded native Writer content controls without
|
|
313
339
|
introducing a second document model or a remote service:
|
|
314
340
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { documentRunBorderDomAttributes, normalizeDocumentRunBorder, normalizeDocumentParagraphBorder, serializeDocumentRunBorder, serializeDocumentRunShading, documentIndexEntryHtml, attribute as work_ooxml_package_attribute, documentScriptFontFallbackSlots, documentScriptFontsDomAttributes, documentHighlightFromDocxValue, serializeDocxThemeReference, directChildren as work_ooxml_package_directChildren, documentParagraphShadingDomAttributes, documentTableOfContentsHtml, documentParagraphBordersDomAttributes, normalizeDocumentScriptFontHint, normalizeDocumentScriptFonts, DOCUMENT_PARAGRAPH_BORDER_STYLES, normalizeDocumentParagraphBorders as work_document_paragraph_borders_normalizeDocumentParagraphBorders, DOCUMENT_PARAGRAPH_BORDER_EDGES, documentScriptFontFamily, normalizeDocumentThemeFont, normalizeDocumentParagraphId, documentHighlightDomAttributes, descendants, documentIndexHtml, documentHighlightCssColor, xmlNamespacePrefix, normalizeDocumentFontName, documentProofingDomAttributes, work_document_paragraph_shading_DOCUMENT_PARAGRAPH_SHADING_PATTERNS, directChild, documentScriptFontSegments, childPath, parseDocumentTableOfContentsInstruction, documentRunShadingDomAttributes } from "./6968.js";
|
|
2
|
+
import { hasUnsupportedContentControlSemanticChild, docxThemeFont, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, hasContentControlRelationshipReference, parseDocumentIndexEntryInstruction, resolveDocxProofing, parseDocumentIndexInstruction, CONTENT_CONTROL_WORD_2012_NAMESPACE, DOCX_WORD_2010_NAMESPACE, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, STRICT_WORDPROCESSING_NAMESPACE, docxCharacterSpacingTwipsFromProperties, parseBoundedDocxInteger, xmlAttributeLocalName, isDocxWordElement, resolveDocxOpenTypeFeatures, resolveDocxEmphasisMark, docxCharacterScalePercentFromProperties, docxCharacterPositionHalfPointsFromProperties, docxThemeColor, parseDocxParagraphDefaultCollapsed, resolveDocxKerningThresholdHalfPoints, resolveDocxThemeResolver as work_docx_theme_resolveDocxThemeResolver, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace, parseDocxTwipsMeasure } from "./0~3534.js";
|
|
2
3
|
import { normalizeDocumentEmphasisMark, normalizeDocumentPageBorders, textBoxCss, documentCharacterPositionDomAttributes, DOCUMENT_PAGE_BORDER_EDGES, normalizeDocumentTabStops, documentTextCaseFromWordFlags, documentStrikeDomAttributes, serializeDocumentNumberingChange, numberingTypeFromFormat, normalizeDocumentUnderlineColor, documentAutoLineHeight, documentKerningDomAttributes, documentCharacterScaleDomAttributes, textBoxDomAttributes, serializeDocumentParagraphFormatting, normalizeDocumentContentControlProperties, documentEquationText, normalizeDocumentPaperSource, documentLegacyTextEffectsDomAttributes, documentLegacyTextEffectsConflict, documentCharacterSpacingDomAttributes, normalizeDocumentParagraphIndent, normalizeDocumentEquation, documentOpenTypeDomAttributes, normalizeDocumentTextBoxProperties, renderDocumentAutoLineHeight, contentControlDomAttributes, documentUnderlineDomAttributes, MAX_DOCUMENT_NUMBERING_START, normalizeDocumentUnderlineStyle, applyDocumentTextCaseStyle, documentHiddenTextDomAttributes, importedDocumentCharacterFormatting, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, normalizeDocumentPageGeometry, createDocumentEquationElement, serializeDocumentTabStops, documentEmphasisMarkDomAttributes, normalizeDocumentPageMargins, documentWordLineHeightFactor } from "./4174.js";
|
|
3
|
-
import { hasUnsupportedContentControlSemanticChild, docxThemeFont, hasContentControlRelationshipReference, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, parseDocumentIndexEntryInstruction, resolveDocxProofing, parseDocumentIndexInstruction, CONTENT_CONTROL_WORD_2012_NAMESPACE, DOCX_WORD_2010_NAMESPACE, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, STRICT_WORDPROCESSING_NAMESPACE, docxCharacterSpacingTwipsFromProperties, parseBoundedDocxInteger, isDocxWordElement, xmlAttributeLocalName, resolveDocxOpenTypeFeatures, resolveDocxEmphasisMark, docxCharacterScalePercentFromProperties, docxCharacterPositionHalfPointsFromProperties, docxThemeColor, parseDocxParagraphDefaultCollapsed, resolveDocxKerningThresholdHalfPoints, resolveDocxThemeResolver as work_docx_theme_resolveDocxThemeResolver, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace, parseDocxTwipsMeasure } from "./0~3534.js";
|
|
4
4
|
function docxCaptionSequenceKind(instruction) {
|
|
5
5
|
const identifier = /^\s*SEQ\s+([^\s\\]+)/i.exec(instruction)?.[1]?.toLowerCase();
|
|
6
6
|
if (!identifier) return null;
|
|
@@ -159,9 +159,267 @@ function containsRange(outer, inner) {
|
|
|
159
159
|
return outer.start >= 0 && inner.start >= 0 && outer.start < inner.start && outer.end >= inner.end;
|
|
160
160
|
}
|
|
161
161
|
const WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
162
|
+
const XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
|
|
163
|
+
const MOVE_FROM = 'moveFrom';
|
|
164
|
+
const MOVE_TO = 'moveTo';
|
|
165
|
+
const MAX_MOVE_REVISIONS = 65536;
|
|
166
|
+
const MAX_MOVE_TEXT_LENGTH = 1000000;
|
|
167
|
+
const MAX_MOVE_DATE_LENGTH = 64;
|
|
168
|
+
function markDocxTextChanges(document) {
|
|
169
|
+
const changes = [];
|
|
170
|
+
const movePairs = supportedMovePairs(document);
|
|
171
|
+
const moveByElement = new Map();
|
|
172
|
+
for (const pair of movePairs){
|
|
173
|
+
moveByElement.set(pair.from.element, pair);
|
|
174
|
+
moveByElement.set(pair.to.element, pair);
|
|
175
|
+
}
|
|
176
|
+
const processedMoves = new Set();
|
|
177
|
+
let markerIndex = 0;
|
|
178
|
+
const revisions = [
|
|
179
|
+
...descendants(document, 'ins'),
|
|
180
|
+
...descendants(document, 'del'),
|
|
181
|
+
...movePairs.flatMap((pair)=>[
|
|
182
|
+
pair.from.element,
|
|
183
|
+
pair.to.element
|
|
184
|
+
])
|
|
185
|
+
].sort(compareDocumentOrder);
|
|
186
|
+
for (const revision of revisions){
|
|
187
|
+
if (!revision.parentNode || closestRevision(revision.parentElement)) continue;
|
|
188
|
+
const move = moveByElement.get(revision);
|
|
189
|
+
if (move) {
|
|
190
|
+
if (processedMoves.has(move)) continue;
|
|
191
|
+
processedMoves.add(move);
|
|
192
|
+
const id = uniqueChangeId(`docx-move-${move.from.id}`, changes);
|
|
193
|
+
const ordered = [
|
|
194
|
+
move.from,
|
|
195
|
+
move.to
|
|
196
|
+
].sort((left, right)=>compareDocumentOrder(left.element, right.element));
|
|
197
|
+
for (const side of ordered){
|
|
198
|
+
markerIndex += 1;
|
|
199
|
+
if ('from' === side.role) convertDeletedText(document, side.element);
|
|
200
|
+
const marker = {
|
|
201
|
+
id,
|
|
202
|
+
kind: 'move',
|
|
203
|
+
moveRole: side.role,
|
|
204
|
+
author: side.author,
|
|
205
|
+
date: side.date,
|
|
206
|
+
start: `__A3S_WORK_CHANGE_START_${markerIndex}__`,
|
|
207
|
+
end: `__A3S_WORK_CHANGE_END_${markerIndex}__`
|
|
208
|
+
};
|
|
209
|
+
unwrapRevision(document, side.element, marker.start, marker.end);
|
|
210
|
+
changes.push(marker);
|
|
211
|
+
}
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const kind = 'del' === revision.localName ? 'deletion' : 'insertion';
|
|
215
|
+
if (!revisionText(revision, kind)) continue;
|
|
216
|
+
if ('deletion' === kind) convertDeletedText(document, revision);
|
|
217
|
+
markerIndex += 1;
|
|
218
|
+
const sourceId = work_ooxml_package_attribute(revision, 'id')?.trim() ?? '';
|
|
219
|
+
const id = uniqueChangeId(sourceId ? `docx-change-${sourceId}` : `docx-change-${markerIndex}`, changes);
|
|
220
|
+
const marker = {
|
|
221
|
+
id,
|
|
222
|
+
kind,
|
|
223
|
+
author: work_ooxml_package_attribute(revision, 'author')?.trim() || '未知审阅者',
|
|
224
|
+
date: normalizeDate(work_ooxml_package_attribute(revision, 'date')),
|
|
225
|
+
start: `__A3S_WORK_CHANGE_START_${markerIndex}__`,
|
|
226
|
+
end: `__A3S_WORK_CHANGE_END_${markerIndex}__`
|
|
227
|
+
};
|
|
228
|
+
unwrapRevision(document, revision, marker.start, marker.end);
|
|
229
|
+
changes.push(marker);
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
changes
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function applyImportedDocxChangeMarkers(document, markers) {
|
|
236
|
+
for (const marker of markers.changes){
|
|
237
|
+
const isMoveFrom = 'move' === marker.kind && 'from' === marker.moveRole;
|
|
238
|
+
const element = document.createElement('deletion' === marker.kind || isMoveFrom ? 'del' : 'ins');
|
|
239
|
+
element.dataset.documentChange = 'true';
|
|
240
|
+
element.dataset.changeKind = marker.kind;
|
|
241
|
+
if ('move' === marker.kind && marker.moveRole) element.dataset.changeMoveRole = marker.moveRole;
|
|
242
|
+
element.dataset.changeId = marker.id;
|
|
243
|
+
element.dataset.changeAuthor = marker.author;
|
|
244
|
+
element.dataset.changeDate = marker.date;
|
|
245
|
+
wrapMarkerRange(document.body, marker.start, marker.end, element);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function hasImportedDocxChangeMarkers(markers) {
|
|
249
|
+
return markers.changes.length > 0;
|
|
250
|
+
}
|
|
251
|
+
function revisionText(revision, kind) {
|
|
252
|
+
const names = 'deletion' === kind ? [
|
|
253
|
+
'delText',
|
|
254
|
+
't'
|
|
255
|
+
] : [
|
|
256
|
+
't'
|
|
257
|
+
];
|
|
258
|
+
return names.flatMap((name)=>descendants(revision, name)).map((element)=>element.textContent ?? '').join('');
|
|
259
|
+
}
|
|
260
|
+
function isSupportedDocxMoveChange(element) {
|
|
261
|
+
return null !== supportedMoveRevision(element);
|
|
262
|
+
}
|
|
263
|
+
function supportedDocxMovePairCount(document) {
|
|
264
|
+
return supportedMovePairs(document).length;
|
|
265
|
+
}
|
|
266
|
+
function supportedMovePairs(document) {
|
|
267
|
+
const from = descendants(document, MOVE_FROM).map((element)=>supportedMoveRevision(element, 'from')).filter((value)=>null !== value);
|
|
268
|
+
const to = descendants(document, MOVE_TO).map((element)=>supportedMoveRevision(element, 'to')).filter((value)=>null !== value);
|
|
269
|
+
const fromById = uniqueMoveById(from);
|
|
270
|
+
const toById = uniqueMoveById(to);
|
|
271
|
+
const pairs = [];
|
|
272
|
+
for (const [id, source] of fromById){
|
|
273
|
+
const destination = toById.get(id);
|
|
274
|
+
if (!(!destination || source.author !== destination.author || source.date !== destination.date || source.text !== destination.text || closestRevision(source.element.parentElement) || closestRevision(destination.element.parentElement))) pairs.push({
|
|
275
|
+
from: source,
|
|
276
|
+
to: destination
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
return pairs.slice(0, MAX_MOVE_REVISIONS);
|
|
280
|
+
}
|
|
281
|
+
function uniqueMoveById(revisions) {
|
|
282
|
+
const result = new Map();
|
|
283
|
+
const duplicates = new Set();
|
|
284
|
+
for (const revision of revisions)if (!duplicates.has(revision.id)) {
|
|
285
|
+
if (result.has(revision.id)) {
|
|
286
|
+
result.delete(revision.id);
|
|
287
|
+
duplicates.add(revision.id);
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
result.set(revision.id, revision);
|
|
291
|
+
}
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
294
|
+
function supportedMoveRevision(element, role) {
|
|
295
|
+
const resolvedRole = role ?? (element.localName === MOVE_FROM ? 'from' : element.localName === MOVE_TO ? 'to' : null);
|
|
296
|
+
if (!resolvedRole || !DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? '') || element.localName !== MOVE_FROM && element.localName !== MOVE_TO || null !== element.parentElement && element.namespaceURI !== element.parentElement.namespaceURI) return null;
|
|
297
|
+
const id = wordAttribute(element, 'id')?.trim() ?? '';
|
|
298
|
+
const author = wordAttribute(element, 'author')?.trim() ?? '';
|
|
299
|
+
const rawDate = wordAttribute(element, 'date');
|
|
300
|
+
const text = moveRevisionText(element, resolvedRole);
|
|
301
|
+
if (!/^\d{1,10}$/.test(id) || !author || author.length > 255 || /[\u0000-\u001f\u007f]/.test(author) || null !== rawDate && rawDate.length > MAX_MOVE_DATE_LENGTH || null !== rawDate && !Number.isFinite(Date.parse(rawDate)) || !text || text.length > MAX_MOVE_TEXT_LENGTH || hasUnsupportedWordAttribute(element) || !moveChildrenAreTextOnly(element, resolvedRole)) return null;
|
|
302
|
+
return {
|
|
303
|
+
element,
|
|
304
|
+
role: resolvedRole,
|
|
305
|
+
id,
|
|
306
|
+
author,
|
|
307
|
+
date: normalizeDate(rawDate),
|
|
308
|
+
text
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function moveRevisionText(revision, role) {
|
|
312
|
+
const names = 'from' === role ? [
|
|
313
|
+
'delText'
|
|
314
|
+
] : [
|
|
315
|
+
't'
|
|
316
|
+
];
|
|
317
|
+
return names.flatMap((name)=>descendants(revision, name)).map((element)=>element.textContent ?? '').join('');
|
|
318
|
+
}
|
|
319
|
+
function moveChildrenAreTextOnly(revision, role) {
|
|
320
|
+
const allowedText = 'from' === role ? new Set([
|
|
321
|
+
'delText'
|
|
322
|
+
]) : new Set([
|
|
323
|
+
't'
|
|
324
|
+
]);
|
|
325
|
+
const runs = Array.from(revision.children);
|
|
326
|
+
if (!runs.length || runs.some((run)=>'r' !== run.localName || !DOCX_WORDPROCESSING_NAMESPACES.has(run.namespaceURI ?? ''))) return false;
|
|
327
|
+
for (const run of runs){
|
|
328
|
+
const properties = Array.from(run.children).filter((child)=>'rPr' === child.localName);
|
|
329
|
+
if (properties.length > 1) return false;
|
|
330
|
+
for (const child of Array.from(run.children)){
|
|
331
|
+
if (!DOCX_WORDPROCESSING_NAMESPACES.has(child.namespaceURI ?? '')) return false;
|
|
332
|
+
if ('rPr' === child.localName) {
|
|
333
|
+
if (Array.from(child.querySelectorAll('*')).some((descendant)=>!DOCX_WORDPROCESSING_NAMESPACES.has(descendant.namespaceURI ?? ''))) return false;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if (!allowedText.has(child.localName)) return false;
|
|
337
|
+
if (child.querySelector('*')) return false;
|
|
338
|
+
}
|
|
339
|
+
if (!Array.from(run.children).some((child)=>allowedText.has(child.localName))) return false;
|
|
340
|
+
}
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
343
|
+
function wordAttribute(element, localName) {
|
|
344
|
+
const namespace = element.namespaceURI;
|
|
345
|
+
if (!namespace) return null;
|
|
346
|
+
const matches = Array.from(element.attributes).filter((candidate)=>xmlAttributeLocalName(candidate) === localName && xmlAttributeNamespace(element, candidate) === namespace);
|
|
347
|
+
return 1 === matches.length ? matches[0]?.value ?? null : null;
|
|
348
|
+
}
|
|
349
|
+
function hasUnsupportedWordAttribute(element) {
|
|
350
|
+
const namespace = element.namespaceURI;
|
|
351
|
+
const supported = new Set([
|
|
352
|
+
'id',
|
|
353
|
+
'author',
|
|
354
|
+
'date'
|
|
355
|
+
]);
|
|
356
|
+
return Array.from(element.attributes).some((candidate)=>xmlAttributeNamespace(element, candidate) === namespace && !supported.has(xmlAttributeLocalName(candidate)));
|
|
357
|
+
}
|
|
358
|
+
function convertDeletedText(document, revision) {
|
|
359
|
+
for (const deleted of descendants(revision, 'delText')){
|
|
360
|
+
const text = document.createElementNS(WORD_NAMESPACE, 'w:t');
|
|
361
|
+
const preserve = deleted.getAttributeNS(XML_NAMESPACE, 'space') ?? deleted.getAttribute('xml:space');
|
|
362
|
+
if (preserve) text.setAttributeNS(XML_NAMESPACE, 'xml:space', preserve);
|
|
363
|
+
text.textContent = deleted.textContent;
|
|
364
|
+
deleted.replaceWith(text);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function unwrapRevision(document, revision, start, end) {
|
|
368
|
+
const parent = revision.parentNode;
|
|
369
|
+
if (!parent) return;
|
|
370
|
+
parent.insertBefore(work_docx_change_import_markerRun(document, start), revision);
|
|
371
|
+
while(revision.firstChild)parent.insertBefore(revision.firstChild, revision);
|
|
372
|
+
parent.insertBefore(work_docx_change_import_markerRun(document, end), revision);
|
|
373
|
+
revision.remove();
|
|
374
|
+
}
|
|
375
|
+
function work_docx_change_import_markerRun(document, value) {
|
|
376
|
+
const run = document.createElementNS(WORD_NAMESPACE, 'w:r');
|
|
377
|
+
const text = document.createElementNS(WORD_NAMESPACE, 'w:t');
|
|
378
|
+
text.setAttributeNS(XML_NAMESPACE, 'xml:space', 'preserve');
|
|
379
|
+
text.textContent = value;
|
|
380
|
+
run.append(text);
|
|
381
|
+
return run;
|
|
382
|
+
}
|
|
383
|
+
function wrapMarkerRange(root, start, end, wrapper) {
|
|
384
|
+
const html = root.innerHTML;
|
|
385
|
+
const startIndex = html.indexOf(start);
|
|
386
|
+
const endIndex = html.indexOf(end, startIndex + start.length);
|
|
387
|
+
if (startIndex < 0 || endIndex < 0) return false;
|
|
388
|
+
const closingTag = `</${wrapper.localName}>`;
|
|
389
|
+
const serializedWrapper = wrapper.outerHTML;
|
|
390
|
+
if (!serializedWrapper.endsWith(closingTag)) return false;
|
|
391
|
+
const openingTag = serializedWrapper.slice(0, -closingTag.length);
|
|
392
|
+
root.innerHTML = `${html.slice(0, startIndex)}${openingTag}${html.slice(startIndex + start.length, endIndex)}${closingTag}${html.slice(endIndex + end.length)}`;
|
|
393
|
+
return true;
|
|
394
|
+
}
|
|
395
|
+
function closestRevision(element) {
|
|
396
|
+
let current = element;
|
|
397
|
+
while(current){
|
|
398
|
+
if ('ins' === current.localName || 'del' === current.localName || current.localName === MOVE_FROM || current.localName === MOVE_TO) return current;
|
|
399
|
+
current = current.parentElement;
|
|
400
|
+
}
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
function uniqueChangeId(base, changes) {
|
|
404
|
+
const ids = new Set(changes.map((change)=>change.id));
|
|
405
|
+
if (!ids.has(base)) return base;
|
|
406
|
+
let suffix = 2;
|
|
407
|
+
while(ids.has(`${base}-${suffix}`))suffix += 1;
|
|
408
|
+
return `${base}-${suffix}`;
|
|
409
|
+
}
|
|
410
|
+
function normalizeDate(value) {
|
|
411
|
+
if (!value) return '';
|
|
412
|
+
const time = Date.parse(value);
|
|
413
|
+
return Number.isFinite(time) ? new Date(time).toISOString() : '';
|
|
414
|
+
}
|
|
415
|
+
function compareDocumentOrder(left, right) {
|
|
416
|
+
if (left === right) return 0;
|
|
417
|
+
return left.compareDocumentPosition(right) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
418
|
+
}
|
|
419
|
+
const work_docx_content_control_import_WORD_NAMESPACE = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';
|
|
162
420
|
const STRICT_WORD_NAMESPACE = 'http://purl.oclc.org/ooxml/wordprocessingml/main';
|
|
163
421
|
const WORD_NAMESPACES = new Set([
|
|
164
|
-
|
|
422
|
+
work_docx_content_control_import_WORD_NAMESPACE,
|
|
165
423
|
STRICT_WORD_NAMESPACE
|
|
166
424
|
]);
|
|
167
425
|
const MARKUP_COMPATIBILITY_NAMESPACE = 'http://schemas.openxmlformats.org/markup-compatibility/2006';
|
|
@@ -342,7 +600,7 @@ function readProperties(properties) {
|
|
|
342
600
|
if (id && !validLeaf(id, new Set([
|
|
343
601
|
'val'
|
|
344
602
|
]))) return null;
|
|
345
|
-
const nativeId = id ? parseNativeId(
|
|
603
|
+
const nativeId = id ? parseNativeId(work_docx_content_control_import_wordAttribute(id, 'val')) : null;
|
|
346
604
|
if (id && null === nativeId) return null;
|
|
347
605
|
const alias = readStringProperty(groups.get('alias')?.[0]);
|
|
348
606
|
const tag = readStringProperty(groups.get('tag')?.[0]);
|
|
@@ -351,7 +609,7 @@ function readProperties(properties) {
|
|
|
351
609
|
if (lockElement && !validLeaf(lockElement, new Set([
|
|
352
610
|
'val'
|
|
353
611
|
]))) return null;
|
|
354
|
-
const lockValue = lockElement ?
|
|
612
|
+
const lockValue = lockElement ? work_docx_content_control_import_wordAttribute(lockElement, 'val') : null;
|
|
355
613
|
const lock = lockValue ?? 'unlocked';
|
|
356
614
|
if (!LOCK_VALUES.has(lock)) return null;
|
|
357
615
|
const textElement = groups.get('text')?.[0];
|
|
@@ -361,7 +619,7 @@ function readProperties(properties) {
|
|
|
361
619
|
'multiLine'
|
|
362
620
|
]))) return null;
|
|
363
621
|
if (richTextElement && !validLeaf(richTextElement, new Set())) return null;
|
|
364
|
-
const multilineValue = textElement ?
|
|
622
|
+
const multilineValue = textElement ? work_docx_content_control_import_wordAttribute(textElement, 'multiLine') : null;
|
|
365
623
|
if (null !== multilineValue && ![
|
|
366
624
|
'0',
|
|
367
625
|
'1',
|
|
@@ -417,7 +675,7 @@ function replaceControlWithMarkers(document, control, start, end) {
|
|
|
417
675
|
return true;
|
|
418
676
|
}
|
|
419
677
|
function work_docx_content_control_import_markerRun(document, context, value) {
|
|
420
|
-
const namespace = context.namespaceURI ??
|
|
678
|
+
const namespace = context.namespaceURI ?? work_docx_content_control_import_WORD_NAMESPACE;
|
|
421
679
|
const prefix = xmlNamespacePrefix(context, namespace) ?? 'w';
|
|
422
680
|
const run = document.createElementNS(namespace, `${prefix}:r`);
|
|
423
681
|
const text = document.createElementNS(namespace, `${prefix}:t`);
|
|
@@ -535,7 +793,7 @@ function isStructuralContentControl(control) {
|
|
|
535
793
|
'docPartList'
|
|
536
794
|
].includes(child.localName));
|
|
537
795
|
}
|
|
538
|
-
function
|
|
796
|
+
function work_docx_content_control_import_wordAttribute(element, localName) {
|
|
539
797
|
const matches = Array.from(element.attributes).filter((item)=>xmlAttributeLocalName(item) === localName && xmlAttributeNamespace(element, item) === element.namespaceURI && WORD_NAMESPACES.has(element.namespaceURI ?? ''));
|
|
540
798
|
return 1 === matches.length ? matches[0].value : null;
|
|
541
799
|
}
|
|
@@ -548,7 +806,7 @@ function readStringProperty(element) {
|
|
|
548
806
|
if (!validLeaf(element, new Set([
|
|
549
807
|
'val'
|
|
550
808
|
]))) return null;
|
|
551
|
-
const value =
|
|
809
|
+
const value = work_docx_content_control_import_wordAttribute(element, 'val');
|
|
552
810
|
if (null === value || /[\u0000-\u001f\u007f]/u.test(value)) return null;
|
|
553
811
|
return value.slice(0, 255);
|
|
554
812
|
}
|
|
@@ -1495,7 +1753,7 @@ const WORD_COMBINE_BRACKETS = new Set([
|
|
|
1495
1753
|
'angle',
|
|
1496
1754
|
'curly'
|
|
1497
1755
|
]);
|
|
1498
|
-
const
|
|
1756
|
+
const work_docx_equation_import_XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
|
|
1499
1757
|
const MAX_IMPORTED_EQUATIONS = 4096;
|
|
1500
1758
|
const MAX_MATH_DEPTH = 32;
|
|
1501
1759
|
const MAX_MATH_NODES = 4096;
|
|
@@ -4374,7 +4632,7 @@ function hasMeaningfulDirectText(element) {
|
|
|
4374
4632
|
return Array.from(element.childNodes).some((node)=>(node.nodeType === Node.TEXT_NODE || node.nodeType === Node.CDATA_SECTION_NODE) && Boolean(node.textContent?.trim()));
|
|
4375
4633
|
}
|
|
4376
4634
|
function safeMathTextAttributes(element) {
|
|
4377
|
-
return meaningfulAttributes(element).every((attribute)=>xmlAttributeNamespace(element, attribute) ===
|
|
4635
|
+
return meaningfulAttributes(element).every((attribute)=>xmlAttributeNamespace(element, attribute) === work_docx_equation_import_XML_NAMESPACE && 'space' === xmlAttributeLocalName(attribute) && ('default' === attribute.value || 'preserve' === attribute.value));
|
|
4378
4636
|
}
|
|
4379
4637
|
function mathValue(element) {
|
|
4380
4638
|
if (!DOCX_MATH_NAMESPACES.has(element.namespaceURI ?? '') || work_ooxml_package_directChildren(element).length || hasMeaningfulDirectText(element)) return null;
|
|
@@ -4810,7 +5068,7 @@ function supportedNumberingChange(change) {
|
|
|
4810
5068
|
const paragraph = properties?.parentElement;
|
|
4811
5069
|
if (numbering?.localName !== 'numPr' || numbering.namespaceURI !== namespace || properties?.localName !== 'pPr' || properties.namespaceURI !== namespace || paragraph?.localName !== 'p' || paragraph.namespaceURI !== namespace) return null;
|
|
4812
5070
|
const numberingChildren = work_ooxml_package_directChildren(numbering);
|
|
4813
|
-
if (3 !== numberingChildren.length || numberingChildren.some((child)=>child.namespaceURI !== namespace) || 1 !== work_ooxml_package_directChildren(numbering, 'numberingChange').length || 0 !== change.children.length ||
|
|
5071
|
+
if (3 !== numberingChildren.length || numberingChildren.some((child)=>child.namespaceURI !== namespace) || 1 !== work_ooxml_package_directChildren(numbering, 'numberingChange').length || 0 !== change.children.length || work_docx_numbering_change_import_hasUnsupportedWordAttribute(change)) return null;
|
|
4814
5072
|
const levels = directWordChildren(numbering, 'ilvl');
|
|
4815
5073
|
const numberingIds = directWordChildren(numbering, 'numId');
|
|
4816
5074
|
if (1 !== levels.length || 1 !== numberingIds.length) return null;
|
|
@@ -4940,7 +5198,7 @@ function work_docx_numbering_change_import_wordAttribute(element, localName) {
|
|
|
4940
5198
|
const attributes = Array.from(element.attributes).filter((attribute)=>xmlAttributeLocalName(attribute) === localName && xmlAttributeNamespace(element, attribute) === namespace);
|
|
4941
5199
|
return 1 === attributes.length ? attributes[0]?.value ?? null : null;
|
|
4942
5200
|
}
|
|
4943
|
-
function
|
|
5201
|
+
function work_docx_numbering_change_import_hasUnsupportedWordAttribute(element) {
|
|
4944
5202
|
const namespace = element.namespaceURI;
|
|
4945
5203
|
const supported = new Set([
|
|
4946
5204
|
'id',
|
|
@@ -8933,4 +9191,4 @@ function work_docx_text_box_import_textNodes(root) {
|
|
|
8933
9191
|
while(walker.nextNode())nodes.push(walker.currentNode);
|
|
8934
9192
|
return nodes;
|
|
8935
9193
|
}
|
|
8936
|
-
export { applyImportedDocxContentControlMarkers, applyImportedDocxEquationMarkers, applyImportedDocxIndexMarkers, applyImportedDocxNumberingChangeMarkers, applyImportedDocxParagraphAlignmentMarkers, applyImportedDocxParagraphBorderMarkers, applyImportedDocxParagraphDirectionMarkers, applyImportedDocxParagraphFormattingChangeMarkers, applyImportedDocxParagraphIndentMarkers, applyImportedDocxParagraphPaginationMarkers, applyImportedDocxParagraphShadingMarkers, applyImportedDocxParagraphSpacingMarkers, applyImportedDocxParagraphTabStopMarkers, applyImportedDocxRunFormattingMarkers, applyImportedDocxTableOfContentsMarkers, applyImportedDocxTextBoxMarkers, createDocxParagraphStyleResolver, createDocxTableStyleResolver, createImportedDocxRunFormattingMarkerState, docxCaptionBookmark, docxCaptionReferenceTarget, docxCaptionSequenceKind, docxEquationHtml, docxFieldInstructions, docxFieldOccurrenceIsInlineEditable, docxFieldOccurrences, docxFieldResultText, docxRunPropertySources, docxTableCellStyleLayers, docxTablePropertySources, docxTableRunPropertySources, hasImportedDocxContentControlMarkers, hasImportedDocxIndexMarkers, hasImportedDocxNumberingChangeMarkers, hasImportedDocxParagraphAlignmentMarkers, hasImportedDocxParagraphBorderMarkers, hasImportedDocxParagraphDirectionMarkers, hasImportedDocxParagraphFormattingChangeMarkers, hasImportedDocxParagraphIndentMarkers, hasImportedDocxParagraphPaginationMarkers, hasImportedDocxParagraphShadingMarkers, hasImportedDocxParagraphSpacingMarkers, hasImportedDocxParagraphTabStopMarkers, hasImportedDocxRunFormattingMarkers, hasImportedDocxTableOfContentsMarkers, hasImportedDocxTextBoxMarkers, hasInvalidDocxFieldStructure, importedDocxStrike, importedDocxUnderline, inspectDocxContentControls, inspectDocxEquation, inspectDocxHiddenText, inspectDocxLegacyTextEffects, inspectDocxPageBorders, inspectDocxPageMarginSettings, inspectDocxPageMargins, inspectDocxPageSize, inspectDocxPaperSource, inspectDocxRunBorder, inspectDocxRunFonts, inspectDocxRunShading, inspectDocxTextBoxes, isDocxEquationLikeRoot, isSupportedDocxEquationPlacement, isSupportedDocxNumberingChange, isSupportedDocxParagraphFormattingChange, isSupportedDocxRunFormattingChange, markDocxContentControls, markDocxIndexes, markDocxNumberingChanges, markDocxPackageEquations, markDocxParagraphAlignments, markDocxParagraphBorders, markDocxParagraphDirections, markDocxParagraphFormattingChanges, markDocxParagraphIndents, markDocxParagraphPagination, markDocxParagraphShading, markDocxParagraphSpacing, markDocxParagraphTabStops, markDocxRunFormattingIntoState, markDocxTablesOfContents, markDocxTextBoxes, parseDirectDocxParagraphShading, parseDocxPageBorders, parseDocxPageGeometry, parseDocxPageMargins, parseDocxPaperSource, resolveDocxHiddenText, resolveDocxLegacyTextEffects, resolveDocxParagraphBordersForParagraph, resolveDocxRunBorder, resolveDocxRunShading, resolveDocxTableStyleResolver, supportedDocxIndexEntryField, supportedDocxIndexField, supportedDocxTableOfContentsField };
|
|
9194
|
+
export { applyImportedDocxChangeMarkers, applyImportedDocxContentControlMarkers, applyImportedDocxEquationMarkers, applyImportedDocxIndexMarkers, applyImportedDocxNumberingChangeMarkers, applyImportedDocxParagraphAlignmentMarkers, applyImportedDocxParagraphBorderMarkers, applyImportedDocxParagraphDirectionMarkers, applyImportedDocxParagraphFormattingChangeMarkers, applyImportedDocxParagraphIndentMarkers, applyImportedDocxParagraphPaginationMarkers, applyImportedDocxParagraphShadingMarkers, applyImportedDocxParagraphSpacingMarkers, applyImportedDocxParagraphTabStopMarkers, applyImportedDocxRunFormattingMarkers, applyImportedDocxTableOfContentsMarkers, applyImportedDocxTextBoxMarkers, createDocxParagraphStyleResolver, createDocxTableStyleResolver, createImportedDocxRunFormattingMarkerState, docxCaptionBookmark, docxCaptionReferenceTarget, docxCaptionSequenceKind, docxEquationHtml, docxFieldInstructions, docxFieldOccurrenceIsInlineEditable, docxFieldOccurrences, docxFieldResultText, docxRunPropertySources, docxTableCellStyleLayers, docxTablePropertySources, docxTableRunPropertySources, hasImportedDocxChangeMarkers, hasImportedDocxContentControlMarkers, hasImportedDocxIndexMarkers, hasImportedDocxNumberingChangeMarkers, hasImportedDocxParagraphAlignmentMarkers, hasImportedDocxParagraphBorderMarkers, hasImportedDocxParagraphDirectionMarkers, hasImportedDocxParagraphFormattingChangeMarkers, hasImportedDocxParagraphIndentMarkers, hasImportedDocxParagraphPaginationMarkers, hasImportedDocxParagraphShadingMarkers, hasImportedDocxParagraphSpacingMarkers, hasImportedDocxParagraphTabStopMarkers, hasImportedDocxRunFormattingMarkers, hasImportedDocxTableOfContentsMarkers, hasImportedDocxTextBoxMarkers, hasInvalidDocxFieldStructure, importedDocxStrike, importedDocxUnderline, inspectDocxContentControls, inspectDocxEquation, inspectDocxHiddenText, inspectDocxLegacyTextEffects, inspectDocxPageBorders, inspectDocxPageMarginSettings, inspectDocxPageMargins, inspectDocxPageSize, inspectDocxPaperSource, inspectDocxRunBorder, inspectDocxRunFonts, inspectDocxRunShading, inspectDocxTextBoxes, isDocxEquationLikeRoot, isSupportedDocxEquationPlacement, isSupportedDocxMoveChange, isSupportedDocxNumberingChange, isSupportedDocxParagraphFormattingChange, isSupportedDocxRunFormattingChange, markDocxContentControls, markDocxIndexes, markDocxNumberingChanges, markDocxPackageEquations, markDocxParagraphAlignments, markDocxParagraphBorders, markDocxParagraphDirections, markDocxParagraphFormattingChanges, markDocxParagraphIndents, markDocxParagraphPagination, markDocxParagraphShading, markDocxParagraphSpacing, markDocxParagraphTabStops, markDocxRunFormattingIntoState, markDocxTablesOfContents, markDocxTextBoxes, markDocxTextChanges, parseDirectDocxParagraphShading, parseDocxPageBorders, parseDocxPageGeometry, parseDocxPageMargins, parseDocxPaperSource, resolveDocxHiddenText, resolveDocxLegacyTextEffects, resolveDocxParagraphBordersForParagraph, resolveDocxRunBorder, resolveDocxRunShading, resolveDocxTableStyleResolver, supportedDocxIndexEntryField, supportedDocxIndexField, supportedDocxMovePairCount, supportedDocxTableOfContentsField };
|