@docx4j/core-ts 0.6.0 → 0.7.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.
Files changed (119) hide show
  1. package/README.md +60 -0
  2. package/dist/model/content/Body.mjs +6 -17
  3. package/dist/model/content/Comment.d.mts +2 -2
  4. package/dist/model/content/Comment.mjs +12 -7
  5. package/dist/model/content/ContentControl.d.mts +1 -1
  6. package/dist/model/content/ContentControl.mjs +8 -4
  7. package/dist/model/content/Font.d.mts +4 -1
  8. package/dist/model/content/Font.mjs +6 -2
  9. package/dist/model/content/List.d.mts +6 -3
  10. package/dist/model/content/List.mjs +15 -8
  11. package/dist/model/content/Paragraph.d.mts +12 -2
  12. package/dist/model/content/Paragraph.mjs +31 -11
  13. package/dist/model/content/Table.mjs +26 -16
  14. package/dist/model/content/TrackedChange.d.mts +2 -2
  15. package/dist/model/content/TrackedChange.mjs +6 -3
  16. package/dist/model/content/index.d.mts +3 -1
  17. package/dist/model/content/index.mjs +4 -1
  18. package/dist/model/content/ooxml.mjs +12 -1
  19. package/dist/model/content/paraIds.d.mts +5 -0
  20. package/dist/model/content/paraIds.mjs +54 -0
  21. package/dist/model/content/search.d.mts +2 -0
  22. package/dist/model/content/search.mjs +51 -7
  23. package/dist/model/content/story.d.mts +5 -2
  24. package/dist/model/content/story.mjs +6 -3
  25. package/dist/model/content/tableRules.mjs +2 -0
  26. package/dist/model/content/tracking.d.mts +35 -6
  27. package/dist/model/content/tracking.mjs +93 -12
  28. package/dist/model/content/tree.d.mts +7 -8
  29. package/dist/model/content/tree.mjs +7 -9
  30. package/dist/model/content/wordRange.d.mts +48 -0
  31. package/dist/model/content/wordRange.mjs +97 -0
  32. package/dist/model/customxml/CustomXmlPartCollection.d.mts +22 -1
  33. package/dist/model/customxml/CustomXmlPartCollection.mjs +48 -2
  34. package/dist/model/customxml/XmlMapping.d.mts +31 -7
  35. package/dist/model/customxml/XmlMapping.mjs +53 -10
  36. package/dist/model/customxml/bindings.d.mts +12 -2
  37. package/dist/model/customxml/bindings.mjs +98 -16
  38. package/dist/model/customxml/index.d.mts +1 -0
  39. package/dist/model/customxml/index.mjs +1 -0
  40. package/dist/model/customxml/opendope.d.mts +4 -1
  41. package/dist/model/customxml/opendope.mjs +9 -6
  42. package/dist/model/customxml/pictures.mjs +5 -3
  43. package/dist/model/customxml/storeItems.d.mts +57 -0
  44. package/dist/model/customxml/storeItems.mjs +122 -0
  45. package/dist/model/customxml/xhtml.mjs +15 -20
  46. package/dist/model/dateZone.d.mts +25 -0
  47. package/dist/model/dateZone.mjs +57 -0
  48. package/dist/model/index.d.mts +1 -0
  49. package/dist/model/index.mjs +1 -0
  50. package/dist/model/properties/PropertyResolver.d.mts +14 -1
  51. package/dist/model/properties/PropertyResolver.mjs +18 -3
  52. package/dist/model/properties/index.d.mts +1 -1
  53. package/dist/model/properties/log.mjs +2 -2
  54. package/dist/model/properties/styleUtil.d.mts +3 -1
  55. package/dist/model/properties/styleUtil.mjs +20 -24
  56. package/dist/model/text/CaseMapping.d.mts +38 -0
  57. package/dist/model/text/CaseMapping.mjs +86 -0
  58. package/dist/model/text/Extractor.d.mts +66 -6
  59. package/dist/model/text/Extractor.mjs +300 -56
  60. package/dist/model/text/PlainText.mjs +7 -4
  61. package/dist/model/text/TextContext.d.mts +103 -8
  62. package/dist/model/text/TextContext.mjs +228 -53
  63. package/dist/model/text/TextOptions.d.mts +88 -5
  64. package/dist/model/text/TextOptions.mjs +158 -17
  65. package/dist/model/text/TextResult.d.mts +126 -9
  66. package/dist/model/text/TextResult.mjs +115 -12
  67. package/dist/model/text/WmlToMarkdown.mjs +32 -7
  68. package/dist/model/text/caseMapping.generated.d.mts +7 -0
  69. package/dist/model/text/caseMapping.generated.mjs +214 -0
  70. package/dist/model/text/index.d.mts +3 -2
  71. package/dist/model/text/index.mjs +1 -0
  72. package/dist/model/wordIntegers.d.mts +29 -0
  73. package/dist/model/wordIntegers.mjs +78 -0
  74. package/dist/office-js/document.mjs +15 -1
  75. package/dist/office-js/toApiScript.mjs +8 -7
  76. package/dist/opc/DirectoryPartStore.d.mts +6 -2
  77. package/dist/opc/DirectoryPartStore.mjs +11 -4
  78. package/dist/opc/FlatOpcPartStore.d.mts +4 -2
  79. package/dist/opc/FlatOpcPartStore.mjs +11 -8
  80. package/dist/opc/Load.d.mts +32 -0
  81. package/dist/opc/Load.mjs +115 -5
  82. package/dist/opc/PartStore.d.mts +34 -1
  83. package/dist/opc/PartStore.mjs +71 -8
  84. package/dist/opc/Save.d.mts +17 -2
  85. package/dist/opc/Save.mjs +100 -4
  86. package/dist/opc/ZipPartStore.d.mts +4 -2
  87. package/dist/opc/ZipPartStore.mjs +12 -7
  88. package/dist/opc/exceptions.d.mts +140 -0
  89. package/dist/opc/exceptions.mjs +108 -0
  90. package/dist/opc/index.d.mts +7 -4
  91. package/dist/opc/index.mjs +5 -3
  92. package/dist/opc/mce/preprocessor.d.mts +121 -10
  93. package/dist/opc/mce/preprocessor.mjs +122 -21
  94. package/dist/opc/mce/understood.d.mts +3 -35
  95. package/dist/opc/mce/understood.mjs +27 -53
  96. package/dist/opc/repair/breaks.d.mts +23 -0
  97. package/dist/opc/repair/breaks.mjs +288 -0
  98. package/dist/opc/repair/hosts.d.mts +12 -0
  99. package/dist/opc/repair/hosts.mjs +33 -0
  100. package/dist/opc/repair/mainRoot.d.mts +19 -0
  101. package/dist/opc/repair/mainRoot.mjs +168 -0
  102. package/dist/opc/repair/unknownElements.d.mts +8 -0
  103. package/dist/opc/repair/unknownElements.mjs +180 -0
  104. package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
  105. package/dist/opc/repair/wmlNames.generated.mjs +80 -0
  106. package/dist/opc/skipped.d.mts +50 -0
  107. package/dist/opc/skipped.mjs +140 -0
  108. package/dist/packages/OpcPackage.d.mts +98 -5
  109. package/dist/packages/OpcPackage.mjs +122 -7
  110. package/dist/packages/WordprocessingMLPackage.mjs +3 -1
  111. package/dist/packages/index.d.mts +1 -1
  112. package/dist/parts/Part.d.mts +5 -1
  113. package/dist/parts/RelationshipsPart.d.mts +15 -0
  114. package/dist/parts/RelationshipsPart.mjs +66 -1
  115. package/dist/parts/XmlPart.d.mts +54 -5
  116. package/dist/parts/XmlPart.mjs +203 -10
  117. package/dist/parts/wml/index.d.mts +12 -1
  118. package/dist/parts/wml/index.mjs +25 -1
  119. package/package.json +2 -2
