@a3s-lab/office 0.26.0 → 0.28.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/README.md +89 -2
- package/dist/0~4595.js +16 -2
- package/dist/0~5093.js +563 -201
- package/dist/0~6090.js +77 -77
- package/dist/{0~2805.js → 0~7043.js} +305 -2
- package/dist/0~document-editor.js +2633 -976
- package/dist/0~spreadsheet-editor.js +1324 -378
- package/dist/0~work-docx-export.js +737 -17
- package/dist/0~work-docx-import.js +173 -98
- package/dist/0~work-office-diagnostics.js +250 -5
- package/dist/{164.js → 1544.js} +1083 -785
- package/dist/4104.js +145 -29
- package/dist/5184.js +13 -0
- package/dist/6282.js +1898 -345
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/features/work/editors/document-command-catalog.d.ts +102 -0
- package/dist/internal/features/work/editors/document-font-dialog-model.d.ts +111 -0
- package/dist/internal/features/work/editors/document-font-dialog-script-font-model.d.ts +18 -0
- package/dist/internal/features/work/editors/document-font-dialog.d.ts +9 -0
- package/dist/internal/features/work/editors/document-home-ribbon.d.ts +2 -1
- package/dist/internal/features/work/editors/document-page-chrome-editor.d.ts +6 -0
- package/dist/internal/features/work/editors/document-page-chrome-ribbon.d.ts +2 -1
- package/dist/internal/features/work/editors/document-strike-ribbon.d.ts +7 -0
- package/dist/internal/features/work/editors/document-text-case-ribbon.d.ts +4 -0
- package/dist/internal/features/work/editors/document-toolbar.d.ts +3 -1
- package/dist/internal/features/work/editors/document-underline-ribbon.d.ts +9 -0
- package/dist/internal/features/work/editors/document-wps-shortcuts.d.ts +1 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-fill-format.d.ts +11 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-format.d.ts +2 -1
- package/dist/internal/features/work/editors/spreadsheet-format-cells-dialog-model.d.ts +13 -2
- package/dist/internal/features/work/editors/spreadsheet-format-cells-fill-panel.d.ts +13 -0
- package/dist/internal/features/work/editors/spreadsheet-format-cells-fill-preview.d.ts +6 -0
- package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +1 -1
- package/dist/internal/features/work/editors/work-office-chrome.d.ts +9 -1
- package/dist/internal/features/work/work-document-character-formatting.d.ts +16 -1
- package/dist/internal/features/work/work-document-character-position.d.ts +9 -0
- package/dist/internal/features/work/work-document-character-scale.d.ts +8 -0
- package/dist/internal/features/work/work-document-character-spacing.d.ts +8 -0
- package/dist/internal/features/work/work-document-emphasis.d.ts +7 -0
- package/dist/internal/features/work/work-document-equations.d.ts +2 -1
- package/dist/internal/features/work/work-document-format-changes.d.ts +20 -2
- package/dist/internal/features/work/work-document-hidden-text.d.ts +5 -0
- package/dist/internal/features/work/work-document-kerning.d.ts +10 -0
- package/dist/internal/features/work/work-document-legacy-text-effects.d.ts +27 -0
- package/dist/internal/features/work/work-document-script-font-extension.d.ts +2 -0
- package/dist/internal/features/work/work-document-script-fonts.d.ts +51 -0
- package/dist/internal/features/work/work-document-strike.d.ts +21 -0
- package/dist/internal/features/work/work-document-text-case.d.ts +10 -0
- package/dist/internal/features/work/work-document-underline.d.ts +37 -0
- package/dist/internal/features/work/work-document-word-line-metrics.d.ts +16 -0
- package/dist/internal/features/work/work-docx-character-position.d.ts +2 -0
- package/dist/internal/features/work/work-docx-character-scale.d.ts +2 -0
- package/dist/internal/features/work/work-docx-character-spacing.d.ts +4 -0
- package/dist/internal/features/work/work-docx-emphasis-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-emphasis.d.ts +14 -0
- package/dist/internal/features/work/work-docx-hidden-text-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-hidden-text-export.d.ts +17 -0
- package/dist/internal/features/work/work-docx-hidden-text.d.ts +11 -0
- package/dist/internal/features/work/work-docx-kerning-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-kerning.d.ts +14 -0
- package/dist/internal/features/work/work-docx-legacy-text-effects-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-legacy-text-effects-export.d.ts +18 -0
- package/dist/internal/features/work/work-docx-legacy-text-effects.d.ts +12 -0
- package/dist/internal/features/work/work-docx-run-fonts-diagnostics.d.ts +3 -0
- package/dist/internal/features/work/work-docx-run-fonts-export.d.ts +14 -0
- package/dist/internal/features/work/work-docx-run-fonts.d.ts +13 -0
- package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +27 -2
- package/dist/internal/features/work/work-docx-run-property-order.d.ts +2 -0
- package/dist/internal/features/work/work-docx-run-script-font-import.d.ts +9 -0
- package/dist/internal/features/work/work-docx-strike.d.ts +8 -0
- package/dist/internal/features/work/work-docx-theme-reference.d.ts +1 -1
- package/dist/internal/features/work/work-docx-twips.d.ts +6 -0
- package/dist/internal/features/work/work-docx-underline.d.ts +3 -0
- package/dist/internal/features/work/work-spreadsheet-gradient-fill-canvas.d.ts +10 -0
- package/dist/internal/features/work/work-spreadsheet-native-fill-canvas.d.ts +8 -0
- package/dist/internal/features/work/work-spreadsheet-pattern-fill-canvas.d.ts +8 -0
- package/dist/internal/features/work/work-xlsx-cell-style-origin.d.ts +2 -1
- package/dist/internal/features/work/work-xlsx-cell-style-writer.d.ts +3 -0
- package/dist/internal/features/work/work-xlsx-cell-styles.d.ts +4 -0
- package/dist/internal/features/work/work-xlsx-gradient-fill.d.ts +31 -0
- package/dist/internal/features/work/work-xlsx-native-fill.d.ts +17 -0
- package/dist/internal/features/work/work-xlsx-pattern-fill.d.ts +21 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +809 -78
- package/docs/latest/en/browser-editor-architecture.md +24 -0
- package/package.json +35 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { __webpack_require__ } from "./0~rslib-runtime.js";
|
|
2
2
|
import { contentTypeForPart, directChildren, OoxmlPackage, parseXml, firstDescendant, descendants, directChild, xmlContainsAnyElement, attribute } from "./5184.js";
|
|
3
|
-
import { normalizeDocumentBookmarkName, docxBookmarkReferenceTarget,
|
|
4
|
-
import { markDocxParagraphShading, inspectDocxPageSize, docxCaptionBookmark, hasInvalidDocxFieldStructure, inspectDocxPageMargins, inspectDocxPaperSource, createDocxParagraphStyleResolver, createDocxTableStyleResolver, docxFieldOccurrences, inspectDocxEquation, inspectDocxPageMarginSettings, markDocxParagraphBorders, isSupportedDocxParagraphFormattingChange, docxFieldOccurrenceIsInlineEditable, docxCaptionSequenceKind, inspectDocxPageBorders, isSupportedDocxRunFormattingChange, docxFieldInstructions, isSupportedDocxEquationPlacement } from "./0~5093.js";
|
|
3
|
+
import { normalizeDocumentBookmarkName, docxBookmarkReferenceTarget, isDocumentParagraphArtBorderStyle, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, normalizeDocumentBookmarkNativeId, supportedDocxBookmarkReferenceInstruction, documentCitationTagsFromInstruction, docxDocumentFieldKind } from "./6282.js";
|
|
4
|
+
import { markDocxParagraphShading, inspectDocxPageSize, docxCaptionBookmark, hasInvalidDocxFieldStructure, inspectDocxLegacyTextEffects, inspectDocxPageMargins, inspectDocxPaperSource, createDocxParagraphStyleResolver, createDocxTableStyleResolver, docxFieldOccurrences, inspectDocxRunFonts, inspectDocxEquation, inspectDocxPageMarginSettings, markDocxParagraphBorders, isSupportedDocxParagraphFormattingChange, docxFieldOccurrenceIsInlineEditable, inspectDocxHiddenText, docxCaptionSequenceKind, inspectDocxPageBorders, isSupportedDocxRunFormattingChange, docxFieldInstructions, isSupportedDocxEquationPlacement } from "./0~5093.js";
|
|
5
5
|
import { normalizeDocumentHref } from "./0~work-document-links.js";
|
|
6
|
-
import { xmlAttributeLocalName,
|
|
6
|
+
import { xmlAttributeLocalName, readDocxBibliography, inspectDocxEmphasisMark, createDocxThemeResolver, parseDocxParagraphDefaultCollapsed, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace, inspectDocxKerningThresholdHalfPoints } from "./0~7043.js";
|
|
7
7
|
import { updateSpreadsheetWorksheetCompatibilitySummary, inspectXlsxPivotTables, isSupportedXlsxChartLegend, isSupportedXlsxChartPlotLayout, xlsxChartNodeUsesStackedGrouping, isSupportedXlsxChartSeriesFormatting, readXlsxFormulaFeaturesFromPackage, inspectXlsxHeaderFooterText, emptySpreadsheetWorksheetCompatibilitySummary, isSupportedXlsxWorksheetImageContentType, MAX_XLSX_WORKSHEET_IMAGE_BYTES, xlsxChartSeriesFormattingShapeProperties, diagnoseXlsxProtection, isEditableXlsxPaperSizeCode, isSupportedXlsxCombinationChartNodes } from "./4104.js";
|
|
8
|
-
import { spreadsheetConditionalComparisonNeedsUpperValue, isSpreadsheetConditionalIconSetName, isSpreadsheetConditionalComparisonOperator, spreadsheetConditionalIconSetCount, xlsxWorksheetCellEntries } from "./
|
|
8
|
+
import { spreadsheetConditionalComparisonNeedsUpperValue, isSpreadsheetConditionalIconSetName, isSpreadsheetConditionalComparisonOperator, spreadsheetConditionalIconSetCount, xlsxWorksheetCellEntries } from "./1544.js";
|
|
9
9
|
import { formulaHasStructuredReference, formulaHasExternalReference, parseSpreadsheetPrintTitles, volatileSpreadsheetFormulaFunctions, stripSpreadsheetSheetQualifier } from "./8715.js";
|
|
10
10
|
import { unsupportedSpreadsheetFormulaFunctions } from "./0~work-spreadsheet-formula-support.js";
|
|
11
11
|
var work_office_diagnostics_namespaceObject = {};
|
|
@@ -269,6 +269,187 @@ function equationIssue(code, message, severity = 'warning') {
|
|
|
269
269
|
severity
|
|
270
270
|
};
|
|
271
271
|
}
|
|
272
|
+
const EMPHASIS_DIAGNOSTIC_PART_PATTERN = /^word\/(?:document|styles|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
|
|
273
|
+
async function diagnoseDocxEmphasisMarks(archive, document) {
|
|
274
|
+
const parts = [
|
|
275
|
+
{
|
|
276
|
+
path: 'word/document.xml',
|
|
277
|
+
document
|
|
278
|
+
}
|
|
279
|
+
];
|
|
280
|
+
for (const path of archive.paths('word/'))if ('word/document.xml' !== path.toLowerCase() && EMPHASIS_DIAGNOSTIC_PART_PATTERN.test(path)) parts.push({
|
|
281
|
+
path,
|
|
282
|
+
document: await archive.xml(path)
|
|
283
|
+
});
|
|
284
|
+
let validCount = 0;
|
|
285
|
+
let explicitNoneCount = 0;
|
|
286
|
+
let underDotCount = 0;
|
|
287
|
+
let invalidCount = 0;
|
|
288
|
+
for (const part of parts){
|
|
289
|
+
const propertySets = descendants(part.document, 'rPr').filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
|
|
290
|
+
for (const properties of propertySets){
|
|
291
|
+
if (!directChildren(properties, 'em').length) continue;
|
|
292
|
+
const inspection = inspectDocxEmphasisMark(properties);
|
|
293
|
+
if ('valid' === inspection.status) {
|
|
294
|
+
validCount += 1;
|
|
295
|
+
if ('none' === inspection.value) explicitNoneCount += 1;
|
|
296
|
+
if ('underDot' === inspection.value) underDotCount += 1;
|
|
297
|
+
} else if ('invalid' === inspection.status) invalidCount += 1;
|
|
298
|
+
}
|
|
299
|
+
invalidCount += descendants(part.document, 'em').filter((element)=>{
|
|
300
|
+
const parent = element.parentElement;
|
|
301
|
+
return !parent || 'rPr' !== parent.localName || !DOCX_WORDPROCESSING_NAMESPACES.has(parent.namespaceURI ?? '');
|
|
302
|
+
}).length;
|
|
303
|
+
}
|
|
304
|
+
const issues = [];
|
|
305
|
+
if (validCount) issues.push({
|
|
306
|
+
code: 'docx.emphasis-mark',
|
|
307
|
+
severity: 'info',
|
|
308
|
+
feature: 'East Asian emphasis marks',
|
|
309
|
+
message: `${validCount} native emphasis mark(s), including ${explicitNoneCount} explicit none reset(s) and ${underDotCount} below-text dot(s), preserve all five w:em values through style inheritance, body and page-chrome editing, formatting revisions, CSS projection, and DOCX export. Runs with visible marks use browser line measurement so their out-of-line glyph extents are not approximated by the Worker/WASM shaper.`
|
|
310
|
+
});
|
|
311
|
+
if (invalidCount) issues.push({
|
|
312
|
+
code: 'docx.emphasis-mark.invalid',
|
|
313
|
+
severity: 'warning',
|
|
314
|
+
feature: 'East Asian emphasis marks',
|
|
315
|
+
message: `${invalidCount} malformed, duplicated, misplaced, namespace-spoofed, text-bearing, or unknown emphasis property set(s) are ignored instead of enabling untrusted typography.`
|
|
316
|
+
});
|
|
317
|
+
return issues;
|
|
318
|
+
}
|
|
319
|
+
const HIDDEN_TEXT_DIAGNOSTIC_PART_PATTERN = /^word\/(?:document|styles|header\d*|footer\d*|footnotes|endnotes|comments)\.xml$/i;
|
|
320
|
+
async function diagnoseDocxHiddenText(archive, document) {
|
|
321
|
+
const parts = [
|
|
322
|
+
document
|
|
323
|
+
];
|
|
324
|
+
for (const path of archive.paths('word/'))if ('word/document.xml' !== path.toLowerCase() && HIDDEN_TEXT_DIAGNOSTIC_PART_PATTERN.test(path)) parts.push(await archive.xml(path));
|
|
325
|
+
let hiddenCount = 0;
|
|
326
|
+
let visibleResetCount = 0;
|
|
327
|
+
let invalidCount = 0;
|
|
328
|
+
for (const part of parts){
|
|
329
|
+
const propertySets = descendants(part, 'rPr').filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
|
|
330
|
+
for (const properties of propertySets){
|
|
331
|
+
if (!directChildren(properties, 'vanish').length) continue;
|
|
332
|
+
const inspection = inspectDocxHiddenText(properties);
|
|
333
|
+
if ('valid' === inspection.status) if (inspection.value) hiddenCount += 1;
|
|
334
|
+
else visibleResetCount += 1;
|
|
335
|
+
else if ('invalid' === inspection.status) invalidCount += 1;
|
|
336
|
+
}
|
|
337
|
+
invalidCount += descendants(part, 'vanish').filter((element)=>{
|
|
338
|
+
const parent = element.parentElement;
|
|
339
|
+
return !parent || 'rPr' !== parent.localName || !DOCX_WORDPROCESSING_NAMESPACES.has(parent.namespaceURI ?? '');
|
|
340
|
+
}).length;
|
|
341
|
+
}
|
|
342
|
+
const issues = [];
|
|
343
|
+
const validCount = hiddenCount + visibleResetCount;
|
|
344
|
+
if (validCount) issues.push({
|
|
345
|
+
code: 'docx.hidden-text',
|
|
346
|
+
severity: 'info',
|
|
347
|
+
feature: 'Hidden text',
|
|
348
|
+
message: `${validCount} native hidden-text value(s), including ${hiddenCount} hidden value(s) and ${visibleResetCount} explicit visible reset(s), were detected across document defaults, character and paragraph styles, body, headers, footers, notes, comments, and formatting revisions. Editable Writer stories preserve w:vanish through the Font dialog, the show-hidden-text editing view, and exact DOCX export; unchanged comment XML remains source-preserved rather than becoming a rich comment-editing claim. Preview and PDF output keep hidden text suppressed, while affected paragraphs use browser-authoritative line measurement.`
|
|
349
|
+
});
|
|
350
|
+
if (invalidCount) issues.push({
|
|
351
|
+
code: 'docx.hidden-text.invalid',
|
|
352
|
+
severity: 'warning',
|
|
353
|
+
feature: 'Hidden text',
|
|
354
|
+
message: `${invalidCount} malformed, duplicated, misplaced, namespace-spoofed, text-bearing, child-bearing, extra-attribute, or unknown hidden-text property set(s) are ignored instead of hiding untrusted content.`
|
|
355
|
+
});
|
|
356
|
+
return issues;
|
|
357
|
+
}
|
|
358
|
+
const KERNING_DIAGNOSTIC_PART_PATTERN = /^word\/(?:document|styles|header\d*|footer\d*|footnotes|endnotes)\.xml$/i;
|
|
359
|
+
async function diagnoseDocxKerning(archive, document) {
|
|
360
|
+
const parts = [
|
|
361
|
+
{
|
|
362
|
+
path: 'word/document.xml',
|
|
363
|
+
document
|
|
364
|
+
}
|
|
365
|
+
];
|
|
366
|
+
for (const path of archive.paths('word/'))if ('word/document.xml' !== path.toLowerCase() && KERNING_DIAGNOSTIC_PART_PATTERN.test(path)) parts.push({
|
|
367
|
+
path,
|
|
368
|
+
document: await archive.xml(path)
|
|
369
|
+
});
|
|
370
|
+
let validCount = 0;
|
|
371
|
+
let explicitZeroCount = 0;
|
|
372
|
+
let invalidCount = 0;
|
|
373
|
+
for (const part of parts){
|
|
374
|
+
const propertySets = descendants(part.document, 'rPr').filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
|
|
375
|
+
for (const properties of propertySets){
|
|
376
|
+
if (!directChildren(properties, 'kern').length) continue;
|
|
377
|
+
const inspection = inspectDocxKerningThresholdHalfPoints(properties);
|
|
378
|
+
if ('valid' === inspection.status) {
|
|
379
|
+
validCount += 1;
|
|
380
|
+
if (0 === inspection.value) explicitZeroCount += 1;
|
|
381
|
+
} else if ('invalid' === inspection.status) invalidCount += 1;
|
|
382
|
+
}
|
|
383
|
+
invalidCount += descendants(part.document, 'kern').filter((element)=>{
|
|
384
|
+
const parent = element.parentElement;
|
|
385
|
+
return !parent || 'rPr' !== parent.localName || !DOCX_WORDPROCESSING_NAMESPACES.has(parent.namespaceURI ?? '');
|
|
386
|
+
}).length;
|
|
387
|
+
}
|
|
388
|
+
const issues = [];
|
|
389
|
+
if (validCount) issues.push({
|
|
390
|
+
code: 'docx.kerning',
|
|
391
|
+
severity: 'info',
|
|
392
|
+
feature: 'Character kerning',
|
|
393
|
+
message: `${validCount} native kerning threshold(s), including ${explicitZeroCount} explicit all-font-size value(s), preserve exact half-points through style inheritance, body and page-chrome editing, effective font-size rendering, formatting revisions, and DOCX export. Pair kerning applies when the effective w:sz value meets or exceeds w:kern; absence throughout the hierarchy keeps kerning disabled.`
|
|
394
|
+
});
|
|
395
|
+
if (invalidCount) issues.push({
|
|
396
|
+
code: 'docx.kerning.invalid',
|
|
397
|
+
severity: 'warning',
|
|
398
|
+
feature: 'Character kerning',
|
|
399
|
+
message: `${invalidCount} malformed, duplicated, misplaced, namespace-spoofed, text-bearing, or out-of-range kerning property set(s) are ignored instead of enabling untrusted typography.`
|
|
400
|
+
});
|
|
401
|
+
return issues;
|
|
402
|
+
}
|
|
403
|
+
const LEGACY_TEXT_EFFECTS_DIAGNOSTIC_PART_PATTERN = /^word\/(?:document|styles|header\d*|footer\d*|footnotes|endnotes|comments)\.xml$/i;
|
|
404
|
+
async function diagnoseDocxLegacyTextEffects(archive, document) {
|
|
405
|
+
const parts = [
|
|
406
|
+
document
|
|
407
|
+
];
|
|
408
|
+
for (const path of archive.paths('word/'))if ('word/document.xml' !== path.toLowerCase() && LEGACY_TEXT_EFFECTS_DIAGNOSTIC_PART_PATTERN.test(path)) parts.push(await archive.xml(path));
|
|
409
|
+
const enabled = {
|
|
410
|
+
outline: 0,
|
|
411
|
+
shadow: 0,
|
|
412
|
+
emboss: 0,
|
|
413
|
+
imprint: 0
|
|
414
|
+
};
|
|
415
|
+
let validCount = 0;
|
|
416
|
+
let explicitFalseCount = 0;
|
|
417
|
+
let invalidCount = 0;
|
|
418
|
+
for (const part of parts){
|
|
419
|
+
const propertySets = descendants(part, 'rPr').filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
|
|
420
|
+
for (const properties of propertySets){
|
|
421
|
+
if (!DOCUMENT_LEGACY_TEXT_EFFECT_NAMES.some((name)=>directChildren(properties, name).length > 0)) continue;
|
|
422
|
+
const inspection = inspectDocxLegacyTextEffects(properties);
|
|
423
|
+
if ('valid' === inspection.status) for (const name of DOCUMENT_LEGACY_TEXT_EFFECT_NAMES){
|
|
424
|
+
const value = inspection.value[name];
|
|
425
|
+
if (void 0 !== value) {
|
|
426
|
+
validCount += 1;
|
|
427
|
+
if (value) enabled[name] += 1;
|
|
428
|
+
else explicitFalseCount += 1;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
else if ('invalid' === inspection.status) invalidCount += 1;
|
|
432
|
+
}
|
|
433
|
+
for (const name of DOCUMENT_LEGACY_TEXT_EFFECT_NAMES)invalidCount += descendants(part, name).filter((element)=>{
|
|
434
|
+
const parent = element.parentElement;
|
|
435
|
+
return !parent || 'rPr' !== parent.localName || !DOCX_WORDPROCESSING_NAMESPACES.has(parent.namespaceURI ?? '');
|
|
436
|
+
}).length;
|
|
437
|
+
}
|
|
438
|
+
const issues = [];
|
|
439
|
+
if (validCount) issues.push({
|
|
440
|
+
code: 'docx.legacy-text-effects',
|
|
441
|
+
severity: 'info',
|
|
442
|
+
feature: 'Legacy text effects',
|
|
443
|
+
message: `${validCount} native legacy text-effect value(s), including ${explicitFalseCount} explicit false reset(s), ${enabled.outline} enabled outline value(s), ${enabled.shadow} enabled shadow value(s), ${enabled.emboss} enabled emboss value(s), and ${enabled.imprint} enabled imprint value(s), were detected across document defaults, styles, body, page chrome, notes, comments, and formatting revisions. Editable Writer stories preserve w:outline, w:shadow, w:emboss, and w:imprint through independently mixed Font-dialog controls, conflict-aware one-step Undo, Format Painter, bounded CSS paint projections, and exact DOCX export. Outline plus shadow remains valid; emboss and imprint stay mutually exclusive with the other enabled legacy effects. The browser and PDF projections are bounded visual approximations rather than a claim of desktop-engine pixel identity, and no non-standard shortcut is invented.`
|
|
444
|
+
});
|
|
445
|
+
if (invalidCount) issues.push({
|
|
446
|
+
code: 'docx.legacy-text-effects.invalid',
|
|
447
|
+
severity: 'warning',
|
|
448
|
+
feature: 'Legacy text effects',
|
|
449
|
+
message: `${invalidCount} malformed, duplicated, misplaced, namespace-spoofed, text-bearing, child-bearing, extra-attribute, unknown, or conflicting legacy text-effect property set(s) are ignored instead of enabling contradictory or untrusted paint effects.`
|
|
450
|
+
});
|
|
451
|
+
return issues;
|
|
452
|
+
}
|
|
272
453
|
const WORDPROCESSINGML_NAMESPACES = new Set([
|
|
273
454
|
'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
|
|
274
455
|
'http://purl.oclc.org/ooxml/wordprocessingml/main'
|
|
@@ -665,6 +846,63 @@ async function diagnoseDocxParagraphShading(archive, document) {
|
|
|
665
846
|
});
|
|
666
847
|
return issues;
|
|
667
848
|
}
|
|
849
|
+
const RUN_FONT_DIAGNOSTIC_PART_PATTERN = /^word\/(?:document|styles|header\d*|footer\d*|footnotes|endnotes|comments)\.xml$/i;
|
|
850
|
+
async function diagnoseDocxRunFonts(archive, document) {
|
|
851
|
+
const parts = [
|
|
852
|
+
{
|
|
853
|
+
path: 'word/document.xml',
|
|
854
|
+
document
|
|
855
|
+
}
|
|
856
|
+
];
|
|
857
|
+
for (const path of archive.paths('word/'))if ('word/document.xml' !== path.toLowerCase() && RUN_FONT_DIAGNOSTIC_PART_PATTERN.test(path)) parts.push({
|
|
858
|
+
path,
|
|
859
|
+
document: await archive.xml(path)
|
|
860
|
+
});
|
|
861
|
+
let validCount = 0;
|
|
862
|
+
let directSlotCount = 0;
|
|
863
|
+
let themeSlotCount = 0;
|
|
864
|
+
let hintCount = 0;
|
|
865
|
+
let invalidCount = 0;
|
|
866
|
+
for (const part of parts){
|
|
867
|
+
const propertySets = descendants(part.document, 'rPr').filter((element)=>DOCX_WORDPROCESSING_NAMESPACES.has(element.namespaceURI ?? ''));
|
|
868
|
+
for (const properties of propertySets){
|
|
869
|
+
if (!directChildren(properties, 'rFonts').length) continue;
|
|
870
|
+
const inspection = inspectDocxRunFonts(properties);
|
|
871
|
+
if ('valid' === inspection.status) {
|
|
872
|
+
validCount += 1;
|
|
873
|
+
if (!inspection.value) continue;
|
|
874
|
+
for (const slot of [
|
|
875
|
+
inspection.value.ascii,
|
|
876
|
+
inspection.value.highAnsi,
|
|
877
|
+
inspection.value.eastAsia,
|
|
878
|
+
inspection.value.complexScript
|
|
879
|
+
]){
|
|
880
|
+
if (slot?.name) directSlotCount += 1;
|
|
881
|
+
if (slot?.theme) themeSlotCount += 1;
|
|
882
|
+
}
|
|
883
|
+
if (inspection.value.hint) hintCount += 1;
|
|
884
|
+
} else if ('invalid' === inspection.status) invalidCount += 1;
|
|
885
|
+
}
|
|
886
|
+
invalidCount += descendants(part.document, 'rFonts').filter((element)=>{
|
|
887
|
+
const parent = element.parentElement;
|
|
888
|
+
return !parent || 'rPr' !== parent.localName || !DOCX_WORDPROCESSING_NAMESPACES.has(parent.namespaceURI ?? '');
|
|
889
|
+
}).length;
|
|
890
|
+
}
|
|
891
|
+
const issues = [];
|
|
892
|
+
if (validCount) issues.push({
|
|
893
|
+
code: "docx.script-fonts",
|
|
894
|
+
severity: 'info',
|
|
895
|
+
feature: 'Script-specific run fonts',
|
|
896
|
+
message: `${validCount} native run-font property set(s), containing ${directSlotCount} direct slot value(s), ${themeSlotCount} theme slot reference(s), and ${hintCount} script hint(s), preserve the independent ASCII, high ANSI, East Asian, and complex-script identities through style inheritance, mixed-script browser rendering, body and page-chrome editing, formatting revisions, and DOCX export. Browser-resolved families remain separate from native source identity so font substitution does not rewrite untouched theme references.`
|
|
897
|
+
});
|
|
898
|
+
if (invalidCount) issues.push({
|
|
899
|
+
code: "docx.script-fonts.invalid",
|
|
900
|
+
severity: 'warning',
|
|
901
|
+
feature: 'Script-specific run fonts',
|
|
902
|
+
message: `${invalidCount} malformed, duplicated, misplaced, namespace-spoofed, child-bearing, text-bearing, unknown, or oversized run-font property set(s) are ignored instead of applying untrusted font metadata.`
|
|
903
|
+
});
|
|
904
|
+
return issues;
|
|
905
|
+
}
|
|
668
906
|
const SUPPORTED_CHART_ELEMENTS = new Set([
|
|
669
907
|
'barChart',
|
|
670
908
|
'lineChart',
|
|
@@ -1687,6 +1925,13 @@ async function analyzeDocxCompatibility(file, messages, sourcePackage) {
|
|
|
1687
1925
|
}
|
|
1688
1926
|
issues.push(...await diagnoseDocxNotes(archive, document));
|
|
1689
1927
|
issues.push(...await diagnoseDocxEquations(archive, document));
|
|
1928
|
+
if (document) {
|
|
1929
|
+
issues.push(...await diagnoseDocxKerning(archive, document));
|
|
1930
|
+
issues.push(...await diagnoseDocxEmphasisMarks(archive, document));
|
|
1931
|
+
issues.push(...await diagnoseDocxHiddenText(archive, document));
|
|
1932
|
+
issues.push(...await diagnoseDocxLegacyTextEffects(archive, document));
|
|
1933
|
+
issues.push(...await diagnoseDocxRunFonts(archive, document));
|
|
1934
|
+
}
|
|
1690
1935
|
issues.push(...await diagnoseDocxPageChrome(archive));
|
|
1691
1936
|
if (archive.paths('word/embeddings/').length) issues.push(work_office_diagnostics_issue('docx.embedded', 'Embedded objects', 'Embedded Office and OLE payload parts plus safe relationships are retained in source-backed exports, but Work does not render or edit their object anchors; placement inside regenerated document XML may normalize.'));
|
|
1692
1937
|
if (document) {
|
|
@@ -1716,7 +1961,7 @@ async function analyzeDocxCompatibility(file, messages, sourcePackage) {
|
|
|
1716
1961
|
const supportedRunFormattingRevisionCount = runFormattingRevisions.filter(isSupportedDocxRunFormattingChange).length;
|
|
1717
1962
|
const supportedParagraphFormattingRevisionCount = paragraphFormattingRevisions.filter(isSupportedDocxParagraphFormattingChange).length;
|
|
1718
1963
|
if (textRevisions.some((revision)=>descendants(revision, 't').length || descendants(revision, 'delText').length)) issues.push(work_office_diagnostics_issue('docx.revisions', 'Tracked changes', 'Body-text insertions and deletions preserve their author and date, remain reviewable in Work, and round-trip as native DOCX revisions.', 'info'));
|
|
1719
|
-
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, subscript, superscript, font, size, color, highlight, and grid state. They remain reviewable in Work and round-trip as native w:rPrChange records.`, 'info'));
|
|
1964
|
+
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 scale, spacing, kerning threshold, emphasis mark, baseline position, and grid state. They remain reviewable in Work and round-trip as native w:rPrChange records.`, 'info'));
|
|
1720
1965
|
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'));
|
|
1721
1966
|
if (textRevisions.some((revision)=>!descendants(revision, 't').length && !descendants(revision, 'delText').length) || supportedRunFormattingRevisionCount !== runFormattingRevisions.length || supportedParagraphFormattingRevisionCount !== paragraphFormattingRevisions.length || [
|
|
1722
1967
|
'moveFrom',
|