@docx4j/core-ts 0.5.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 (207) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +92 -4
  3. package/dist/html/convert.mjs +2 -1
  4. package/dist/html/elements.mjs +2 -1
  5. package/dist/model/color/ColorMath.d.mts +29 -0
  6. package/dist/model/color/ColorMath.mjs +146 -0
  7. package/dist/model/color/ColorTables.d.mts +6 -0
  8. package/dist/model/color/ColorTables.mjs +83 -0
  9. package/dist/model/color/DrawingMLColors.d.mts +52 -0
  10. package/dist/model/color/DrawingMLColors.mjs +374 -0
  11. package/dist/model/color/ResolvedColor.d.mts +36 -0
  12. package/dist/model/color/ResolvedColor.mjs +65 -0
  13. package/dist/model/color/SpreadsheetColors.d.mts +36 -0
  14. package/dist/model/color/SpreadsheetColors.mjs +84 -0
  15. package/dist/model/color/StyleFill.d.mts +28 -0
  16. package/dist/model/color/StyleFill.mjs +21 -0
  17. package/dist/model/color/ThemeColors.d.mts +86 -0
  18. package/dist/model/color/ThemeColors.mjs +304 -0
  19. package/dist/model/color/WordColors.d.mts +71 -0
  20. package/dist/model/color/WordColors.mjs +121 -0
  21. package/dist/model/color/index.d.mts +6 -0
  22. package/dist/model/color/index.mjs +30 -0
  23. package/dist/model/content/Body.d.mts +145 -23
  24. package/dist/model/content/Body.mjs +507 -150
  25. package/dist/model/content/Comment.d.mts +23 -5
  26. package/dist/model/content/Comment.mjs +207 -26
  27. package/dist/model/content/ContentControl.d.mts +198 -19
  28. package/dist/model/content/ContentControl.mjs +672 -99
  29. package/dist/model/content/Font.d.mts +70 -17
  30. package/dist/model/content/Font.mjs +119 -36
  31. package/dist/model/content/InlinePicture.d.mts +11 -0
  32. package/dist/model/content/InlinePicture.mjs +21 -1
  33. package/dist/model/content/List.d.mts +6 -3
  34. package/dist/model/content/List.mjs +18 -8
  35. package/dist/model/content/Paragraph.d.mts +200 -14
  36. package/dist/model/content/Paragraph.mjs +898 -82
  37. package/dist/model/content/Range.d.mts +227 -12
  38. package/dist/model/content/Range.mjs +785 -59
  39. package/dist/model/content/ResolvedView.d.mts +104 -0
  40. package/dist/model/content/ResolvedView.mjs +596 -0
  41. package/dist/model/content/Table.d.mts +29 -3
  42. package/dist/model/content/Table.mjs +135 -49
  43. package/dist/model/content/TrackedChange.d.mts +174 -15
  44. package/dist/model/content/TrackedChange.mjs +734 -170
  45. package/dist/model/content/comments.d.mts +20 -6
  46. package/dist/model/content/comments.mjs +67 -57
  47. package/dist/model/content/generalException.d.mts +18 -0
  48. package/dist/model/content/generalException.mjs +24 -0
  49. package/dist/model/content/index.d.mts +10 -3
  50. package/dist/model/content/index.mjs +10 -2
  51. package/dist/model/content/mathText.d.mts +21 -0
  52. package/dist/model/content/mathText.mjs +267 -0
  53. package/dist/model/content/officeText.d.mts +27 -0
  54. package/dist/model/content/officeText.mjs +74 -0
  55. package/dist/model/content/ooxml.mjs +12 -1
  56. package/dist/model/content/outline.d.mts +5 -0
  57. package/dist/model/content/outline.mjs +13 -0
  58. package/dist/model/content/paraIds.d.mts +5 -0
  59. package/dist/model/content/paraIds.mjs +54 -0
  60. package/dist/model/content/placeholders.d.mts +110 -0
  61. package/dist/model/content/placeholders.mjs +253 -0
  62. package/dist/model/content/search.d.mts +74 -0
  63. package/dist/model/content/search.mjs +255 -9
  64. package/dist/model/content/spanEdits.d.mts +159 -0
  65. package/dist/model/content/spanEdits.mjs +728 -0
  66. package/dist/model/content/story.d.mts +47 -0
  67. package/dist/model/content/story.mjs +95 -0
  68. package/dist/model/content/tableColumns.d.mts +1 -1
  69. package/dist/model/content/tableColumns.mjs +108 -80
  70. package/dist/model/content/tableRevisions.d.mts +11 -3
  71. package/dist/model/content/tableRevisions.mjs +72 -42
  72. package/dist/model/content/tableRules.d.mts +30 -0
  73. package/dist/model/content/tableRules.mjs +102 -0
  74. package/dist/model/content/textBoxes.d.mts +18 -0
  75. package/dist/model/content/textBoxes.mjs +105 -0
  76. package/dist/model/content/trackedChangeFilter.d.mts +39 -0
  77. package/dist/model/content/trackedChangeFilter.mjs +81 -0
  78. package/dist/model/content/tracking.d.mts +63 -6
  79. package/dist/model/content/tracking.mjs +242 -22
  80. package/dist/model/content/tree.d.mts +172 -24
  81. package/dist/model/content/tree.mjs +328 -54
  82. package/dist/model/content/wordRange.d.mts +48 -0
  83. package/dist/model/content/wordRange.mjs +97 -0
  84. package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
  85. package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
  86. package/dist/model/customxml/XmlMapping.d.mts +32 -8
  87. package/dist/model/customxml/XmlMapping.mjs +64 -10
  88. package/dist/model/customxml/bindings.d.mts +33 -4
  89. package/dist/model/customxml/bindings.mjs +171 -45
  90. package/dist/model/customxml/index.d.mts +1 -0
  91. package/dist/model/customxml/index.mjs +1 -0
  92. package/dist/model/customxml/kinds.d.mts +8 -3
  93. package/dist/model/customxml/kinds.mjs +26 -5
  94. package/dist/model/customxml/opendope.d.mts +4 -1
  95. package/dist/model/customxml/opendope.mjs +9 -6
  96. package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
  97. package/dist/model/customxml/picturePlaceholder.mjs +32 -0
  98. package/dist/model/customxml/pictures.d.mts +4 -3
  99. package/dist/model/customxml/pictures.mjs +22 -8
  100. package/dist/model/customxml/storeItems.d.mts +57 -0
  101. package/dist/model/customxml/storeItems.mjs +122 -0
  102. package/dist/model/customxml/xhtml.mjs +23 -22
  103. package/dist/model/dateZone.d.mts +25 -0
  104. package/dist/model/dateZone.mjs +57 -0
  105. package/dist/model/index.d.mts +3 -0
  106. package/dist/model/index.mjs +5 -0
  107. package/dist/model/listnumbering/Emulator.d.mts +37 -5
  108. package/dist/model/listnumbering/Emulator.mjs +63 -9
  109. package/dist/model/properties/PropertyResolver.d.mts +74 -2
  110. package/dist/model/properties/PropertyResolver.mjs +133 -5
  111. package/dist/model/properties/catalogue.d.mts +19 -5
  112. package/dist/model/properties/catalogue.mjs +41 -15
  113. package/dist/model/properties/index.d.mts +1 -1
  114. package/dist/model/properties/log.d.mts +1 -1
  115. package/dist/model/properties/log.mjs +5 -5
  116. package/dist/model/properties/styleUtil.d.mts +3 -1
  117. package/dist/model/properties/styleUtil.mjs +20 -24
  118. package/dist/model/properties/table.mjs +4 -2
  119. package/dist/model/text/CaseMapping.d.mts +38 -0
  120. package/dist/model/text/CaseMapping.mjs +86 -0
  121. package/dist/model/text/Extractor.d.mts +349 -0
  122. package/dist/model/text/Extractor.mjs +2406 -0
  123. package/dist/model/text/LinkTargets.d.mts +45 -0
  124. package/dist/model/text/LinkTargets.mjs +170 -0
  125. package/dist/model/text/MarkdownExporter.d.mts +140 -0
  126. package/dist/model/text/MarkdownExporter.mjs +255 -0
  127. package/dist/model/text/PlainText.d.mts +29 -0
  128. package/dist/model/text/PlainText.mjs +542 -0
  129. package/dist/model/text/TextContext.d.mts +256 -0
  130. package/dist/model/text/TextContext.mjs +600 -0
  131. package/dist/model/text/TextOptions.d.mts +233 -0
  132. package/dist/model/text/TextOptions.mjs +419 -0
  133. package/dist/model/text/TextResult.d.mts +621 -0
  134. package/dist/model/text/TextResult.mjs +629 -0
  135. package/dist/model/text/Texts.d.mts +99 -0
  136. package/dist/model/text/Texts.mjs +187 -0
  137. package/dist/model/text/WmlToMarkdown.d.mts +120 -0
  138. package/dist/model/text/WmlToMarkdown.mjs +936 -0
  139. package/dist/model/text/caseMapping.generated.d.mts +7 -0
  140. package/dist/model/text/caseMapping.generated.mjs +214 -0
  141. package/dist/model/text/commonmark.d.mts +121 -0
  142. package/dist/model/text/commonmark.mjs +655 -0
  143. package/dist/model/text/index.d.mts +8 -0
  144. package/dist/model/text/index.mjs +9 -0
  145. package/dist/model/text/normalize.d.mts +8 -0
  146. package/dist/model/text/normalize.mjs +13 -0
  147. package/dist/model/text/outline.d.mts +4 -0
  148. package/dist/model/text/outline.mjs +71 -0
  149. package/dist/model/wordIntegers.d.mts +29 -0
  150. package/dist/model/wordIntegers.mjs +78 -0
  151. package/dist/office-js/document.mjs +15 -1
  152. package/dist/office-js/fragment.d.mts +7 -5
  153. package/dist/office-js/fragment.mjs +63 -14
  154. package/dist/office-js/proxy.d.mts +8 -0
  155. package/dist/office-js/proxy.mjs +29 -0
  156. package/dist/office-js/run.mjs +2 -0
  157. package/dist/office-js/supported.generated.mjs +16 -0
  158. package/dist/office-js/toApiScript.mjs +29 -12
  159. package/dist/opc/DirectoryPartStore.d.mts +6 -2
  160. package/dist/opc/DirectoryPartStore.mjs +11 -4
  161. package/dist/opc/FlatOpcPartStore.d.mts +4 -2
  162. package/dist/opc/FlatOpcPartStore.mjs +11 -8
  163. package/dist/opc/Load.d.mts +32 -0
  164. package/dist/opc/Load.mjs +115 -5
  165. package/dist/opc/PartStore.d.mts +34 -1
  166. package/dist/opc/PartStore.mjs +71 -8
  167. package/dist/opc/Save.d.mts +32 -0
  168. package/dist/opc/Save.mjs +110 -4
  169. package/dist/opc/ZipPartStore.d.mts +4 -2
  170. package/dist/opc/ZipPartStore.mjs +12 -7
  171. package/dist/opc/exceptions.d.mts +140 -0
  172. package/dist/opc/exceptions.mjs +108 -0
  173. package/dist/opc/index.d.mts +8 -5
  174. package/dist/opc/index.mjs +5 -3
  175. package/dist/opc/mce/preprocessor.d.mts +141 -5
  176. package/dist/opc/mce/preprocessor.mjs +119 -18
  177. package/dist/opc/mce/understood.d.mts +3 -11
  178. package/dist/opc/mce/understood.mjs +27 -23
  179. package/dist/opc/repair/breaks.d.mts +23 -0
  180. package/dist/opc/repair/breaks.mjs +288 -0
  181. package/dist/opc/repair/hosts.d.mts +12 -0
  182. package/dist/opc/repair/hosts.mjs +33 -0
  183. package/dist/opc/repair/mainRoot.d.mts +19 -0
  184. package/dist/opc/repair/mainRoot.mjs +168 -0
  185. package/dist/opc/repair/unknownElements.d.mts +8 -0
  186. package/dist/opc/repair/unknownElements.mjs +180 -0
  187. package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
  188. package/dist/opc/repair/wmlNames.generated.mjs +80 -0
  189. package/dist/opc/skipped.d.mts +50 -0
  190. package/dist/opc/skipped.mjs +140 -0
  191. package/dist/packages/OpcPackage.d.mts +110 -4
  192. package/dist/packages/OpcPackage.mjs +123 -7
  193. package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
  194. package/dist/packages/WordprocessingMLPackage.mjs +158 -21
  195. package/dist/packages/index.d.mts +1 -1
  196. package/dist/parts/DefaultXmlPart.mjs +2 -2
  197. package/dist/parts/Part.d.mts +14 -2
  198. package/dist/parts/RelationshipsPart.d.mts +15 -0
  199. package/dist/parts/RelationshipsPart.mjs +66 -1
  200. package/dist/parts/XmlPart.d.mts +63 -32
  201. package/dist/parts/XmlPart.mjs +240 -96
  202. package/dist/parts/wml/comments.mjs +30 -0
  203. package/dist/parts/wml/index.d.mts +12 -1
  204. package/dist/parts/wml/index.mjs +37 -1
  205. package/dist/xml/dom.d.mts +7 -0
  206. package/dist/xml/dom.mjs +18 -0
  207. package/package.json +2 -2
