@a3s-lab/office 0.37.5 → 0.38.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 CHANGED
@@ -309,9 +309,14 @@ and [CLI reference](./docs/latest/en/cli-reference.md).
309
309
 
310
310
  ## Current release
311
311
 
312
- Version `0.37.5` keeps the release surface focused on local, testable
312
+ Version `0.38.0` keeps the release surface focused on local, testable
313
313
  workflows:
314
314
 
315
+ - Writer's shared advanced Font dialog now edits the complete bounded Office
316
+ 2010 OpenType typography set: 16 ligature combinations, numeral form and
317
+ spacing, style sets 1-20, and contextual alternates. Mixed selections,
318
+ tracked formatting, Undo, body/page-chrome stories, exact DOCX reopen, and
319
+ malformed-input diagnostics share one model with structured equations.
315
320
  - Spreadsheet XLSX import/export now retains the workbook's native 1900 or
316
321
  1904 date system, exact typed date serials, dynamic date filters, and
317
322
  epoch-correct current-date authoring across controlled and collaborative
@@ -1,6 +1,6 @@
1
1
  import jszip from "jszip";
2
2
  import { normalizeDocumentIndexEntryDraft, serializeUtf8Xml, directChildren, xmlNamespacePrefix, normalizeDocumentLanguageTag, parseXml, firstDescendant, decodeXmlBytes, directChild, descendants, normalizeDocumentProofingLanguages, attribute as work_ooxml_package_attribute, normalizeDocumentIndexOptions } from "./4121.js";
3
- import { normalizeDocumentEmphasisMark, normalizeDocumentCharacterScalePercent, documentCitationStyle, normalizeDocumentKerningThresholdHalfPoints, normalizeDocumentCharacterPositionHalfPoints, normalizeDocumentCharacterSpacingTwips, normalizeDocumentTabStops, createDocumentBibliography, documentCitationStyleDetails } from "./4174.js";
3
+ import { normalizeDocumentEmphasisMark, normalizeDocumentCharacterScalePercent, documentCitationStyle, normalizeDocumentKerningThresholdHalfPoints, normalizeDocumentCharacterPositionHalfPoints, normalizeDocumentCharacterSpacingTwips, normalizeDocumentOpenTypeNumberSpacing, createDocumentBibliography, normalizeDocumentOpenTypeNumberForm, normalizeDocumentOpenTypeLigatures, normalizeDocumentTabStops, documentCitationStyleDetails, normalizeDocumentOpenTypeStylisticSets } from "./4174.js";
4
4
  const BIBLIOGRAPHY_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/bibliography';
5
5
  const CUSTOM_XML_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/customXml';
6
6
  const OFFICE_RELATIONSHIPS_NAMESPACE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';
@@ -1151,6 +1151,154 @@ function work_docx_kerning_setWordValue(element, value) {
1151
1151
  if (existing) existing.value = value;
1152
1152
  else element.setAttributeNS(namespace, `${prefix}:val`, value);
1153
1153
  }
