docxmlater 10.4.0 → 10.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docxmlater",
3
- "version": "10.4.0",
3
+ "version": "10.4.1",
4
4
  "description": "A comprehensive DOCX editing framework for creating, reading, and manipulating Microsoft Word documents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -6835,6 +6835,15 @@ export class Document {
6835
6835
  * });
6836
6836
  * ```
6837
6837
  */
6838
+ private static stripThemeFontsIfExplicitFont(runConfig: any): void {
6839
+ if (runConfig?.font) {
6840
+ delete runConfig.fontAsciiTheme;
6841
+ delete runConfig.fontHAnsiTheme;
6842
+ delete runConfig.fontEastAsiaTheme;
6843
+ delete runConfig.fontCsTheme;
6844
+ }
6845
+ }
6846
+
6838
6847
  public applyStyles(options?: ApplyStylesOptions): {
6839
6848
  heading1: boolean;
6840
6849
  heading2: boolean;
@@ -6915,6 +6924,14 @@ export class Document {
6915
6924
  },
6916
6925
  };
6917
6926
 
6927
+ // Strip theme font attributes when an explicit font is provided,
6928
+ // because Word prioritizes theme fonts over explicit font names.
6929
+ Document.stripThemeFontsIfExplicitFont(h1Config.run);
6930
+ Document.stripThemeFontsIfExplicitFont(h2Config.run);
6931
+ Document.stripThemeFontsIfExplicitFont(h3Config.run);
6932
+ Document.stripThemeFontsIfExplicitFont(normalConfig.run);
6933
+ Document.stripThemeFontsIfExplicitFont(listParaConfig.run);
6934
+
6918
6935
  // Extract preserve blank lines option (defaults to true)
6919
6936
  const preserveBlankLines = options?.preserveBlankLinesAfterHeading2Tables ?? true;
6920
6937
 
@@ -1344,9 +1344,61 @@ export class DocumentParser {
1344
1344
  hyperlinkObj['w:moveFrom'] ||
1345
1345
  hyperlinkObj['w:moveTo'];
1346
1346
  if (hasRevisionChildren) {
1347
- const rawXml = extractElementXmlAtPosition(child.pos, 'w:hyperlink');
1348
- if (rawXml) {
1349
- paragraph.addContent(new PreservedElement(rawXml, 'w:hyperlink', 'inline'));
1347
+ // Flatten revisions to make hyperlink editable (setUrl/setText).
1348
+ // Trades revision fidelity inside the hyperlink for editability.
1349
+ const flattenedObj = { ...hyperlinkObj };
1350
+ const allRuns: any[] = [];
1351
+
1352
+ // Keep existing direct runs
1353
+ if (flattenedObj['w:r']) {
1354
+ const directRuns = Array.isArray(flattenedObj['w:r'])
1355
+ ? flattenedObj['w:r']
1356
+ : [flattenedObj['w:r']];
1357
+ allRuns.push(...directRuns);
1358
+ }
1359
+
1360
+ // Unwrap w:ins runs (inserted content — keep)
1361
+ if (flattenedObj['w:ins']) {
1362
+ const insArr = Array.isArray(flattenedObj['w:ins'])
1363
+ ? flattenedObj['w:ins']
1364
+ : [flattenedObj['w:ins']];
1365
+ for (const ins of insArr) {
1366
+ if (ins['w:r']) {
1367
+ const insRuns = Array.isArray(ins['w:r']) ? ins['w:r'] : [ins['w:r']];
1368
+ allRuns.push(...insRuns);
1369
+ }
1370
+ }
1371
+ }
1372
+
1373
+ // Unwrap w:moveTo runs (move destination — keep)
1374
+ if (flattenedObj['w:moveTo']) {
1375
+ const moveToArr = Array.isArray(flattenedObj['w:moveTo'])
1376
+ ? flattenedObj['w:moveTo']
1377
+ : [flattenedObj['w:moveTo']];
1378
+ for (const mt of moveToArr) {
1379
+ if (mt['w:r']) {
1380
+ const mtRuns = Array.isArray(mt['w:r']) ? mt['w:r'] : [mt['w:r']];
1381
+ allRuns.push(...mtRuns);
1382
+ }
1383
+ }
1384
+ }
1385
+
1386
+ // Drop w:del and w:moveFrom (deleted/moved-away content)
1387
+ flattenedObj['w:r'] = allRuns.length > 0 ? allRuns : undefined;
1388
+ delete flattenedObj['w:del'];
1389
+ delete flattenedObj['w:ins'];
1390
+ delete flattenedObj['w:moveFrom'];
1391
+ delete flattenedObj['w:moveTo'];
1392
+
1393
+ const result = this.parseHyperlinkFromObject(flattenedObj, relationshipManager);
1394
+ if (result.hyperlink) {
1395
+ paragraph.addHyperlink(result.hyperlink);
1396
+ }
1397
+ for (const bookmark of result.bookmarkStarts) {
1398
+ paragraph.addBookmarkStart(bookmark);
1399
+ }
1400
+ for (const bookmark of result.bookmarkEnds) {
1401
+ paragraph.addBookmarkEnd(bookmark);
1350
1402
  }
1351
1403
  } else {
1352
1404
  const result = this.parseHyperlinkFromObject(hyperlinkObj, relationshipManager);