@@ -0,0 +1,542 @@
1
+ import { CaseMapping } from './CaseMapping.mjs';
2
+ /** The spaces for each 720-twip tab stop of indent under `layout: indent` (REQ-709). */
3
+ export const INDENT_SPACES = 4;
4
+ /** The note line before a table in the listed format (REQ-605, REQ-707). */
5
+ export const LISTED_FORMAT_NOTE = '[table: listed format]';
6
+ /**
7
+ * Plain text from the block model (WD section 7.1): each paragraph one line, a break one line more
8
+ * (REQ-603); the text exactly as the document holds it (REQ-602), U+000A between lines and after the last.
9
+ *
10
+ * Tables (REQ-605): a simple table a row a line, its cells a tab apart; any other in the listed format,
11
+ * after the note line `[table: listed format]`, a row a line as `Header: value; Header: value`. `tables:
12
+ * tsv` writes every table in the simple form, `tables: grid` as a pandoc grid table, its spans drawn.
13
+ *
14
+ * What the extractor adds follows the WD's bracket convention (REQ-707): `[n]` at a note's reference and
15
+ * at the start of the note; `[image: ...]` (or `[image, generated: ...]`) under `alt_text: true`; `[page
16
+ * n]` under `page_markers: true`; and under `metadata: true`, before the body, one line per kind of
17
+ * property that has any (REQ-515). In the markup view, insertions are `{++text++}`, deletions `{--text--}`
18
+ * and comments `{>>text<<}`, at their references with their replies after them (REQ-702, REQ-504); under
19
+ * `markup_detail` the marker's opening is followed by `author:` or `author, date:`.
20
+ *
21
+ * Under `layout: indent` (REQ-709) a paragraph outside a table begins with four spaces for each tab stop
22
+ * (720 twips) of its first line's indent, rounded to the nearest stop. docx4j `PlainText`.
23
+ */
24
+ export const PlainText = {
25
+ /** The plain text of a result. */
26
+ of(result) {
27
+ const w = new Writer(result);
28
+ if (result.options.metadata)
29
+ w.metadata(result.metadata);
30
+ for (const block of result.blocks) {
31
+ w.top(block);
32
+ w.out += '\n';
33
+ }
34
+ return w.out;
35
+ },
36
+ /** Whether a table is written in REQ-605's simple form under `tables: auto`. */
37
+ isSimple(table) {
38
+ return isSimple(table);
39
+ },
40
+ };
41
+ /**
42
+ * No merged or split cells, no nested table, one paragraph a cell. A cell is merged or split when it
43
+ * crosses a column edge another row has, or is in a vertical merge; a cell spanning grid columns that
44
+ * every row spans alike merges nothing. A cell's empty paragraphs don't count.
45
+ */
46
+ function isSimple(table) {
47
+ let edgesBefore;
48
+ for (const row of table.rows) {
49
+ const own = [...edges(row)].join(',');
50
+ if (edgesBefore !== undefined && edgesBefore !== own)
51
+ return false;
52
+ edgesBefore = own;
53
+ for (const cell of row.cells) {
54
+ if (cell.mergeContinue || cell.mergeRestart)
55
+ return false;
56
+ let paragraphs = 0;
57
+ for (const b of cell.blocks) {
58
+ if (b.kind !== 'PARAGRAPH')
59
+ return false;
60
+ if (b.runs.length > 0 || b.listLabel !== undefined)
61
+ paragraphs++;
62
+ }
63
+ if (paragraphs > 1)
64
+ return false;
65
+ }
66
+ }
67
+ return true;
68
+ }
69
+ /** A row's cell edges in grid columns, by gridSpan: 0, and each cell's end. */
70
+ function edges(row) {
71
+ const out = new Set([0]);
72
+ let col = 0;
73
+ for (const c of row.cells)
74
+ out.add((col += Math.max(1, c.gridSpan)));
75
+ return out;
76
+ }
77
+ /** The grid columns each cell of a row starts at, by gridSpan. */
78
+ function starts(row) {
79
+ const out = [];
80
+ let col = 0;
81
+ for (const c of row.cells) {
82
+ out.push(col);
83
+ col += Math.max(1, c.gridSpan);
84
+ }
85
+ return out;
86
+ }
87
+ /** The header rows: those marked `w:tblHeader`, else the first. */
88
+ function headerRows(rows) {
89
+ let n = 0;
90
+ while (n < rows.length && rows[n].header)
91
+ n++;
92
+ return n > 0 ? n : Math.min(1, rows.length);
93
+ }
94
+ /** The grid's width: the most grid columns a row spans. */
95
+ function width(rows) {
96
+ let w = 0;
97
+ for (const row of rows)
98
+ w = Math.max(w, row.cells.reduce((n, c) => n + Math.max(1, c.gridSpan), 0));
99
+ return w;
100
+ }
101
+ /** A row of one cell spanning every grid column: a title, or a divider such as "Part A". */
102
+ function fullWidth(row, gridWidth) {
103
+ return row.cells.length === 1 && Math.max(1, row.cells[0].gridSpan) === gridWidth;
104
+ }
105
+ /** The first header with text over a cell's grid columns. */
106
+ function header(headers, start, span) {
107
+ for (let g = start; g < start + span; g++) {
108
+ const h = headers.get(g);
109
+ if (h !== undefined && h !== '')
110
+ return h;
111
+ }
112
+ return undefined;
113
+ }
114
+ function label(head, value) {
115
+ return head === undefined || head === '' ? value : `${head}: ${value}`;
116
+ }
117
+ class Writer {
118
+ constructor(result) {
119
+ this.result = result;
120
+ this.out = '';
121
+ this.options = result.options;
122
+ }
123
+ // --- the metadata block (REQ-515) ---------------------------------------------------------------
124
+ metadata(metadata) {
125
+ this.group('core properties', metadata.core);
126
+ this.group('application properties', metadata.app);
127
+ this.group('custom properties', metadata.custom);
128
+ }
129
+ group(name, properties) {
130
+ if (typeof properties !== 'object' || properties === null)
131
+ return;
132
+ const entries = Object.entries(properties);
133
+ if (entries.length === 0)
134
+ return;
135
+ this.out += `[${name}: ${entries.map(([k, v]) => `${k}: ${String(v)}`).join('; ')}]\n`;
136
+ }
137
+ // --- blocks -----------------------------------------------------------------------------------
138
+ /** A block of the story: a paragraph with its indent, a table, a chart. */
139
+ top(block) {
140
+ if (block.kind === 'PARAGRAPH' && this.options.layout === 'indent')
141
+ this.indent(block);
142
+ this.block(block);
143
+ }
144
+ indent(block) {
145
+ var _a, _b, _c;
146
+ const twips = ((_a = block.indentLeft) !== null && _a !== void 0 ? _a : 0) + ((_b = block.indentFirstLine) !== null && _b !== void 0 ? _b : 0) - ((_c = block.indentHanging) !== null && _c !== void 0 ? _c : 0);
147
+ const stops = Math.round(twips / 720); // Java's Math.round: half up
148
+ for (let i = 0; i < stops * INDENT_SPACES; i++)
149
+ this.out += ' ';
150
+ }
151
+ block(block) {
152
+ if (block.kind === 'TABLE')
153
+ this.table(block);
154
+ else if (block.kind === 'CHART')
155
+ this.chart(block);
156
+ else
157
+ this.paragraph(block);
158
+ }
159
+ chart(block) {
160
+ let any = false;
161
+ if (block.chart) {
162
+ this.out += block.chart.note;
163
+ any = true;
164
+ }
165
+ if (block.chartTitle) {
166
+ if (any)
167
+ this.out += '\n';
168
+ this.out += block.chartTitle;
169
+ any = true;
170
+ }
171
+ const lines = [];
172
+ if (block.chartHeader.length > 0)
173
+ lines.push(block.chartHeader);
174
+ lines.push(...block.chartRows);
175
+ for (const line of lines) {
176
+ if (any)
177
+ this.out += '\n';
178
+ this.out += line.join('\t');
179
+ any = true;
180
+ }
181
+ }
182
+ paragraph(block) {
183
+ if (block.listLabel !== undefined)
184
+ this.out += block.listLabel;
185
+ const runs = block.runs;
186
+ let i = 0;
187
+ while (i < runs.length) {
188
+ const revision = runs[i].revision;
189
+ let j = i;
190
+ while (j < runs.length && this.sameMarker(revision, runs[j].revision))
191
+ j++;
192
+ if (revision) {
193
+ this.out += revision.type === 'INSERTION' ? '{++' : '{--';
194
+ this.detail(revision.author, revision.date);
195
+ }
196
+ for (let k = i; k < j; k++)
197
+ this.run(runs[k]);
198
+ if (revision)
199
+ this.out += revision.type === 'INSERTION' ? '++}' : '--}';
200
+ i = j;
201
+ }
202
+ }
203
+ /** Runs under one marker: the same type, and the same author and date where the detail shows them. */
204
+ sameMarker(a, b) {
205
+ if (a === undefined || b === undefined)
206
+ return a === b;
207
+ if (a.type !== b.type)
208
+ return false;
209
+ switch (this.options.markupDetail) {
210
+ case 'author': return a.author === b.author;
211
+ case 'author_date': return a.author === b.author && a.date === b.date;
212
+ default: return true;
213
+ }
214
+ }
215
+ detail(author, date) {
216
+ switch (this.options.markupDetail) {
217
+ case 'author':
218
+ this.out += `${author !== null && author !== void 0 ? author : ''}: `;
219
+ break;
220
+ case 'author_date':
221
+ this.out += `${author !== null && author !== void 0 ? author : ''}${date === undefined ? '' : `, ${date}`}: `;
222
+ break; // a mark with no date: its author alone (REQ-702)
223
+ default:
224
+ }
225
+ }
226
+ run(run) {
227
+ switch (run.kind) {
228
+ case 'TEXT': // w:caps in capitals, by the run's language (REQ-607)
229
+ this.out += CaseMapping.written(run, this.options);
230
+ break;
231
+ case 'FIELD_CODE':
232
+ case 'LIST_LABEL':
233
+ this.out += run.text;
234
+ break;
235
+ case 'NOTE_REFERENCE':
236
+ if (this.options.noteReferences && this.options.notes && run.noteNumber > 0)
237
+ this.out += `[${run.noteNumber}]`;
238
+ break;
239
+ case 'NOTE_MARK':
240
+ if (run.noteNumber > 0)
241
+ this.out += `[${run.noteNumber}]`;
242
+ break;
243
+ case 'COMMENT_REFERENCE': {
244
+ const comment = run.commentId === undefined ? undefined : this.result.comments.get(run.commentId);
245
+ if (!comment || (comment.parentId !== undefined && this.result.comments.has(comment.parentId)))
246
+ break;
247
+ this.comment(comment);
248
+ for (const reply of comment.replies)
249
+ this.comment(reply);
250
+ break;
251
+ }
252
+ case 'IMAGE': {
253
+ const d = run.description;
254
+ if (!this.options.altText || !d)
255
+ break;
256
+ this.out += `${d.provenance === 'GENERATED' ? '[image, generated: ' : '[image: '}${d.text}]`;
257
+ break;
258
+ }
259
+ case 'PAGE_MARKER':
260
+ if (this.options.pageMarkers)
261
+ this.out += `[page ${run.pageNumber}]`;
262
+ break;
263
+ default:
264
+ }
265
+ }
266
+ comment(comment) {
267
+ this.out += '{>>';
268
+ this.detail(comment.author, comment.date);
269
+ this.out += `${CaseMapping.written(comment, this.options)}<<}`;
270
+ }
271
+ /** A block written on its own, for a table cell's value. */
272
+ text(block) {
273
+ const saved = this.out;
274
+ this.out = '';
275
+ try {
276
+ this.block(block);
277
+ return this.out;
278
+ }
279
+ finally {
280
+ this.out = saved;
281
+ }
282
+ }
283
+ // --- tables (REQ-605) -------------------------------------------------------------------------
284
+ table(table) {
285
+ let form = this.options.tables;
286
+ if (table.simpleForm)
287
+ form = 'tsv';
288
+ if (form === 'grid')
289
+ this.grid(table);
290
+ else if (form === 'tsv' || isSimple(table))
291
+ this.tabSeparated(table);
292
+ else
293
+ this.listed(table);
294
+ }
295
+ tabSeparated(table) {
296
+ const rows = table.rows;
297
+ for (let r = 0; r < rows.length; r++) {
298
+ if (r > 0)
299
+ this.out += '\n';
300
+ const cells = rows[r].cells;
301
+ for (let c = 0; c < cells.length; c++) {
302
+ if (c > 0)
303
+ this.out += '\t';
304
+ this.out += this.values(cells[c]).join(' ');
305
+ }
306
+ }
307
+ }
308
+ /**
309
+ * The listed format (REQ-605). Every cell is labelled by the header over its first grid column, or the
310
+ * first of its columns' headers that has text; several header rows' texts are joined ` / `; a cell under
311
+ * a header with no text is its value alone. A row whose one cell spans every grid column is that cell's
312
+ * text alone, and labels nothing. A cell with no value is left out; a vertical merge's value is on every
313
+ * row it covers. Labelled cells are `; ` apart; in a table with no labels cells are a tab apart.
314
+ */
315
+ listed(table) {
316
+ var _a;
317
+ this.out += LISTED_FORMAT_NOTE;
318
+ const rows = table.rows;
319
+ const gridWidth = width(rows);
320
+ const headerCount = headerRows(rows);
321
+ // a table of header rows only is written unlabelled, its rows as body rows
322
+ const headersOnly = headerCount >= rows.length;
323
+ const headers = new Map();
324
+ if (!headersOnly) {
325
+ for (let r = 0; r < headerCount; r++) {
326
+ const row = rows[r];
327
+ if (fullWidth(row, gridWidth)) {
328
+ const text = this.value(row.cells[0]);
329
+ if (text !== '')
330
+ this.out += `\n${text}`;
331
+ continue;
332
+ }
333
+ const at = starts(row);
334
+ for (let c = 0; c < at.length; c++) {
335
+ const cell = row.cells[c];
336
+ const text = this.value(cell);
337
+ if (text === '')
338
+ continue;
339
+ for (let g = at[c]; g < at[c] + Math.max(1, cell.gridSpan); g++) {
340
+ const h = headers.get(g);
341
+ headers.set(g, h === undefined ? text : `${h} / ${text}`);
342
+ }
343
+ }
344
+ }
345
+ }
346
+ const labelled = headers.size > 0;
347
+ const body = headersOnly ? rows : rows.slice(headerCount);
348
+ const restarts = new Map();
349
+ for (const row of body) {
350
+ this.out += '\n';
351
+ if (fullWidth(row, gridWidth)) {
352
+ this.out += this.value(row.cells[0]);
353
+ continue;
354
+ }
355
+ const at = starts(row);
356
+ const parts = [];
357
+ for (let c = 0; c < at.length; c++) {
358
+ const cell = row.cells[c];
359
+ let value;
360
+ if (cell.mergeContinue) {
361
+ value = (_a = restarts.get(at[c])) !== null && _a !== void 0 ? _a : '';
362
+ }
363
+ else {
364
+ value = this.value(cell);
365
+ if (cell.mergeRestart)
366
+ restarts.set(at[c], value);
367
+ }
368
+ if (value === '')
369
+ continue;
370
+ parts.push(labelled ? label(header(headers, at[c], Math.max(1, cell.gridSpan)), value) : value);
371
+ }
372
+ this.out += parts.join(labelled ? '; ' : '\t');
373
+ }
374
+ }
375
+ /** A cell's paragraphs, a nested table's included, `; ` apart, empty ones left out. */
376
+ value(cell) {
377
+ return this.values(cell).join('; ');
378
+ }
379
+ values(cell, out = []) {
380
+ for (const b of cell.blocks) {
381
+ if (b.kind === 'TABLE') {
382
+ for (const r of b.rows)
383
+ for (const c of r.cells)
384
+ this.values(c, out);
385
+ }
386
+ else {
387
+ const s = this.text(b);
388
+ if (s !== '')
389
+ out.push(s);
390
+ }
391
+ }
392
+ return out;
393
+ }
394
+ // --- pandoc grid tables -----------------------------------------------------------------------
395
+ grid(table) {
396
+ for (const line of this.gridLines(table)) {
397
+ if (this.out.length > 0 && !this.out.endsWith('\n'))
398
+ this.out += '\n';
399
+ this.out += line;
400
+ }
401
+ }
402
+ gridLines(table) {
403
+ var _a;
404
+ const rows = table.rows;
405
+ const placed = [];
406
+ const at = [];
407
+ // the grid's columns are those some row's cell edges mark, so a span every row shares draws as one column
408
+ const union = new Set();
409
+ for (const row of rows)
410
+ for (const e of edges(row))
411
+ union.add(e);
412
+ const edgeList = [...union].sort((a, b) => a - b);
413
+ const columns = edgeList.length - 1;
414
+ if (columns <= 0)
415
+ return [];
416
+ const open = new Map();
417
+ for (let r = 0; r < rows.length; r++) {
418
+ at[r] = new Array(columns).fill(undefined);
419
+ const row = rows[r];
420
+ const begin = starts(row);
421
+ for (let c = 0; c < begin.length; c++) {
422
+ const cell = row.cells[c];
423
+ const first = edgeList.indexOf(begin[c]);
424
+ const span = edgeList.indexOf(begin[c] + Math.max(1, cell.gridSpan)) - first;
425
+ let p;
426
+ const opened = open.get(first);
427
+ if (cell.mergeContinue && opened !== undefined && opened.span === span) {
428
+ p = opened;
429
+ p.rowSpan++;
430
+ }
431
+ else {
432
+ p = { row: r, col: first, span, rowSpan: 1, lines: this.cellLines(cell) };
433
+ placed.push(p);
434
+ if (cell.mergeRestart)
435
+ open.set(first, p);
436
+ else
437
+ open.delete(first);
438
+ }
439
+ for (let g = first; g < first + span && g < columns; g++)
440
+ at[r][g] = p;
441
+ }
442
+ }
443
+ // column widths: single-column cells first, then spans widen their last column
444
+ const widths = new Array(columns).fill(3);
445
+ for (const p of placed)
446
+ if (p.span === 1)
447
+ for (const l of p.lines)
448
+ widths[p.col] = Math.max(widths[p.col], l.length);
449
+ for (const p of placed) {
450
+ if (p.span === 1)
451
+ continue;
452
+ const last = Math.min(columns, p.col + p.span) - 1;
453
+ let have = 0;
454
+ for (let g = p.col; g <= last; g++)
455
+ have += widths[g];
456
+ have += 3 * (last - p.col);
457
+ for (const l of p.lines)
458
+ if (l.length > have) {
459
+ widths[last] = widths[last] + (l.length - have);
460
+ have = l.length;
461
+ }
462
+ }
463
+ // row heights: a cell's lines over the rows it spans
464
+ const heights = new Array(rows.length).fill(1);
465
+ for (const p of placed)
466
+ if (p.rowSpan === 1)
467
+ heights[p.row] = Math.max(heights[p.row], p.lines.length);
468
+ for (const p of placed) {
469
+ if (p.rowSpan === 1)
470
+ continue;
471
+ let have = 0;
472
+ for (let r = p.row; r < p.row + p.rowSpan; r++)
473
+ have += heights[r];
474
+ if (p.lines.length > have)
475
+ heights[p.row + p.rowSpan - 1] = heights[p.row + p.rowSpan - 1] + (p.lines.length - have);
476
+ }
477
+ const headerCount = rows.length > 1 ? headerRows(rows) : 0;
478
+ const out = [border(undefined, at[0], widths, '-')];
479
+ const written = new Map();
480
+ for (let r = 0; r < rows.length; r++) {
481
+ for (let line = 0; line < heights[r]; line++) {
482
+ let l = '|';
483
+ let g = 0;
484
+ while (g < columns) {
485
+ const p = at[r][g];
486
+ const span = p === undefined ? 1 : Math.min(p.span, columns - g);
487
+ let w = 0;
488
+ for (let k = g; k < g + span; k++)
489
+ w += widths[k];
490
+ w += 3 * (span - 1);
491
+ let text = '';
492
+ if (p) {
493
+ const n = (_a = written.get(p)) !== null && _a !== void 0 ? _a : 0;
494
+ if (n < p.lines.length)
495
+ text = p.lines[n];
496
+ written.set(p, n + 1);
497
+ }
498
+ l += ` ${text}${' '.repeat(Math.max(0, w - text.length))} |`;
499
+ g += span;
500
+ }
501
+ out.push(l);
502
+ }
503
+ if (r < rows.length - 1)
504
+ out.push(border(at[r], at[r + 1], widths, r === headerCount - 1 ? '=' : '-'));
505
+ }
506
+ out.push(border(at[rows.length - 1], undefined, widths, '-'));
507
+ return out;
508
+ }
509
+ /** A cell's lines: each paragraph's lines, a blank line between paragraphs, a nested table drawn as a grid. */
510
+ cellLines(cell) {
511
+ const lines = [];
512
+ for (const b of cell.blocks) {
513
+ let own;
514
+ if (b.kind === 'TABLE') {
515
+ own = this.gridLines(b);
516
+ }
517
+ else {
518
+ const s = this.text(b);
519
+ if (s === '')
520
+ continue;
521
+ own = s.split('\n');
522
+ }
523
+ if (lines.length > 0)
524
+ lines.push('');
525
+ lines.push(...own);
526
+ }
527
+ return lines;
528
+ }
529
+ }
530
+ /** The border between two rows: open where a cell spans both. */
531
+ function border(above, below, widths, fill) {
532
+ let l = '';
533
+ for (let g = 0; g < widths.length; g++) {
534
+ const through = above !== undefined && below !== undefined && above[g] !== undefined && above[g] === below[g];
535
+ const joinLeft = g > 0 && through && above[g - 1] === above[g];
536
+ l += g === 0 ? (through ? '|' : '+') : joinLeft ? ' ' : '+';
537
+ l += (through ? ' ' : fill).repeat(widths[g] + 2);
538
+ }
539
+ const lastColumn = widths.length - 1;
540
+ const throughLast = above !== undefined && below !== undefined && above[lastColumn] !== undefined && above[lastColumn] === below[lastColumn];
541
+ return l + (throughLast ? '|' : '+');
542
+ }