1154
+ const DOCX_WORD_2010_NAMESPACE = 'http://schemas.microsoft.com/office/word/2010/wordml';
1155
+ const OPEN_TYPE_PROPERTY_NAMES = [
1156
+ 'ligatures',
1157
+ 'numForm',
1158
+ 'numSpacing',
1159
+ 'stylisticSets',
1160
+ 'cntxtAlts'
1161
+ ];
1162
+ const OPEN_TYPE_PROPERTY_NAME_SET = new Set(OPEN_TYPE_PROPERTY_NAMES);
1163
+ const MAX_STYLISTIC_SET_ENTRIES = 4096;
1164
+ function resolveDocxOpenTypeFeatures(propertySources) {
1165
+ const features = {};
1166
+ let invalidCount = 0;
1167
+ let spoofedCount = 0;
1168
+ for (const properties of propertySources){
1169
+ const candidates = new Map();
1170
+ for (const child of directChildren(properties)){
1171
+ if (!OPEN_TYPE_PROPERTY_NAME_SET.has(child.localName)) continue;
1172
+ if (child.namespaceURI !== DOCX_WORD_2010_NAMESPACE) {
1173
+ spoofedCount += 1;
1174
+ continue;
1175
+ }
1176
+ const name = child.localName;
1177
+ const values = candidates.get(name) ?? [];
1178
+ values.push(child);
1179
+ candidates.set(name, values);
1180
+ }
1181
+ for (const name of OPEN_TYPE_PROPERTY_NAMES){
1182
+ const values = candidates.get(name) ?? [];
1183
+ if (!values.length) continue;
1184
+ if (1 !== values.length || !values[0]) {
1185
+ invalidCount += 1;
1186
+ continue;
1187
+ }
1188
+ const parsed = parseProperty(name, values[0]);
1189
+ if (null === parsed) {
1190
+ invalidCount += 1;
1191
+ continue;
1192
+ }
1193
+ if ('ligatures' === parsed.name) features.ligatures = parsed.value;
1194
+ else if ('numForm' === parsed.name) features.numberForm = parsed.value;
1195
+ else if ('numSpacing' === parsed.name) features.numberSpacing = parsed.value;
1196
+ else if ('stylisticSets' === parsed.name) features.stylisticSets = parsed.value;
1197
+ else features.contextualAlternates = parsed.value;
1198
+ }
1199
+ }
1200
+ return {
1201
+ features: invalidCount || spoofedCount || !Object.keys(features).length ? null : features,
1202
+ invalidCount,
1203
+ spoofedCount
1204
+ };
1205
+ }
1206
+ function parseProperty(name, element) {
1207
+ if ('ligatures' === name) {
1208
+ const attributes = word2010LeafAttributes(element, new Set([
1209
+ 'val'
1210
+ ]));
1211
+ const value = attributes?.size === 1 ? normalizeDocumentOpenTypeLigatures(attributes.get('val')) : null;
1212
+ return null === value ? null : {
1213
+ name,
1214
+ value
1215
+ };
1216
+ }
1217
+ if ('numForm' === name) {
1218
+ const attributes = word2010LeafAttributes(element, new Set([
1219
+ 'val'
1220
+ ]));
1221
+ const value = attributes?.size === 1 ? normalizeDocumentOpenTypeNumberForm(attributes.get('val')) : null;
1222
+ return null === value ? null : {
1223
+ name,
1224
+ value
1225
+ };
1226
+ }
1227
+ if ('numSpacing' === name) {
1228
+ const attributes = word2010LeafAttributes(element, new Set([
1229
+ 'val'
1230
+ ]));
1231
+ const value = attributes?.size === 1 ? normalizeDocumentOpenTypeNumberSpacing(attributes.get('val')) : null;
1232
+ return null === value ? null : {
1233
+ name,
1234
+ value
1235
+ };
1236
+ }
1237
+ if ('cntxtAlts' === name) {
1238
+ const attributes = word2010LeafAttributes(element, new Set([
1239
+ 'val'
1240
+ ]));
1241
+ if (!attributes) return null;
1242
+ const value = attributes.has('val') ? strictOnOff(attributes.get('val')) : true;
1243
+ return null === value ? null : {
1244
+ name,
1245
+ value
1246
+ };
1247
+ }
1248
+ const value = parseStylisticSets(element);
1249
+ return null === value ? null : {
1250
+ name,
1251
+ value
1252
+ };
1253
+ }
1254
+ function parseStylisticSets(element) {
1255
+ const attributes = word2010Attributes(element, new Set());
1256
+ if (!attributes || attributes.size || hasNonWhitespaceText(element)) return null;
1257
+ const children = directChildren(element);
1258
+ if (children.length > MAX_STYLISTIC_SET_ENTRIES) return null;
1259
+ const raw = [];
1260
+ for (const child of children){
1261
+ if ('styleSet' !== child.localName || child.namespaceURI !== DOCX_WORD_2010_NAMESPACE) return null;
1262
+ const childAttributes = word2010LeafAttributes(child, new Set([
1263
+ 'id',
1264
+ 'val'
1265
+ ]));
1266
+ if (!childAttributes?.has('id')) return null;
1267
+ const id = boundedInteger(childAttributes.get('id'), 1, 20);
1268
+ const enabled = childAttributes.has('val') ? strictOnOff(childAttributes.get('val')) : true;
1269
+ if (null === id || null === enabled) return null;
1270
+ if (enabled) raw.push(id);
1271
+ }
1272
+ return normalizeDocumentOpenTypeStylisticSets(raw);
1273
+ }
1274
+ function word2010LeafAttributes(element, allowed) {
1275
+ if (directChildren(element).length || hasNonWhitespaceText(element)) return null;
1276
+ return word2010Attributes(element, allowed);
1277
+ }
1278
+ function word2010Attributes(element, allowed) {
1279
+ const result = new Map();
1280
+ for (const attribute of Array.from(element.attributes)){
1281
+ if (attribute.namespaceURI === XMLNS_NAMESPACE) continue;
1282
+ const name = xmlAttributeLocalName(attribute);
1283
+ if (!allowed.has(name) || xmlAttributeNamespace(element, attribute) !== DOCX_WORD_2010_NAMESPACE || result.has(name)) return null;
1284
+ result.set(name, attribute.value);
1285
+ }
1286
+ return result;
1287
+ }
1288
+ function hasNonWhitespaceText(element) {
1289
+ return Array.from(element.childNodes).some((node)=>1 !== node.nodeType && (node.textContent ?? '').trim());
1290
+ }
1291
+ function strictOnOff(value) {
1292
+ if ('1' === value || 'true' === value) return true;
1293
+ if ('0' === value || 'false' === value) return false;
1294
+ return null;
1295
+ }
1296
+ function boundedInteger(value, minimum, maximum) {
1297
+ const source = value?.trim() ?? '';
1298
+ if (!/^[+-]?\d+$/.test(source)) return null;
1299
+ const number = Number(source);
1300
+ return Number.isSafeInteger(number) && number >= minimum && number <= maximum ? number : null;
1301
+ }
1154
1302
  function docxEmphasisMarkFromProperties(properties) {
1155
1303
  const inspection = inspectDocxEmphasisMark(properties);
1156
1304
  return 'valid' === inspection.status ? inspection.value : void 0;
@@ -1924,4 +2072,4 @@ function isParagraphPartRoot(root, path) {
1924
2072
  const expected = /^word\/header\d*\.xml$/i.test(path) ? 'hdr' : /^word\/footer\d*\.xml$/i.test(path) ? 'ftr' : /^word\/footnotes\.xml$/i.test(path) ? 'footnotes' : /^word\/endnotes\.xml$/i.test(path) ? 'endnotes' : 'document';
1925
2073
  return root.localName === expected && DOCX_WORDPROCESSING_NAMESPACES.has(root.namespaceURI ?? '');
1926
2074
  }
1927
- export { DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, DOCX_WORDPROCESSING_NAMESPACES, DocxParagraphDefaultCollapsedPatchCollector, STRICT_WORDPROCESSING_NAMESPACE, XMLNS_NAMESPACE, XML_NAMESPACE, assertXmlRoot, cloneXmlElement, createDocxThemeResolver, cssColorToHex, cssFontFamily, cssFontSize, dataBoolean, documentIndexEntryInstruction, documentIndexInstruction, documentProofingLanguageDocxOptions, docxCharacterPositionHalfPointsFromProperties, docxCharacterPositionValue, docxCharacterScalePercentFromProperties, docxCharacterScaleValue, docxCharacterSpacingTwipsFromProperties, docxCharacterSpacingValue, docxEmphasisMarkRunOptions, docxKerningThresholdValue, docxThemeColor, docxThemeFont, domDirection, hasNonWhitespaceXmlText, inspectDocxEmphasisMark, inspectDocxKerningThresholdHalfPoints, inspectDocxNoProof, inspectDocxProofingLanguages, mergeDocxIgnorableExtensions, mergeDocxIgnorableExtensionsAtPairs, paragraphAlignment, paragraphBidirectional, paragraphDirectionOptions, paragraphIndent, paragraphPaginationOptions, paragraphSpacingOptions, paragraphTabStops, parseBoundedDocxInteger, parseDocumentIndexEntryInstruction, parseDocumentIndexInstruction, parseDocxColorSchemeMappingElement, parseDocxParagraphDefaultCollapsed, parseDocxTwipsMeasure, patchDocxBibliography, patchDocxExplicitZeroCharacterSpacing, patchDocxExplicitZeroKerningThresholds, patchDocxParagraphDefaultCollapsed, readDocxBibliography, resolveDocxEmphasisMark, resolveDocxKerningThresholdHalfPoints, resolveDocxProofing, resolveDocxThemeResolver, xmlAttributeLocalName, xmlAttributeNamespace, xmlDeclaredPrefix, xmlNamespaceUri };
2075
+ export { DOCX_COLOR_SCHEME_MAPPING_ATTRIBUTES, DOCX_WORDPROCESSING_NAMESPACES, DOCX_WORD_2010_NAMESPACE, DocxParagraphDefaultCollapsedPatchCollector, STRICT_WORDPROCESSING_NAMESPACE, XMLNS_NAMESPACE, XML_NAMESPACE, assertXmlRoot, cloneXmlElement, createDocxThemeResolver, cssColorToHex, cssFontFamily, cssFontSize, dataBoolean, documentIndexEntryInstruction, documentIndexInstruction, documentProofingLanguageDocxOptions, docxCharacterPositionHalfPointsFromProperties, docxCharacterPositionValue, docxCharacterScalePercentFromProperties, docxCharacterScaleValue, docxCharacterSpacingTwipsFromProperties, docxCharacterSpacingValue, docxEmphasisMarkRunOptions, docxKerningThresholdValue, docxThemeColor, docxThemeFont, domDirection, hasNonWhitespaceXmlText, inspectDocxEmphasisMark, inspectDocxKerningThresholdHalfPoints, inspectDocxNoProof, inspectDocxProofingLanguages, mergeDocxIgnorableExtensions, mergeDocxIgnorableExtensionsAtPairs, paragraphAlignment, paragraphBidirectional, paragraphDirectionOptions, paragraphIndent, paragraphPaginationOptions, paragraphSpacingOptions, paragraphTabStops, parseBoundedDocxInteger, parseDocumentIndexEntryInstruction, parseDocumentIndexInstruction, parseDocxColorSchemeMappingElement, parseDocxParagraphDefaultCollapsed, parseDocxTwipsMeasure, patchDocxBibliography, patchDocxExplicitZeroCharacterSpacing, patchDocxExplicitZeroKerningThresholds, patchDocxParagraphDefaultCollapsed, readDocxBibliography, resolveDocxEmphasisMark, resolveDocxKerningThresholdHalfPoints, resolveDocxOpenTypeFeatures, resolveDocxProofing, resolveDocxThemeResolver, xmlAttributeLocalName, xmlAttributeNamespace, xmlDeclaredPrefix, xmlNamespaceUri };
package/dist/0~7240.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { documentRunBorderDomAttributes, normalizeDocumentRunBorder, normalizeDocumentParagraphBorder, serializeDocumentRunBorder, serializeDocumentRunShading, documentIndexEntryHtml, attribute as work_ooxml_package_attribute, documentScriptFontFallbackSlots, documentScriptFontsDomAttributes, documentHighlightFromDocxValue, documentTableOfContentsHtml, directChildren as work_ooxml_package_directChildren, documentParagraphShadingDomAttributes, serializeDocxThemeReference, 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 "./4121.js";
2
- import { docxThemeFont, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, parseDocumentIndexEntryInstruction, resolveDocxProofing, parseDocumentIndexInstruction, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, STRICT_WORDPROCESSING_NAMESPACE, docxCharacterSpacingTwipsFromProperties, parseBoundedDocxInteger, xmlAttributeLocalName, docxCharacterScalePercentFromProperties, resolveDocxEmphasisMark, docxCharacterPositionHalfPointsFromProperties, docxThemeColor, parseDocxParagraphDefaultCollapsed, resolveDocxKerningThresholdHalfPoints, resolveDocxThemeResolver as work_docx_theme_resolveDocxThemeResolver, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace, parseDocxTwipsMeasure } from "./0~4808.js";
3
- import { normalizeDocumentEmphasisMark, normalizeDocumentPageBorders, documentCharacterPositionDomAttributes, DOCUMENT_PAGE_BORDER_EDGES, normalizeDocumentTabStops, documentTextCaseFromWordFlags, documentStrikeDomAttributes, documentAutoLineHeight, documentKerningDomAttributes, normalizeDocumentUnderlineColor, documentCharacterScaleDomAttributes, serializeDocumentParagraphFormatting, normalizeDocumentPaperSource, documentEquationText, documentLegacyTextEffectsDomAttributes, documentLegacyTextEffectsConflict, documentCharacterSpacingDomAttributes, normalizeDocumentParagraphIndent, normalizeDocumentEquation, renderDocumentAutoLineHeight, documentUnderlineDomAttributes, normalizeDocumentUnderlineStyle, applyDocumentTextCaseStyle, documentHiddenTextDomAttributes, importedDocumentCharacterFormatting, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, createDocumentEquationElement, normalizeDocumentPageGeometry, serializeDocumentTabStops, documentWordLineHeightFactor, documentEmphasisMarkDomAttributes, normalizeDocumentPageMargins } from "./4174.js";
2
+ import { docxThemeFont, XML_NAMESPACE as work_docx_settings_xml_XML_NAMESPACE, parseDocumentIndexEntryInstruction, resolveDocxProofing, parseDocumentIndexInstruction, DOCX_WORD_2010_NAMESPACE, XMLNS_NAMESPACE as work_docx_settings_xml_XMLNS_NAMESPACE, STRICT_WORDPROCESSING_NAMESPACE, docxCharacterSpacingTwipsFromProperties, parseBoundedDocxInteger, xmlAttributeLocalName, resolveDocxOpenTypeFeatures, docxCharacterScalePercentFromProperties, resolveDocxEmphasisMark, docxCharacterPositionHalfPointsFromProperties, docxThemeColor, parseDocxParagraphDefaultCollapsed, resolveDocxKerningThresholdHalfPoints, resolveDocxThemeResolver as work_docx_theme_resolveDocxThemeResolver, DOCX_WORDPROCESSING_NAMESPACES, xmlAttributeNamespace, parseDocxTwipsMeasure } from "./0~5024.js";
3
+ import { normalizeDocumentEmphasisMark, normalizeDocumentPageBorders, documentCharacterPositionDomAttributes, DOCUMENT_PAGE_BORDER_EDGES, normalizeDocumentTabStops, documentTextCaseFromWordFlags, documentStrikeDomAttributes, documentAutoLineHeight, documentKerningDomAttributes, normalizeDocumentUnderlineColor, documentCharacterScaleDomAttributes, serializeDocumentParagraphFormatting, normalizeDocumentPaperSource, documentEquationText, documentLegacyTextEffectsDomAttributes, documentLegacyTextEffectsConflict, documentCharacterSpacingDomAttributes, normalizeDocumentParagraphIndent, normalizeDocumentEquation, documentOpenTypeDomAttributes, renderDocumentAutoLineHeight, documentUnderlineDomAttributes, normalizeDocumentUnderlineStyle, applyDocumentTextCaseStyle, documentHiddenTextDomAttributes, importedDocumentCharacterFormatting, DOCUMENT_LEGACY_TEXT_EFFECT_NAMES, createDocumentEquationElement, normalizeDocumentPageGeometry, serializeDocumentTabStops, documentWordLineHeightFactor, documentEmphasisMarkDomAttributes, normalizeDocumentPageMargins } from "./4174.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;
@@ -7369,6 +7369,13 @@ const SUPPORTED_RUN_PROPERTY_CHANGE_CHILDREN = new Set([
7369
7369
  'vertAlign',
7370
7370
  'bdr'
7371
7371
  ]);
7372
+ const SUPPORTED_OPEN_TYPE_PROPERTY_CHANGE_CHILDREN = new Set([
7373
+ 'ligatures',
7374
+ 'numForm',
7375
+ 'numSpacing',
7376
+ 'stylisticSets',
7377
+ 'cntxtAlts'
7378
+ ]);
7372
7379
  function createImportedDocxRunFormattingMarkerState(documents) {
7373
7380
  return {
7374
7381
  markers: {
@@ -7476,6 +7483,7 @@ function resolvedRunFormatting(propertySources, theme, runText, requestedFontSlo
7476
7483
  const runBorder = resolveDocxRunBorder(propertySources, theme).border;
7477
7484
  const runShading = resolveDocxRunShading(propertySources, theme).shading;
7478
7485
  const proofing = resolveDocxProofing(propertySources);
7486
+ const openTypeFeatures = resolveDocxOpenTypeFeatures(propertySources).features;
7479
7487
  for (const properties of propertySources){
7480
7488
  bold = overriddenBoolean(bold, onOffProperty(properties, 'b'));
7481
7489
  complexBold = overriddenBoolean(complexBold, onOffProperty(properties, 'bCs'));
@@ -7635,6 +7643,9 @@ function resolvedRunFormatting(propertySources, theme, runText, requestedFontSlo
7635
7643
  } : {},
7636
7644
  ...void 0 !== proofing.noProof ? {
7637
7645
  noProof: proofing.noProof
7646
+ } : {},
7647
+ ...openTypeFeatures ? {
7648
+ openTypeFeatures
7638
7649
  } : {}
7639
7650
  };
7640
7651
  }
@@ -7660,6 +7671,8 @@ function formattingMarkup(document, formatting) {
7660
7671
  if (formatting.fontFamily) span.style.fontFamily = formatting.fontFamily;
7661
7672
  if (formatting.scriptFonts) for (const [name, value] of Object.entries(documentScriptFontsDomAttributes(formatting.scriptFonts, formatting.scriptFontSlot)))if ('style' === name) span.style.cssText += `; ${value}`;
7662
7673
  else span.setAttribute(name, value);
7674
+ if (formatting.openTypeFeatures) for (const [name, value] of Object.entries(documentOpenTypeDomAttributes(formatting.openTypeFeatures)))if ('style' === name) span.style.cssText += `; ${value}`;
7675
+ else span.setAttribute(name, value);
7663
7676
  if (void 0 !== formatting.characterSpacingTwips) for (const [name, value] of Object.entries(documentCharacterSpacingDomAttributes(formatting.characterSpacingTwips)))if ('style' === name) span.style.cssText += `; ${value}`;
7664
7677
  else span.setAttribute(name, value);
7665
7678
  if (void 0 !== formatting.characterScalePercent) for (const [name, value] of Object.entries(documentCharacterScaleDomAttributes(formatting.characterScalePercent)))if ('style' === name) span.style.cssText += `; ${value}`;
@@ -7805,8 +7818,17 @@ function supportedRunFormattingChangeElement(change) {
7805
7818
  const source = properties[0];
7806
7819
  const names = new Set();
7807
7820
  for (const child of Array.from(source.children)){
7808
- if (!DOCX_WORDPROCESSING_NAMESPACES.has(child.namespaceURI ?? '') || !SUPPORTED_RUN_PROPERTY_CHANGE_CHILDREN.has(child.localName) || names.has(child.localName)) return null;
7809
- names.add(child.localName);
7821
+ const supportedWordProperty = DOCX_WORDPROCESSING_NAMESPACES.has(child.namespaceURI ?? '') && SUPPORTED_RUN_PROPERTY_CHANGE_CHILDREN.has(child.localName);
7822
+ const supportedOpenTypeProperty = child.namespaceURI === DOCX_WORD_2010_NAMESPACE && SUPPORTED_OPEN_TYPE_PROPERTY_CHANGE_CHILDREN.has(child.localName);
7823
+ const key = `${child.namespaceURI ?? ''}|${child.localName}`;
7824
+ if (!supportedWordProperty && !supportedOpenTypeProperty || names.has(key)) return null;
7825
+ names.add(key);
7826
+ }
7827
+ if (Array.from(source.children).some((child)=>child.namespaceURI === DOCX_WORD_2010_NAMESPACE)) {
7828
+ const openType = resolveDocxOpenTypeFeatures([
7829
+ source
7830
+ ]);
7831
+ if (!openType.features || openType.invalidCount || openType.spoofedCount) return null;
7810
7832
  }
7811
7833
  const id = work_ooxml_package_attribute(change, 'id')?.trim() ?? '';
7812
7834
  const author = work_ooxml_package_attribute(change, 'author')?.trim() ?? '';