@@ -7,7 +7,10 @@ import type { ImageDescriber } from './TextResult.mjs';
7
7
  * another name: the content API's `TextView` (CR-002 phase F) is `getText`'s two views.
8
8
  */
9
9
  export type TextModelView = 'accepted' | 'original' | 'markup';
10
- /** The stories `include` adds (REQ-501, REQ-502). */
10
+ /**
11
+ * The stories `include` adds (REQ-501, REQ-502): `headers`, `footers` and `glossary`. Comments are `comments` (REQ-504, WD 0.91).
12
+ * `comments` here is deprecated, a spelling of `comments: true` kept because 0.6.0 released it (CR-012 section 29).
13
+ */
11
14
  export type TextInclude = 'headers' | 'footers' | 'comments' | 'glossary';
12
15
  /** `fields` (REQ-506). */
13
16
  export type TextFields = 'cached' | 'update';
@@ -23,11 +26,36 @@ export type TextTables = 'auto' | 'tsv' | 'grid';
23
26
  export type TextMarkupDetail = 'type' | 'author' | 'author_date';
24
27
  /** `layout` (REQ-709). */
25
28
  export type TextLayout = 'none' | 'indent';
29
+ /**
30
+ * `drop_caps` (REQ-521): a drop cap's frame paragraph (`w:framePr/@w:dropCap`) joined to the paragraph after it, as the
31
+ * page reads (`join`), or the two paragraphs as the package holds them (`asis`, Word's text). CR-012 section 24.3.
32
+ */
33
+ export type TextDropCaps = 'join' | 'asis';
34
+ /**
35
+ * `small_caps` (REQ-607): a small-caps run written as its stored characters (`asis`), or in capitals as a caps run is
36
+ * (`upper`, Word's text). CR-012 section 24.
37
+ */
38
+ export type TextSmallCaps = 'asis' | 'upper';
39
+ /**
40
+ * `repair` (REQ-207, WD 0.102): how a package Word reads only through a repair, or won't open, is loaded: every refusal kept
41
+ * (`refuse`), Word's repair followed where the WD states one (`word`), or that and this package's own (`all`). The load's
42
+ * option (`LoadOptions.repair`, CR-031): a reading of a package already loaded doesn't decide again, and the load's setting
43
+ * holds. `duplicate_entries`, which REQ-206 says an implementation MAY offer, isn't offered here: `word` reads its `first`
44
+ * (CR-031 D1).
45
+ */
46
+ export type TextRepair = 'refuse' | 'word' | 'all';
47
+ /**
48
+ * `profile` (REQ-1002, WD 0.41): a preset of option values applied before the caller's own, so that an option the caller
49
+ * sets by name, before or after the profile, overrides it. `word-text` is Word's Save As plain text as the options reach
50
+ * it (`WORD_TEXT_PROFILE`). CR-012 section 23.1.
51
+ */
52
+ export type TextProfile = 'word-text';
26
53
  /** A boolean option's value: a boolean, or `"true"` / `"false"` as a tool passes it. */
