docxmlater 9.6.0 → 9.6.2

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.
@@ -56,7 +56,9 @@ const TableOfContentsElement_1 = require("../elements/TableOfContentsElement");
56
56
  const NumberingManager_1 = require("../formatting/NumberingManager");
57
57
  const Style_1 = require("../formatting/Style");
58
58
  const StylesManager_1 = require("../formatting/StylesManager");
59
- const ListNormalizer_1 = require("./ListNormalizer");
59
+ const compatibility_types_1 = require("../types/compatibility-types");
60
+ const CompatibilityUpgrader_1 = require("../utils/CompatibilityUpgrader");
61
+ const legacyCompatFlags_1 = require("../constants/legacyCompatFlags");
60
62
  const logger_1 = require("../utils/logger");
61
63
  const units_1 = require("../utils/units");
62
64
  function getLogger() {
@@ -147,6 +149,9 @@ class Document {
147
149
  _originalContentTypes;
148
150
  _originalStylesXml;
149
151
  _originalNumberingXml;
152
+ _originalSettingsXml;
153
+ _settingsModified = false;
154
+ _compatInfo;
150
155
  rsidRoot;
151
156
  rsids = new Set();
152
157
  documentProtection;
@@ -217,6 +222,11 @@ class Document {
217
222
  if (numberingXml) {
218
223
  doc._originalNumberingXml = numberingXml;
219
224
  }
225
+ const settingsXml = zipHandler.getFileAsString(types_1.DOCX_PATHS.SETTINGS);
226
+ if (settingsXml) {
227
+ doc._originalSettingsXml = settingsXml;
228
+ doc.parseSettingsFromXml(settingsXml);
229
+ }
220
230
  await doc.parseDocument();
221
231
  if (useInMemoryAccept) {
222
232
  logger.info('Accepting revisions using in-memory transformation');
@@ -263,6 +273,11 @@ class Document {
263
273
  if (numberingXml) {
264
274
  doc._originalNumberingXml = numberingXml;
265
275
  }
276
+ const settingsXml = zipHandler.getFileAsString(types_1.DOCX_PATHS.SETTINGS);
277
+ if (settingsXml) {
278
+ doc._originalSettingsXml = settingsXml;
279
+ doc.parseSettingsFromXml(settingsXml);
280
+ }
266
281
  await doc.parseDocument();
267
282
  if (useInMemoryAccept) {
268
283
  logger.info('Accepting revisions using in-memory transformation');
@@ -272,6 +287,140 @@ class Document {
272
287
  logger.info('Document loaded from buffer', { paragraphs: doc.getParagraphCount() });
273
288
  return doc;
274
289
  }
290
+ parseSettingsFromXml(settingsXml) {
291
+ const trackRevisionsMatch = settingsXml.match(/<w:trackRevisions\b([^>]*)\/?>/);
292
+ if (trackRevisionsMatch) {
293
+ const attrs = trackRevisionsMatch[1] ?? '';
294
+ const valMatch = attrs.match(/w:val\s*=\s*"([^"]*)"/);
295
+ if (valMatch && valMatch[1] !== undefined) {
296
+ const val = valMatch[1].toLowerCase();
297
+ this.trackChangesEnabled = val !== 'false' && val !== '0' && val !== 'off';
298
+ }
299
+ else {
300
+ this.trackChangesEnabled = true;
301
+ }
302
+ }
303
+ const hasDoNotTrackFormatting = /<w:doNotTrackFormatting\b[^>]*\/?>/.test(settingsXml);
304
+ if (hasDoNotTrackFormatting) {
305
+ this.trackFormatting = false;
306
+ }
307
+ const hasTrackFormatting = /<w:trackFormatting\b[^>]*\/?>/.test(settingsXml);
308
+ if (hasTrackFormatting) {
309
+ this.trackFormatting = true;
310
+ }
311
+ const revisionViewMatch = settingsXml.match(/<w:revisionView\b([^>]*)\/?>/);
312
+ if (revisionViewMatch) {
313
+ const attrs = revisionViewMatch[1] || '';
314
+ const insDelMatch = attrs.match(/w:insDel\s*=\s*"([^"]*)"/);
315
+ const formattingMatch = attrs.match(/w:formatting\s*=\s*"([^"]*)"/);
316
+ const inkMatch = attrs.match(/w:inkAnnotations\s*=\s*"([^"]*)"/);
317
+ if (insDelMatch?.[1] !== undefined) {
318
+ this.revisionViewSettings.showInsertionsAndDeletions = insDelMatch[1] !== '0';
319
+ }
320
+ if (formattingMatch?.[1] !== undefined) {
321
+ this.revisionViewSettings.showFormatting = formattingMatch[1] !== '0';
322
+ }
323
+ if (inkMatch?.[1] !== undefined) {
324
+ this.revisionViewSettings.showInkAnnotations = inkMatch[1] !== '0';
325
+ }
326
+ }
327
+ const protMatch = settingsXml.match(/<w:documentProtection\b([^>]*)\/?>/);
328
+ if (protMatch) {
329
+ const attrs = protMatch[1] || '';
330
+ const editMatch = attrs.match(/w:edit\s*=\s*"([^"]*)"/);
331
+ const enforcementMatch = attrs.match(/w:enforcement\s*=\s*"([^"]*)"/);
332
+ if (editMatch?.[1]) {
333
+ const edit = editMatch[1];
334
+ const enforcement = enforcementMatch?.[1] ? enforcementMatch[1] !== '0' : true;
335
+ this.documentProtection = { edit, enforcement };
336
+ const cryptProviderMatch = attrs.match(/w:cryptProviderType\s*=\s*"([^"]*)"/);
337
+ const cryptAlgClassMatch = attrs.match(/w:cryptAlgorithmClass\s*=\s*"([^"]*)"/);
338
+ const cryptAlgTypeMatch = attrs.match(/w:cryptAlgorithmType\s*=\s*"([^"]*)"/);
339
+ const cryptAlgSidMatch = attrs.match(/w:cryptAlgorithmSid\s*=\s*"([^"]*)"/);
340
+ const cryptSpinMatch = attrs.match(/w:cryptSpinCount\s*=\s*"([^"]*)"/);
341
+ const hashMatch = attrs.match(/w:hash\s*=\s*"([^"]*)"/);
342
+ const saltMatch = attrs.match(/w:salt\s*=\s*"([^"]*)"/);
343
+ if (cryptProviderMatch?.[1])
344
+ this.documentProtection.cryptProviderType = cryptProviderMatch[1];
345
+ if (cryptAlgClassMatch?.[1])
346
+ this.documentProtection.cryptAlgorithmClass = cryptAlgClassMatch[1];
347
+ if (cryptAlgTypeMatch?.[1])
348
+ this.documentProtection.cryptAlgorithmType = cryptAlgTypeMatch[1];
349
+ if (cryptAlgSidMatch?.[1])
350
+ this.documentProtection.cryptAlgorithmSid = parseInt(cryptAlgSidMatch[1], 10);
351
+ if (cryptSpinMatch?.[1])
352
+ this.documentProtection.cryptSpinCount = parseInt(cryptSpinMatch[1], 10);
353
+ if (hashMatch?.[1])
354
+ this.documentProtection.hash = hashMatch[1];
355
+ if (saltMatch?.[1])
356
+ this.documentProtection.salt = saltMatch[1];
357
+ }
358
+ }
359
+ const rsidsBlockMatch = settingsXml.match(/<w:rsids>([\s\S]*?)<\/w:rsids>/);
360
+ if (rsidsBlockMatch?.[1]) {
361
+ const rsidsBlock = rsidsBlockMatch[1];
362
+ const rsidRootMatch = rsidsBlock.match(/<w:rsidRoot\s+w:val\s*=\s*"([^"]*)"\s*\/?>/);
363
+ if (rsidRootMatch?.[1]) {
364
+ this.rsidRoot = rsidRootMatch[1].toUpperCase();
365
+ }
366
+ const rsidRegex = /<w:rsid\s+w:val\s*=\s*"([^"]*)"\s*\/?>/g;
367
+ let rsidMatch;
368
+ while ((rsidMatch = rsidRegex.exec(rsidsBlock)) !== null) {
369
+ if (rsidMatch[1])
370
+ this.rsids.add(rsidMatch[1].toUpperCase());
371
+ }
372
+ if (this.rsidRoot) {
373
+ this.rsids.add(this.rsidRoot);
374
+ }
375
+ }
376
+ this._compatInfo = this.parseCompatBlock(settingsXml);
377
+ }
378
+ parseCompatBlock(settingsXml) {
379
+ const compatSettings = [];
380
+ const legacyFlags = [];
381
+ let mode = compatibility_types_1.CompatibilityMode.Word2007;
382
+ const compatBlockMatch = settingsXml.match(/<w:compat>([\s\S]*?)<\/w:compat>/);
383
+ if (compatBlockMatch?.[1]) {
384
+ const compatBlock = compatBlockMatch[1];
385
+ const settingRegex = /<w:compatSetting\s+([^>]*)\/?\s*>/g;
386
+ let settingMatch;
387
+ while ((settingMatch = settingRegex.exec(compatBlock)) !== null) {
388
+ const attrs = settingMatch[1] ?? '';
389
+ const nameMatch = attrs.match(/w:name\s*=\s*"([^"]*)"/);
390
+ const uriMatch = attrs.match(/w:uri\s*=\s*"([^"]*)"/);
391
+ const valMatch = attrs.match(/w:val\s*=\s*"([^"]*)"/);
392
+ if (nameMatch?.[1] && uriMatch?.[1] && valMatch?.[1]) {
393
+ const setting = {
394
+ name: nameMatch[1],
395
+ uri: uriMatch[1],
396
+ val: valMatch[1],
397
+ };
398
+ compatSettings.push(setting);
399
+ if (setting.name === 'compatibilityMode' &&
400
+ setting.uri === 'http://schemas.microsoft.com/office/word') {
401
+ const modeVal = parseInt(setting.val, 10);
402
+ if (!isNaN(modeVal)) {
403
+ mode = modeVal;
404
+ }
405
+ }
406
+ }
407
+ }
408
+ const legacyFlagRegex = /<w:(\w+)(?:\s[^>]*)?\/?>/g;
409
+ let flagMatch;
410
+ while ((flagMatch = legacyFlagRegex.exec(compatBlock)) !== null) {
411
+ const tagName = flagMatch[1];
412
+ if (!tagName || tagName === 'compatSetting')
413
+ continue;
414
+ legacyFlags.push(tagName);
415
+ }
416
+ }
417
+ return {
418
+ mode,
419
+ isLegacyMode: mode < compatibility_types_1.CompatibilityMode.Word2013Plus,
420
+ compatSettings,
421
+ legacyFlags,
422
+ };
423
+ }
275
424
  async parseDocument() {
276
425
  const result = await this.parser.parseDocument(this.zipHandler, this.relationshipManager, this.imageManager, this.bookmarkManager);
277
426
  this.bodyElements = result.bodyElements;
@@ -377,7 +526,7 @@ class Document {
377
526
  this.zipHandler.addFile(types_1.DOCX_PATHS.STYLES, this.stylesManager.generateStylesXml());
378
527
  this.zipHandler.addFile(types_1.DOCX_PATHS.NUMBERING, this.numberingManager.generateNumberingXml());
379
528
  this.zipHandler.addFile("word/fontTable.xml", this.generator.generateFontTable());
380
- this.zipHandler.addFile("word/settings.xml", this.generator.generateSettings({
529
+ this.zipHandler.addFile(types_1.DOCX_PATHS.SETTINGS, this.generator.generateSettings({
381
530
  trackChangesEnabled: this.trackChangesEnabled,
382
531
  trackFormatting: this.trackFormatting,
383
532
  revisionView: this.revisionViewSettings,
@@ -385,6 +534,18 @@ class Document {
385
534
  rsids: this.getRsids(),
386
535
  documentProtection: this.documentProtection,
387
536
  }));
537
+ this._compatInfo = {
538
+ mode: compatibility_types_1.CompatibilityMode.Word2013Plus,
539
+ isLegacyMode: false,
540
+ compatSettings: [
541
+ { name: 'compatibilityMode', uri: 'http://schemas.microsoft.com/office/word', val: '15' },
542
+ { name: 'overrideTableStyleFontSizeAndJustification', uri: 'http://schemas.microsoft.com/office/word', val: '1' },
543
+ { name: 'enableOpenTypeFeatures', uri: 'http://schemas.microsoft.com/office/word', val: '1' },
544
+ { name: 'doNotFlipMirrorIndents', uri: 'http://schemas.microsoft.com/office/word', val: '1' },
545
+ { name: 'differentiateMultirowTableHeaders', uri: 'http://schemas.microsoft.com/office/word', val: '1' },
546
+ ],
547
+ legacyFlags: [],
548
+ };
388
549
  this.zipHandler.addFile("word/theme/theme1.xml", this.generator.generateTheme());
389
550
  this.zipHandler.addFile(types_1.DOCX_PATHS.CORE_PROPS, this.generator.generateCoreProps(this.properties));
390
551
  this.zipHandler.addFile(types_1.DOCX_PATHS.APP_PROPS, this.generator.generateAppProps(this.properties));
@@ -504,11 +665,6 @@ class Document {
504
665
  }
505
666
  return result;
506
667
  }
507
- normalizeTableLists(options) {
508
- const normalizer = new ListNormalizer_1.ListNormalizer(this.numberingManager);
509
- const tables = this.getAllTables();
510
- return normalizer.normalizeAllTables(tables, options);
511
- }
512
668
  getTableOfContentsElements() {
513
669
  return this.bodyElements.filter((el) => el instanceof TableOfContentsElement_1.TableOfContentsElement);
514
670
  }
@@ -644,6 +800,7 @@ class Document {
644
800
  }
645
801
  this.updateStylesXml();
646
802
  this.updateNumberingXml();
803
+ this.updateSettingsXml();
647
804
  this.updateCoreProps();
648
805
  this.updateAppProps();
649
806
  this.saveImages();
@@ -717,6 +874,7 @@ class Document {
717
874
  }
718
875
  this.updateStylesXml();
719
876
  this.updateNumberingXml();
877
+ this.updateSettingsXml();
720
878
  this.updateCoreProps();
721
879
  this.updateAppProps();
722
880
  this.saveImages();
@@ -724,6 +882,7 @@ class Document {
724
882
  this.saveFooters();
725
883
  this.saveComments();
726
884
  this.updatePeopleXml();
885
+ this.saveCustomProperties();
727
886
  this.updateRelationships();
728
887
  this.updateContentTypesWithImagesHeadersFootersAndComments();
729
888
  if (this.autoPopulateTOCs) {
@@ -812,6 +971,127 @@ class Document {
812
971
  this.zipHandler.updateFile(types_1.DOCX_PATHS.NUMBERING, xml);
813
972
  }
814
973
  }
974
+ updateSettingsXml() {
975
+ const xml = this.mergeSettingsWithOriginal();
976
+ this.zipHandler.updateFile(types_1.DOCX_PATHS.SETTINGS, xml);
977
+ }
978
+ mergeSettingsWithOriginal() {
979
+ if (!this._originalSettingsXml) {
980
+ return this.generator.generateSettings({
981
+ trackChangesEnabled: this.trackChangesEnabled,
982
+ trackFormatting: this.trackFormatting,
983
+ revisionView: this.revisionViewSettings,
984
+ rsidRoot: this.rsidRoot,
985
+ rsids: this.getRsids(),
986
+ documentProtection: this.documentProtection,
987
+ });
988
+ }
989
+ if (!this._settingsModified) {
990
+ return this._originalSettingsXml;
991
+ }
992
+ let xml = this._originalSettingsXml;
993
+ xml = this.mergeTrackChangesIntoSettings(xml);
994
+ xml = this.mergeProtectionIntoSettings(xml);
995
+ xml = this.mergeRsidsIntoSettings(xml);
996
+ return xml;
997
+ }
998
+ mergeTrackChangesIntoSettings(xml) {
999
+ xml = xml.replace(/<w:trackRevisions\b[^>]*\/>/g, '');
1000
+ xml = xml.replace(/<w:trackRevisions\b[^>]*>[\s\S]*?<\/w:trackRevisions>/g, '');
1001
+ xml = xml.replace(/<w:doNotTrackFormatting\b[^>]*\/>/g, '');
1002
+ xml = xml.replace(/<w:doNotTrackFormatting\b[^>]*>[\s\S]*?<\/w:doNotTrackFormatting>/g, '');
1003
+ xml = xml.replace(/<w:trackFormatting\b[^>]*\/>/g, '');
1004
+ xml = xml.replace(/<w:trackFormatting\b[^>]*>[\s\S]*?<\/w:trackFormatting>/g, '');
1005
+ xml = xml.replace(/<w:revisionView\b[^>]*\/>/g, '');
1006
+ xml = xml.replace(/<w:revisionView\b[^>]*>[\s\S]*?<\/w:revisionView>/g, '');
1007
+ let trackBlock = '';
1008
+ const view = this.revisionViewSettings;
1009
+ if (!view.showInsertionsAndDeletions || !view.showFormatting || !view.showInkAnnotations) {
1010
+ trackBlock += `\n <w:revisionView w:insDel="${view.showInsertionsAndDeletions ? '1' : '0'}" w:formatting="${view.showFormatting ? '1' : '0'}" w:inkAnnotations="${view.showInkAnnotations ? '1' : '0'}"/>`;
1011
+ }
1012
+ if (this.trackChangesEnabled) {
1013
+ trackBlock += '\n <w:trackRevisions/>';
1014
+ }
1015
+ if (!this.trackFormatting) {
1016
+ trackBlock += '\n <w:doNotTrackFormatting/>';
1017
+ }
1018
+ if (trackBlock) {
1019
+ if (/<w:documentProtection\b/.test(xml)) {
1020
+ xml = xml.replace(/<w:documentProtection\b/, trackBlock + '\n <w:documentProtection');
1021
+ }
1022
+ else if (/<w:autoFormatOverride\b/.test(xml)) {
1023
+ xml = xml.replace(/<w:autoFormatOverride\b/, trackBlock + '\n <w:autoFormatOverride');
1024
+ }
1025
+ else if (/<w:defaultTabStop\b/.test(xml)) {
1026
+ xml = xml.replace(/<w:defaultTabStop\b/, trackBlock + '\n <w:defaultTabStop');
1027
+ }
1028
+ else {
1029
+ xml = xml.replace(/<\/w:settings>/, trackBlock + '\n</w:settings>');
1030
+ }
1031
+ }
1032
+ return xml;
1033
+ }
1034
+ mergeProtectionIntoSettings(xml) {
1035
+ xml = xml.replace(/<w:documentProtection\b[^>]*\/>/g, '');
1036
+ xml = xml.replace(/<w:documentProtection\b[^>]*>[\s\S]*?<\/w:documentProtection>/g, '');
1037
+ if (!this.documentProtection) {
1038
+ return xml;
1039
+ }
1040
+ const prot = this.documentProtection;
1041
+ let protXml = `\n <w:documentProtection w:edit="${prot.edit}" w:enforcement="${prot.enforcement ? '1' : '0'}"`;
1042
+ if (prot.cryptProviderType)
1043
+ protXml += ` w:cryptProviderType="${prot.cryptProviderType}"`;
1044
+ if (prot.cryptAlgorithmClass)
1045
+ protXml += ` w:cryptAlgorithmClass="${prot.cryptAlgorithmClass}"`;
1046
+ if (prot.cryptAlgorithmType)
1047
+ protXml += ` w:cryptAlgorithmType="${prot.cryptAlgorithmType}"`;
1048
+ if (prot.cryptAlgorithmSid)
1049
+ protXml += ` w:cryptAlgorithmSid="${prot.cryptAlgorithmSid}"`;
1050
+ if (prot.cryptSpinCount)
1051
+ protXml += ` w:cryptSpinCount="${prot.cryptSpinCount}"`;
1052
+ if (prot.hash)
1053
+ protXml += ` w:hash="${prot.hash}"`;
1054
+ if (prot.salt)
1055
+ protXml += ` w:salt="${prot.salt}"`;
1056
+ protXml += '/>';
1057
+ if (/<w:autoFormatOverride\b/.test(xml)) {
1058
+ xml = xml.replace(/<w:autoFormatOverride\b/, protXml + '\n <w:autoFormatOverride');
1059
+ }
1060
+ else if (/<w:defaultTabStop\b/.test(xml)) {
1061
+ xml = xml.replace(/<w:defaultTabStop\b/, protXml + '\n <w:defaultTabStop');
1062
+ }
1063
+ else {
1064
+ xml = xml.replace(/<\/w:settings>/, protXml + '\n</w:settings>');
1065
+ }
1066
+ return xml;
1067
+ }
1068
+ mergeRsidsIntoSettings(xml) {
1069
+ xml = xml.replace(/<w:rsids>[\s\S]*?<\/w:rsids>/g, '');
1070
+ if (this.rsids.size === 0) {
1071
+ return xml;
1072
+ }
1073
+ let rsidsXml = '\n <w:rsids>';
1074
+ if (this.rsidRoot) {
1075
+ rsidsXml += `\n <w:rsidRoot w:val="${this.rsidRoot}"/>`;
1076
+ }
1077
+ for (const rsid of this.rsids) {
1078
+ rsidsXml += `\n <w:rsid w:val="${rsid}"/>`;
1079
+ }
1080
+ rsidsXml += '\n </w:rsids>';
1081
+ if (/<\/w:compat>/.test(xml)) {
1082
+ xml = xml.replace(/<\/w:compat>/, '</w:compat>' + rsidsXml);
1083
+ }
1084
+ else if (/<m:mathPr\b/.test(xml)) {
1085
+ xml = xml.replace(/<m:mathPr\b/, rsidsXml + '\n <m:mathPr');
1086
+ }
1087
+ else if (/<w:themeFontLang\b/.test(xml)) {
1088
+ xml = xml.replace(/<w:themeFontLang\b/, rsidsXml + '\n <w:themeFontLang');
1089
+ }
1090
+ else {
1091
+ xml = xml.replace(/<\/w:settings>/, rsidsXml + '\n</w:settings>');
1092
+ }
1093
+ return xml;
1094
+ }
815
1095
  getStylesManager() {
816
1096
  return this.stylesManager;
817
1097
  }
@@ -3901,6 +4181,7 @@ class Document {
3901
4181
  this.clearAllParagraphPropertyChanges();
3902
4182
  }
3903
4183
  this.trackChangesEnabled = true;
4184
+ this._settingsModified = true;
3904
4185
  if (options) {
3905
4186
  if (options.trackFormatting !== undefined) {
3906
4187
  this.trackFormatting = options.trackFormatting;
@@ -3926,6 +4207,7 @@ class Document {
3926
4207
  }
3927
4208
  disableTrackChanges() {
3928
4209
  this.trackChangesEnabled = false;
4210
+ this._settingsModified = true;
3929
4211
  this.trackingContext.disable();
3930
4212
  return this;
3931
4213
  }
@@ -3992,6 +4274,7 @@ class Document {
3992
4274
  }
3993
4275
  this.rsidRoot = rsidRoot.toUpperCase();
3994
4276
  this.rsids.add(this.rsidRoot);
4277
+ this._settingsModified = true;
3995
4278
  return this;
3996
4279
  }
3997
4280
  addRsid(rsid) {
@@ -3999,6 +4282,7 @@ class Document {
3999
4282
  throw new Error("RSID must be an 8-character hexadecimal value");
4000
4283
  }
4001
4284
  this.rsids.add(rsid.toUpperCase());
4285
+ this._settingsModified = true;
4002
4286
  return this;
4003
4287
  }
4004
4288
  generateRsid() {
@@ -4007,6 +4291,7 @@ class Document {
4007
4291
  .toUpperCase()
4008
4292
  .padStart(8, "0");
4009
4293
  this.rsids.add(rsid);
4294
+ this._settingsModified = true;
4010
4295
  return rsid;
4011
4296
  }
4012
4297
  getRsidRoot() {
@@ -4025,6 +4310,7 @@ class Document {
4025
4310
  cryptAlgorithmSid: protection.cryptAlgorithmSid,
4026
4311
  cryptSpinCount: protection.cryptSpinCount,
4027
4312
  };
4313
+ this._settingsModified = true;
4028
4314
  if (protection.password) {
4029
4315
  const crypto = require("crypto");
4030
4316
  const salt = crypto.randomBytes(16).toString("base64");
@@ -4038,6 +4324,7 @@ class Document {
4038
4324
  }
4039
4325
  unprotectDocument() {
4040
4326
  this.documentProtection = undefined;
4327
+ this._settingsModified = true;
4041
4328
  return this;
4042
4329
  }
4043
4330
  isProtected() {
@@ -4046,6 +4333,65 @@ class Document {
4046
4333
  getProtection() {
4047
4334
  return this.documentProtection;
4048
4335
  }
4336
+ getCompatibilityMode() {
4337
+ return this._compatInfo?.mode ?? compatibility_types_1.CompatibilityMode.Word2007;
4338
+ }
4339
+ isCompatibilityMode() {
4340
+ return this._compatInfo?.isLegacyMode ?? true;
4341
+ }
4342
+ getCompatibilityInfo() {
4343
+ return this._compatInfo ?? {
4344
+ mode: compatibility_types_1.CompatibilityMode.Word2007,
4345
+ isLegacyMode: true,
4346
+ compatSettings: [],
4347
+ legacyFlags: [],
4348
+ };
4349
+ }
4350
+ upgradeToModernFormat() {
4351
+ const currentMode = this.getCompatibilityMode();
4352
+ const currentInfo = this.getCompatibilityInfo();
4353
+ if (currentMode === compatibility_types_1.CompatibilityMode.Word2013Plus && currentInfo.legacyFlags.length === 0) {
4354
+ return {
4355
+ previousMode: currentMode,
4356
+ newMode: 15,
4357
+ removedFlags: [],
4358
+ addedSettings: [],
4359
+ namespacesExpanded: false,
4360
+ changed: false,
4361
+ };
4362
+ }
4363
+ if (this._originalSettingsXml) {
4364
+ const result = CompatibilityUpgrader_1.CompatibilityUpgrader.upgradeCompatBlock(this._originalSettingsXml, currentMode);
4365
+ this._originalSettingsXml = result.xml;
4366
+ this._settingsModified = true;
4367
+ const nsResult = CompatibilityUpgrader_1.CompatibilityUpgrader.ensureModernNamespaces(this.namespaces);
4368
+ this.namespaces = nsResult.namespaces;
4369
+ result.report.namespacesExpanded = nsResult.expanded;
4370
+ this._compatInfo = {
4371
+ mode: compatibility_types_1.CompatibilityMode.Word2013Plus,
4372
+ isLegacyMode: false,
4373
+ compatSettings: [...legacyCompatFlags_1.MODERN_COMPAT_SETTINGS],
4374
+ legacyFlags: [],
4375
+ };
4376
+ return result.report;
4377
+ }
4378
+ this._compatInfo = {
4379
+ mode: compatibility_types_1.CompatibilityMode.Word2013Plus,
4380
+ isLegacyMode: false,
4381
+ compatSettings: [...legacyCompatFlags_1.MODERN_COMPAT_SETTINGS],
4382
+ legacyFlags: [],
4383
+ };
4384
+ const nsResult = CompatibilityUpgrader_1.CompatibilityUpgrader.ensureModernNamespaces(this.namespaces);
4385
+ this.namespaces = nsResult.namespaces;
4386
+ return {
4387
+ previousMode: currentMode,
4388
+ newMode: 15,
4389
+ removedFlags: [],
4390
+ addedSettings: legacyCompatFlags_1.MODERN_COMPAT_SETTINGS.map(s => s.name),
4391
+ namespacesExpanded: nsResult.expanded,
4392
+ changed: currentMode !== compatibility_types_1.CompatibilityMode.Word2013Plus,
4393
+ };
4394
+ }
4049
4395
  createRunPropertiesChange(author, content, previousProperties, date) {
4050
4396
  const revision = Revision_1.Revision.createRunPropertiesChange(author, content, previousProperties, date);
4051
4397
  return this.revisionManager.register(revision);
@@ -4381,8 +4727,21 @@ class Document {
4381
4727
  this.trackingContext.disable();
4382
4728
  this._originalStylesXml = undefined;
4383
4729
  this._originalNumberingXml = undefined;
4730
+ this._originalSettingsXml = undefined;
4384
4731
  this._originalContentTypes = undefined;
4732
+ this._settingsModified = false;
4733
+ this._compatInfo = undefined;
4385
4734
  this.saveStateSnapshot = undefined;
4735
+ this.trackChangesEnabled = false;
4736
+ this.trackFormatting = true;
4737
+ this.revisionViewSettings = {
4738
+ showInsertionsAndDeletions: true,
4739
+ showFormatting: true,
4740
+ showInkAnnotations: true,
4741
+ };
4742
+ this.rsidRoot = undefined;
4743
+ this.rsids = new Set();
4744
+ this.documentProtection = undefined;
4386
4745
  this.properties = {};
4387
4746
  this.section = Section_1.Section.create();
4388
4747
  this.namespaces = {};