27
54
  type Bool = boolean | 'true' | 'false';
28
55
  /**
29
56
  * The options by the specification's names (WD section 10), every one optional, each absent one at its
30
- * default. `include` takes a list of story names or a string of them separated by commas or spaces;
57
+ * default. `include` takes a list of story names or a string of them separated by commas or spaces,
58
+ * and naming `comments` in it is a deprecated spelling of `comments: true`, refused beside `comments: false`;
31
59
  * a boolean takes `"true"` or `"false"` as well; any other value is its name, in any case.
32
60
  * `imageDescriber` is the host's (REQ-514), not one of the specification's options.
33
61
  */
@@ -42,6 +70,7 @@ export interface TextOptionsInit {
42
70
  field_codes?: Bool;
43
71
  fields?: TextFields;
44
72
  toc?: Bool;
73
+ drop_caps?: TextDropCaps;
45
74
  placeholders?: Bool;
46
75
  bindings?: TextBindings;
47
76
  list_labels?: Bool;
@@ -52,12 +81,18 @@ export interface TextOptionsInit {
52
81
  alt_text?: Bool;
53
82
  metadata?: Bool;
54
83
  symbols?: TextSymbols;
84
+ small_caps?: TextSmallCaps;
85
+ /** A BCP 47 tag (REQ-607, WD 0.80): the language of last resort for a cased run's capitals. */
86
+ default_language?: string;
55
87
  math?: TextMath;
56
88
  tables?: TextTables;
57
89
  markup_detail?: TextMarkupDetail;
58
90
  page_markers?: Bool;
59
91
  layout?: TextLayout;
60
92
  warnings?: Bool;
93
+ repair?: TextRepair;
94
+ /** A preset applied before the other options, whichever came first (REQ-1002); `word-text` or `word_text`, in any case. */
95
+ profile?: TextProfile | string | null;
61
96
  /** The describer images take their text from (REQ-514); `AltTextDescriber` by default. */
62
97
  imageDescriber?: ImageDescriber;
63
98
  }
@@ -73,6 +108,19 @@ export declare class TextOptionError extends Docx4JException {
73
108
  }
74
109
  /** The option names of WD section 10, in its order. docx4j `TextOptions.NAMES`. */
75
110
  export declare const TEXT_OPTION_NAMES: readonly string[];
111
+ /**
112
+ * `profile: word-text`'s values by WD name, in WD order (REQ-1002; docx4j `TextOptions.WORD_TEXT_VALUES`): the accepted
113
+ * view, hidden text in, headers and footers in, comments in through `comments` alone (WD 0.91), text boxes out, notes and their references in, list labels
114
+ * (WD 0.75), fields cached, no field codes, the table of contents in, a drop cap apart from its word, placeholders in,
115
+ * bound values, chunks expanded, symbols as they are, small caps in capitals, tables as tab-separated rows, no page
116
+ * markers, no indentation, no alt text, no metadata, no charts, SmartArt or embedded packages. `default_language` keeps
117
+ * its default, since the saving installation's language is not in the file (WD 0.80). What it does not reproduce: the
118
+ * notes' and comments' forms, CR LF and CR cells, folded hyphens, the one space Word writes after every list label where
119
+ * the level's suffix is written here (WD 0.79), Word's linear math (`math: unicodemath` is refused here, as in docx4j, so
120
+ * the preset leaves math as LaTeX; CR-012 section 23.1), and three accidents of Word's own: the partial update a DATE,
121
+ * TIME or SAVEDATE field triggers on open, the SYMBOL omission, and the stale PAGE number.
122
+ */
123
+ export declare const WORD_TEXT_PROFILE: Readonly<Record<string, unknown>>;
76
124
  /**
77
125
  * What a text includes and how it is written: the specification's section 10 options (REQ-1001), as
78
126
  * docx4j's `TextOptions` has them. Mutable; `Texts.of` reads it once.
@@ -101,6 +149,8 @@ export declare class TextOptions {
101
149
  * included under `field_codes`, and a paragraph with nothing else in it is no paragraph.
102
150
  */
103
151
  toc: boolean;
152
+ /** `drop_caps` (REQ-521): `join`, the default, or `asis`. */
153
+ dropCaps: TextDropCaps;
104
154
  placeholders: boolean;
105
155
  bindings: TextBindings;
106
156
  listLabels: boolean;
@@ -111,6 +161,15 @@ export declare class TextOptions {
111
161
  altText: boolean;
112
162
  metadata: boolean;
113
163
  symbols: TextSymbols;
164
+ /** `small_caps` (REQ-607): `asis`, the default, or `upper`. */
165
+ smallCaps: TextSmallCaps;
166
+ /**
167
+ * `default_language` (REQ-607, WD 0.80): the language a cased run's capitals are mapped by where the run, its styles and
168
+ * the document defaults name none. It stands in for Word's editing language, which a library cannot know;
169
+ * `w:themeFontLang` plays no part. A BCP 47 tag, kept as given; `CaseMapping.DEFAULT_LANGUAGE` (`en-US`) by default.
170
+ * CR-012 section 24.8.
171
+ */
172
+ defaultLanguage: string;
114
173
  math: TextMath;
115
174
  tables: TextTables;
116
175
  markupDetail: TextMarkupDetail;
@@ -122,18 +181,42 @@ export declare class TextOptions {
122
181
  pageMarkers: boolean;
123
182
  layout: TextLayout;
124
183
  warnings: boolean;
184
+ /**
185
+ * `repair` (REQ-207): the load's option, accepted here by the WD's name (REQ-1001) and passed by a caller that loads, as the
186
+ * suite's adapter does, to `LoadOptions.repair`; a reading of a loaded package doesn't use it.
187
+ */
188
+ repair: TextRepair;
125
189
  /** The describer images take their text from (REQ-514). */
126
190
  imageDescriber: ImageDescriber;
191
+ /** The profile applied (REQ-1002), or undefined. */
192
+ private profileName;
193
+ /** The options the caller set by name: a profile does not override them, whichever came first. */
194
+ private readonly explicit;
127
195
  /** Options from the specification's names and values (REQ-1001); those not named keep their defaults. */
128
196
  static of(init?: TextOptionsInit | TextOptions): TextOptions;
129
- /** Sets one option by its specification name and value; throws `TextOptionError` for one it does not define. */
197
+ /**
198
+ * Sets one option by its specification name and value; throws `TextOptionError` for one it does not define. An option set
199
+ * by name is the caller's: a profile, applied before or after, leaves it (REQ-1002). A member assigned directly is not
200
+ * recorded so, and a profile applied after the assignment overrides it.
201
+ */
130
202
  set(name: string, value: unknown): this;
203
+ /**
204
+ * Applies a profile (REQ-1002): its values for every option the caller has not set by name; an option the caller sets
205
+ * afterwards overrides it too. Undefined clears the name, leaving the values. See `WORD_TEXT_PROFILE`.
206
+ */
207
+ profile(p: TextProfile | undefined): this;
208
+ /** The profile applied, or undefined. */
209
+ get profileApplied(): TextProfile | undefined;
210
+ /** Sets one option without recording it as the caller's (a profile's value). */
211
+ private apply;
131
212
  private setInclude;
213
+ /** `comments` never stays in `include`: it is the deprecated spelling of `comments: true`, and the caller's option as that is. */
214
+ private addStories;
132
215
  /** Adds stories to `include` (docx4j's builder `include(Include...)`). */
133
216
  include(...stories: TextInclude[]): this;
134
- /** The stories `include` names; `comments: true` adds `comments`. */
217
+ /** The stories in scope: those `include` names, and `comments` where `comments` is true. */
135
218
  get includes(): ReadonlySet<TextInclude>;
136
- /** `comments: true` or `include: comments`. */
219
+ /** `comments: true`, the one setting (REQ-504, WD 0.91). */
137
220
  get comments(): boolean;
138
221
  set comments(value: boolean);
139
222
  /** A copy, for a reading one level down or a first reading. */
@@ -4,6 +4,8 @@
4
4
  // options through unchanged; docx4j's `of(Map)` and `set(name, value)` take the same.
5
5
  import { Docx4JException } from '../../opc/exceptions.mjs';
6
6
  import { AltTextDescriber } from './TextResult.mjs';
7
+ import { CaseMapping } from './CaseMapping.mjs';
8
+ import { log } from '../properties/log.mjs';
7
9
  /**
8
10
  * An option refused (REQ-1001): an unknown name, a value the specification does not define, or a
9
11
  * value this package does not implement yet. `statement` names the requirement, `option` the option.
@@ -20,11 +22,38 @@ export class TextOptionError extends Docx4JException {
20
22
  /** The option names of WD section 10, in its order. docx4j `TextOptions.NAMES`. */
21
23
  export const TEXT_OPTION_NAMES = Object.freeze([
22
24
  'view', 'include', 'text_boxes', 'notes', 'note_references', 'comments', 'hidden', 'field_codes',
23
- 'fields', 'toc', 'placeholders', 'bindings', 'list_labels', 'charts', 'smartart', 'embedded', 'altchunks',
24
- 'alt_text', 'metadata', 'symbols', 'math', 'tables', 'markup_detail', 'page_markers', 'layout',
25
- 'warnings',
25
+ 'fields', 'toc', 'drop_caps', 'placeholders', 'bindings', 'list_labels', 'charts', 'smartart', 'embedded', 'altchunks',
26
+ 'alt_text', 'metadata', 'symbols', 'small_caps', 'default_language', 'math', 'tables', 'markup_detail', 'page_markers', 'layout',
27
+ 'warnings', 'repair', 'profile',
26
28
  ]);
29
+ /**
30
+ * `profile: word-text`'s values by WD name, in WD order (REQ-1002; docx4j `TextOptions.WORD_TEXT_VALUES`): the accepted
31
+ * view, hidden text in, headers and footers in, comments in through `comments` alone (WD 0.91), text boxes out, notes and their references in, list labels
32
+ * (WD 0.75), fields cached, no field codes, the table of contents in, a drop cap apart from its word, placeholders in,
33
+ * bound values, chunks expanded, symbols as they are, small caps in capitals, tables as tab-separated rows, no page
34
+ * markers, no indentation, no alt text, no metadata, no charts, SmartArt or embedded packages. `default_language` keeps
35
+ * its default, since the saving installation's language is not in the file (WD 0.80). What it does not reproduce: the
36
+ * notes' and comments' forms, CR LF and CR cells, folded hyphens, the one space Word writes after every list label where
37
+ * the level's suffix is written here (WD 0.79), Word's linear math (`math: unicodemath` is refused here, as in docx4j, so
38
+ * the preset leaves math as LaTeX; CR-012 section 23.1), and three accidents of Word's own: the partial update a DATE,
39
+ * TIME or SAVEDATE field triggers on open, the SYMBOL omission, and the stale PAGE number.
40
+ */
41
+ export const WORD_TEXT_PROFILE = Object.freeze({
42
+ view: 'accepted', include: 'headers,footers', text_boxes: false, notes: true, note_references: true,
43
+ comments: true, hidden: true, field_codes: false, fields: 'cached', toc: true, drop_caps: 'asis', placeholders: true,
44
+ bindings: 'bound', list_labels: true, charts: false, smartart: false, embedded: false, altchunks: true,
45
+ alt_text: false, metadata: false, symbols: 'asis', small_caps: 'upper', math: 'latex', tables: 'tsv',
46
+ page_markers: false, layout: 'none',
47
+ });
27
48
  const INCLUDES = ['headers', 'footers', 'comments', 'glossary'];
49
+ /** `include`'s stories: a list of names, or a string of them separated by commas or spaces. */
50
+ function includeItems(value) {
51
+ const items = Array.isArray(value) ? value
52
+ : value === undefined || value === null ? [] : String(value).split(/[,\s]+/).filter((s) => s !== '');
53
+ return items.map((item) => choice('include', item, INCLUDES, 'REQ-501'));
54
+ }
55
+ /** Whether the deprecated spelling's notice has been written: once a process, since a caller's code is what has to change. */
56
+ let includeCommentsNoticed = false;
28
57
  /**
29
58
  * What a text includes and how it is written: the specification's section 10 options (REQ-1001), as
30
59
  * docx4j's `TextOptions` has them. Mutable; `Texts.of` reads it once.
@@ -54,6 +83,8 @@ export class TextOptions {
54
83
  * included under `field_codes`, and a paragraph with nothing else in it is no paragraph.
55
84
  */
56
85
  this.toc = false;
86
+ /** `drop_caps` (REQ-521): `join`, the default, or `asis`. */
87
+ this.dropCaps = 'join';
57
88
  this.placeholders = true;
58
89
  this.bindings = 'bound';
59
90
  this.listLabels = false;
@@ -64,6 +95,15 @@ export class TextOptions {
64
95
  this.altText = false;
65
96
  this.metadata = false;
66
97
  this.symbols = 'asis';
98
+ /** `small_caps` (REQ-607): `asis`, the default, or `upper`. */
99
+ this.smallCaps = 'asis';
100
+ /**
101
+ * `default_language` (REQ-607, WD 0.80): the language a cased run's capitals are mapped by where the run, its styles and
102
+ * the document defaults name none. It stands in for Word's editing language, which a library cannot know;
103
+ * `w:themeFontLang` plays no part. A BCP 47 tag, kept as given; `CaseMapping.DEFAULT_LANGUAGE` (`en-US`) by default.
104
+ * CR-012 section 24.8.
105
+ */
106
+ this.defaultLanguage = CaseMapping.DEFAULT_LANGUAGE;
67
107
  this.math = 'latex';
68
108
  this.tables = 'auto';
69
109
  this.markupDetail = 'type';
@@ -75,8 +115,15 @@ export class TextOptions {
75
115
  this.pageMarkers = false;
76
116
  this.layout = 'none';
77
117
  this.warnings = true;
118
+ /**
119
+ * `repair` (REQ-207): the load's option, accepted here by the WD's name (REQ-1001) and passed by a caller that loads, as the
120
+ * suite's adapter does, to `LoadOptions.repair`; a reading of a loaded package doesn't use it.
121
+ */
122
+ this.repair = 'refuse';
78
123
  /** The describer images take their text from (REQ-514). */
79
124
  this.imageDescriber = AltTextDescriber.INSTANCE;
125
+ /** The options the caller set by name: a profile does not override them, whichever came first. */
126
+ this.explicit = new Set();
80
127
  }
81
128
  /** Options from the specification's names and values (REQ-1001); those not named keep their defaults. */
82
129
  static of(init) {
@@ -86,6 +133,11 @@ export class TextOptions {
86
133
  const o = new TextOptions();
87
134
  if (init === undefined || init === null)
88
135
  return o;
136
+ if (init.comments !== undefined && init.include !== undefined && !bool('comments', init.comments, 'REQ-504')
137
+ && includeItems(init.include).includes('comments')) {
138
+ throw new TextOptionError(`comments: false and an include naming comments say opposite things; drop comments from include, `
139
+ + `which is a deprecated spelling of comments: true (WD REQ-504)`, 'comments', 'REQ-504', 'invalid');
140
+ }
89
141
  for (const [name, value] of Object.entries(init)) {
90
142
  if (value === undefined)
91
143
  continue;
@@ -96,9 +148,38 @@ export class TextOptions {
96
148
  }
97
149
  return o;
98
150
  }
99
- /** Sets one option by its specification name and value; throws `TextOptionError` for one it does not define. */
151
+ /**
152
+ * Sets one option by its specification name and value; throws `TextOptionError` for one it does not define. An option set
153
+ * by name is the caller's: a profile, applied before or after, leaves it (REQ-1002). A member assigned directly is not
154
+ * recorded so, and a profile applied after the assignment overrides it.
155
+ */
100
156
  set(name, value) {
101
157
  const n = (name !== null && name !== void 0 ? name : '').trim();
158
+ if (n === 'profile')
159
+ return this.profile(value === undefined || value === null ? undefined : profileOf(value));
160
+ this.apply(n, name, value);
161
+ this.explicit.add(n);
162
+ return this;
163
+ }
164
+ /**
165
+ * Applies a profile (REQ-1002): its values for every option the caller has not set by name; an option the caller sets
166
+ * afterwards overrides it too. Undefined clears the name, leaving the values. See `WORD_TEXT_PROFILE`.
167
+ */
168
+ profile(p) {
169
+ this.profileName = p;
170
+ if (p === undefined)
171
+ return this;
172
+ for (const [n, value] of Object.entries(WORD_TEXT_PROFILE))
173
+ if (!this.explicit.has(n))
174
+ this.apply(n, n, value);
175
+ return this;
176
+ }
177
+ /** The profile applied, or undefined. */
178
+ get profileApplied() {
179
+ return this.profileName;
180
+ }
181
+ /** Sets one option without recording it as the caller's (a profile's value). */
182
+ apply(n, name, value) {
102
183
  switch (n) {
103
184
  case 'view':
104
185
  this.view = viewOf(value);
@@ -130,6 +211,9 @@ export class TextOptions {
130
211
  case 'toc':
131
212
  this.toc = bool(n, value, 'REQ-520');
132
213
  break;
214
+ case 'drop_caps':
215
+ this.dropCaps = choice(n, value, ['join', 'asis'], 'REQ-521');
216
+ break;
133
217
  case 'placeholders':
134
218
  this.placeholders = bool(n, value, 'REQ-508');
135
219
  break;
@@ -160,6 +244,12 @@ export class TextOptions {
160
244
  case 'symbols':
161
245
  this.symbols = choice(n, value, ['asis', 'unicode'], 'REQ-601');
162
246
  break;
247
+ case 'small_caps':
248
+ this.smallCaps = choice(n, value, ['asis', 'upper'], 'REQ-607');
249
+ break;
250
+ case 'default_language':
251
+ this.defaultLanguage = languageTag(n, value, 'REQ-607');
252
+ break;
163
253
  case 'math':
164
254
  this.math = choice(n, value, ['latex', 'unicodemath'], 'REQ-604');
165
255
  break;
@@ -178,34 +268,51 @@ export class TextOptions {
178
268
  case 'warnings':
179
269
  this.warnings = bool(n, value, 'REQ-801');
180
270
  break;
271
+ case 'repair':
272
+ this.repair = choice(n, value, ['refuse', 'word', 'all'], 'REQ-207');
273
+ break;
274
+ case 'duplicate_entries':
275
+ // REQ-206's MAY, not offered (CR-031 D1): one switch, whose word reads the first copy
276
+ throw new TextOptionError("duplicate_entries isn't offered here: load with repair: 'word', which reads the first entry of each name "
277
+ + '(WD REQ-206, REQ-207)', 'duplicate_entries', 'REQ-206', 'not_implemented');
181
278
  default:
182
279
  throw new TextOptionError(`Unknown text option '${String(name)}'; the options are ${TEXT_OPTION_NAMES.join(', ')} (WD REQ-1001)`, String(name), 'REQ-1001', 'unknown');
183
280
  }
184
- return this;
185
281
  }
186
282
  setInclude(value) {
187
283
  this.includeSet.clear();
188
- const items = Array.isArray(value) ? value
189
- : value === undefined || value === null ? [] : String(value).split(/[,\s]+/).filter((s) => s !== '');
190
- for (const item of items)
191
- this.includeSet.add(choice('include', item, INCLUDES, 'REQ-501'));
284
+ this.addStories(includeItems(value));
285
+ }
286
+ /** `comments` never stays in `include`: it is the deprecated spelling of `comments: true`, and the caller's option as that is. */
287
+ addStories(stories) {
288
+ for (const s of stories) {
289
+ if (s !== 'comments') {
290
+ this.includeSet.add(s);
291
+ continue;
292
+ }
293
+ this.commentsOption = true;
294
+ this.explicit.add('comments');
295
+ if (!includeCommentsNoticed)
296
+ log.warn('The text option include: comments is deprecated: use comments: true (WD 0.91, CR-012 section 29)');
297
+ includeCommentsNoticed = true;
298
+ }
192
299
  }
193
300
  /** Adds stories to `include` (docx4j's builder `include(Include...)`). */
194
301
  include(...stories) {
195
- for (const s of stories)
196
- this.includeSet.add(choice('include', s, INCLUDES, 'REQ-501'));
302
+ this.addStories(stories.map((s) => choice('include', s, INCLUDES, 'REQ-501')));
303
+ this.explicit.add('include');
197
304
  return this;
198
305
  }
199
- /** The stories `include` names; `comments: true` adds `comments`. */
306
+ /** The stories in scope: those `include` names, and `comments` where `comments` is true. */
200
307
  get includes() {
201
308
  const out = new Set(this.includeSet);
202
309
  if (this.commentsOption)
203
310
  out.add('comments');
204
311
  return out;
205
312
  }
206
- /** `comments: true` or `include: comments`. */
313
+ /** `comments: true`, the one setting (REQ-504, WD 0.91). */
207
314
  get comments() {
208
- return this.commentsOption || this.includeSet.has('comments');
315
+ return this.commentsOption;
209
316
  }
210
317
  set comments(value) {
211
318
  this.commentsOption = value;
@@ -215,18 +322,21 @@ export class TextOptions {
215
322
  const o = new TextOptions();
216
323
  Object.assign(o, this);
217
324
  o.includeSet = new Set(this.includeSet);
325
+ o.explicit = new Set(this.explicit);
218
326
  return o;
219
327
  }
220
328
  /** The options as the specification names them, with their values, in section 10's order. */
221
329
  toMap() {
330
+ var _a;
222
331
  return {
223
332
  view: this.view, include: [...this.includeSet], text_boxes: this.textBoxes, notes: this.notes,
224
333
  note_references: this.noteReferences, comments: this.commentsOption, hidden: this.hidden,
225
- field_codes: this.fieldCodes, fields: this.fields, toc: this.toc, placeholders: this.placeholders,
334
+ field_codes: this.fieldCodes, fields: this.fields, toc: this.toc, drop_caps: this.dropCaps, placeholders: this.placeholders,
226
335
  bindings: this.bindings, list_labels: this.listLabels, charts: this.charts, smartart: this.smartart,
227
336
  embedded: this.embedded, altchunks: this.altchunks, alt_text: this.altText, metadata: this.metadata,
228
- symbols: this.symbols, math: this.math, tables: this.tables, markup_detail: this.markupDetail,
229
- page_markers: this.pageMarkers, layout: this.layout, warnings: this.warnings,
337
+ symbols: this.symbols, small_caps: this.smallCaps, default_language: this.defaultLanguage, math: this.math, tables: this.tables, markup_detail: this.markupDetail,
338
+ page_markers: this.pageMarkers, layout: this.layout, warnings: this.warnings, repair: this.repair,
339
+ profile: (_a = this.profileName) !== null && _a !== void 0 ? _a : null,
230
340
  };
231
341
  }
232
342
  toJSON() {
@@ -251,6 +361,13 @@ export class TextOptions {
251
361
  }
252
362
  }
253
363
  }
364
+ /** A profile's name as the WD writes it (`word-text`), case-insensitively, a hyphen or an underscore. */
365
+ function profileOf(value) {
366
+ const s = String(value).trim();
367
+ if (s.toLowerCase().replace(/_/g, '-') === 'word-text')
368
+ return 'word-text';
369
+ throw new TextOptionError(`profile: '${s}' is not one of word-text (WD REQ-1002)`, 'profile', 'REQ-1002', 'invalid');
370
+ }
254
371
  function viewOf(value) {
255
372
  const n = String(value !== null && value !== void 0 ? value : '').trim().toLowerCase();
256
373
  if (n === 'current')
@@ -269,6 +386,30 @@ function bool(name, value, statement) {
269
386
  return false;
270
387
  throw new TextOptionError(`${name}: '${String(value)}' is not true or false (WD REQ-1001)`, name, statement, 'invalid');
271
388
  }
389
+ /**
390
+ * RFC 5646's `Language-Tag` (section 2.1): a `langtag`, a private-use tag or a grandfathered one, case-insensitively. A
391
+ * tag this grammar accepts is well formed (section 2.2.9); whether its subtags are registered is not asked.
392
+ */
393
+ const LANGUAGE_TAG = new RegExp('^(?:'
394
+ + '(?:[a-z]{2,3}(?:-[a-z]{3}){0,3}|[a-z]{4}|[a-z]{5,8})' // language, with up to three extlang
395
+ + '(?:-[a-z]{4})?' // script
396
+ + '(?:-(?:[a-z]{2}|[0-9]{3}))?' // region
397
+ + '(?:-(?:[a-z0-9]{5,8}|[0-9][a-z0-9]{3}))*' // variants
398
+ + '(?:-[a-wyz0-9](?:-[a-z0-9]{2,8})+)*' // extensions
399
+ + '(?:-x(?:-[a-z0-9]{1,8})+)?' // private use
400
+ + '|x(?:-[a-z0-9]{1,8})+'
401
+ + '|en-GB-oed|i-(?:ami|bnn|default|enochian|hak|klingon|lux|mingo|navajo|pwn|tao|tay|tsu)|sgn-(?:BE-FR|BE-NL|CH-DE)'
402
+ + ')$', 'i');
403
+ /**
404
+ * A BCP 47 tag as given, trimmed; one RFC 5646's grammar refuses is refused, so that a mistyped tag cannot select the
405
+ * default unnoticed (CR-012 section 24.8, D2).
406
+ */
407
+ function languageTag(name, value, statement) {
408
+ const s = typeof value === 'string' ? value.trim() : '';
409
+ if (LANGUAGE_TAG.test(s))
410
+ return s;
411
+ throw new TextOptionError(`${name}: '${String(value)}' is not a well-formed BCP 47 language tag, such as en-US or tr-TR (WD ${statement})`, name, statement, 'invalid');
412
+ }
272
413
  function choice(name, value, values, statement) {
273
414
  const s = String(value !== null && value !== void 0 ? value : '').trim().toLowerCase();
274
415
  const found = values.find((v) => v === s);