@trebco/treb 23.6.5 → 25.0.0-rc2

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 (217) hide show
  1. package/.eslintignore +8 -0
  2. package/.eslintrc.js +164 -0
  3. package/README-shadow-DOM.md +88 -0
  4. package/README.md +37 -130
  5. package/api-config.json +29 -0
  6. package/api-generator/api-generator-types.ts +82 -0
  7. package/api-generator/api-generator.ts +1172 -0
  8. package/api-generator/package.json +3 -0
  9. package/build/treb-spreadsheet.mjs +14 -0
  10. package/{treb.d.ts → build/treb.d.ts} +323 -271
  11. package/esbuild-custom-element.mjs +336 -0
  12. package/esbuild.js +305 -0
  13. package/package.json +49 -14
  14. package/treb-base-types/package.json +5 -0
  15. package/treb-base-types/src/api_types.ts +36 -0
  16. package/treb-base-types/src/area.ts +583 -0
  17. package/treb-base-types/src/basic_types.ts +45 -0
  18. package/treb-base-types/src/cell.ts +612 -0
  19. package/treb-base-types/src/cells.ts +1066 -0
  20. package/treb-base-types/src/color.ts +124 -0
  21. package/treb-base-types/src/import.ts +71 -0
  22. package/treb-base-types/src/index-standalone.ts +29 -0
  23. package/treb-base-types/src/index.ts +42 -0
  24. package/treb-base-types/src/layout.ts +47 -0
  25. package/treb-base-types/src/localization.ts +187 -0
  26. package/treb-base-types/src/rectangle.ts +145 -0
  27. package/treb-base-types/src/render_text.ts +72 -0
  28. package/treb-base-types/src/style.ts +545 -0
  29. package/treb-base-types/src/table.ts +109 -0
  30. package/treb-base-types/src/text_part.ts +54 -0
  31. package/treb-base-types/src/theme.ts +608 -0
  32. package/treb-base-types/src/union.ts +152 -0
  33. package/treb-base-types/src/value-type.ts +164 -0
  34. package/treb-base-types/style/resizable.css +59 -0
  35. package/treb-calculator/modern.tsconfig.json +11 -0
  36. package/treb-calculator/package.json +5 -0
  37. package/treb-calculator/src/calculator.ts +2546 -0
  38. package/treb-calculator/src/complex-math.ts +558 -0
  39. package/treb-calculator/src/dag/array-vertex.ts +198 -0
  40. package/treb-calculator/src/dag/graph.ts +951 -0
  41. package/treb-calculator/src/dag/leaf_vertex.ts +118 -0
  42. package/treb-calculator/src/dag/spreadsheet_vertex.ts +327 -0
  43. package/treb-calculator/src/dag/spreadsheet_vertex_base.ts +44 -0
  44. package/treb-calculator/src/dag/vertex.ts +352 -0
  45. package/treb-calculator/src/descriptors.ts +162 -0
  46. package/treb-calculator/src/expression-calculator.ts +1069 -0
  47. package/treb-calculator/src/function-error.ts +103 -0
  48. package/treb-calculator/src/function-library.ts +103 -0
  49. package/treb-calculator/src/functions/base-functions.ts +1214 -0
  50. package/treb-calculator/src/functions/checkbox.ts +164 -0
  51. package/treb-calculator/src/functions/complex-functions.ts +253 -0
  52. package/treb-calculator/src/functions/finance-functions.ts +399 -0
  53. package/treb-calculator/src/functions/information-functions.ts +102 -0
  54. package/treb-calculator/src/functions/matrix-functions.ts +182 -0
  55. package/treb-calculator/src/functions/sparkline.ts +335 -0
  56. package/treb-calculator/src/functions/statistics-functions.ts +350 -0
  57. package/treb-calculator/src/functions/text-functions.ts +298 -0
  58. package/treb-calculator/src/index.ts +27 -0
  59. package/treb-calculator/src/notifier-types.ts +59 -0
  60. package/treb-calculator/src/primitives.ts +428 -0
  61. package/treb-calculator/src/utilities.ts +305 -0
  62. package/treb-charts/package.json +5 -0
  63. package/treb-charts/src/chart-functions.ts +156 -0
  64. package/treb-charts/src/chart-types.ts +230 -0
  65. package/treb-charts/src/chart.ts +1288 -0
  66. package/treb-charts/src/index.ts +24 -0
  67. package/treb-charts/src/main.ts +37 -0
  68. package/treb-charts/src/rectangle.ts +52 -0
  69. package/treb-charts/src/renderer.ts +1841 -0
  70. package/treb-charts/src/util.ts +122 -0
  71. package/treb-charts/style/charts.scss +221 -0
  72. package/treb-charts/style/old-charts.scss +250 -0
  73. package/treb-embed/markup/layout.html +137 -0
  74. package/treb-embed/markup/toolbar.html +175 -0
  75. package/treb-embed/modern.tsconfig.json +25 -0
  76. package/treb-embed/src/custom-element/content-types.d.ts +18 -0
  77. package/treb-embed/src/custom-element/global.d.ts +11 -0
  78. package/treb-embed/src/custom-element/spreadsheet-constructor.ts +1228 -0
  79. package/treb-embed/src/custom-element/treb-global.ts +44 -0
  80. package/treb-embed/src/custom-element/treb-spreadsheet-element.ts +52 -0
  81. package/treb-embed/src/embedded-spreadsheet.ts +5358 -0
  82. package/treb-embed/src/index.ts +16 -0
  83. package/treb-embed/src/language-model.ts +41 -0
  84. package/treb-embed/src/options.ts +298 -0
  85. package/treb-embed/src/progress-dialog.ts +228 -0
  86. package/treb-embed/src/selection-state.ts +16 -0
  87. package/treb-embed/src/spinner.ts +42 -0
  88. package/treb-embed/src/toolbar-message.ts +96 -0
  89. package/treb-embed/src/types.ts +167 -0
  90. package/treb-embed/style/autocomplete.scss +103 -0
  91. package/treb-embed/style/dark-theme.scss +114 -0
  92. package/treb-embed/style/defaults.scss +36 -0
  93. package/treb-embed/style/dialog.scss +181 -0
  94. package/treb-embed/style/dropdown-select.scss +101 -0
  95. package/treb-embed/style/formula-bar.scss +193 -0
  96. package/treb-embed/style/grid.scss +374 -0
  97. package/treb-embed/style/layout.scss +424 -0
  98. package/treb-embed/style/mouse-mask.scss +67 -0
  99. package/treb-embed/style/note.scss +92 -0
  100. package/treb-embed/style/overlay-editor.scss +102 -0
  101. package/treb-embed/style/spinner.scss +92 -0
  102. package/treb-embed/style/tab-bar.scss +228 -0
  103. package/treb-embed/style/table.scss +80 -0
  104. package/treb-embed/style/theme-defaults.scss +444 -0
  105. package/treb-embed/style/toolbar.scss +416 -0
  106. package/treb-embed/style/tooltip.scss +68 -0
  107. package/treb-embed/style/treb-icons.scss +130 -0
  108. package/treb-embed/style/treb-spreadsheet-element.scss +20 -0
  109. package/treb-embed/style/z-index.scss +43 -0
  110. package/treb-export/docs/charts.md +68 -0
  111. package/treb-export/modern.tsconfig.json +19 -0
  112. package/treb-export/package.json +4 -0
  113. package/treb-export/src/address-type.ts +77 -0
  114. package/treb-export/src/base-template.ts +22 -0
  115. package/treb-export/src/column-width.ts +85 -0
  116. package/treb-export/src/drawing2/chart-template-components2.ts +389 -0
  117. package/treb-export/src/drawing2/chart2.ts +282 -0
  118. package/treb-export/src/drawing2/column-chart-template2.ts +521 -0
  119. package/treb-export/src/drawing2/donut-chart-template2.ts +296 -0
  120. package/treb-export/src/drawing2/drawing2.ts +355 -0
  121. package/treb-export/src/drawing2/embedded-image.ts +71 -0
  122. package/treb-export/src/drawing2/scatter-chart-template2.ts +555 -0
  123. package/treb-export/src/export-worker/export-worker.ts +99 -0
  124. package/treb-export/src/export-worker/index-modern.ts +22 -0
  125. package/treb-export/src/export2.ts +2204 -0
  126. package/treb-export/src/import2.ts +882 -0
  127. package/treb-export/src/relationship.ts +36 -0
  128. package/treb-export/src/shared-strings2.ts +128 -0
  129. package/treb-export/src/template-2.ts +22 -0
  130. package/treb-export/src/unescape_xml.ts +47 -0
  131. package/treb-export/src/workbook-sheet2.ts +182 -0
  132. package/treb-export/src/workbook-style2.ts +1285 -0
  133. package/treb-export/src/workbook-theme2.ts +88 -0
  134. package/treb-export/src/workbook2.ts +491 -0
  135. package/treb-export/src/xml-utils.ts +201 -0
  136. package/treb-export/template/base/[Content_Types].xml +2 -0
  137. package/treb-export/template/base/_rels/.rels +2 -0
  138. package/treb-export/template/base/docProps/app.xml +2 -0
  139. package/treb-export/template/base/docProps/core.xml +12 -0
  140. package/treb-export/template/base/xl/_rels/workbook.xml.rels +2 -0
  141. package/treb-export/template/base/xl/sharedStrings.xml +2 -0
  142. package/treb-export/template/base/xl/styles.xml +2 -0
  143. package/treb-export/template/base/xl/theme/theme1.xml +2 -0
  144. package/treb-export/template/base/xl/workbook.xml +2 -0
  145. package/treb-export/template/base/xl/worksheets/sheet1.xml +2 -0
  146. package/treb-export/template/base.xlsx +0 -0
  147. package/treb-format/package.json +8 -0
  148. package/treb-format/src/format.test.ts +213 -0
  149. package/treb-format/src/format.ts +942 -0
  150. package/treb-format/src/format_cache.ts +199 -0
  151. package/treb-format/src/format_parser.ts +723 -0
  152. package/treb-format/src/index.ts +25 -0
  153. package/treb-format/src/number_format_section.ts +100 -0
  154. package/treb-format/src/value_parser.ts +337 -0
  155. package/treb-grid/package.json +5 -0
  156. package/treb-grid/src/editors/autocomplete.ts +394 -0
  157. package/treb-grid/src/editors/autocomplete_matcher.ts +260 -0
  158. package/treb-grid/src/editors/formula_bar.ts +473 -0
  159. package/treb-grid/src/editors/formula_editor_base.ts +910 -0
  160. package/treb-grid/src/editors/overlay_editor.ts +511 -0
  161. package/treb-grid/src/index.ts +37 -0
  162. package/treb-grid/src/layout/base_layout.ts +2618 -0
  163. package/treb-grid/src/layout/grid_layout.ts +299 -0
  164. package/treb-grid/src/layout/rectangle_cache.ts +86 -0
  165. package/treb-grid/src/render/selection-renderer.ts +414 -0
  166. package/treb-grid/src/render/svg_header_overlay.ts +93 -0
  167. package/treb-grid/src/render/svg_selection_block.ts +187 -0
  168. package/treb-grid/src/render/tile_renderer.ts +2122 -0
  169. package/treb-grid/src/types/annotation.ts +216 -0
  170. package/treb-grid/src/types/border_constants.ts +34 -0
  171. package/treb-grid/src/types/clipboard_data.ts +31 -0
  172. package/treb-grid/src/types/data_model.ts +334 -0
  173. package/treb-grid/src/types/drag_mask.ts +81 -0
  174. package/treb-grid/src/types/grid.ts +7743 -0
  175. package/treb-grid/src/types/grid_base.ts +3644 -0
  176. package/treb-grid/src/types/grid_command.ts +470 -0
  177. package/treb-grid/src/types/grid_events.ts +124 -0
  178. package/treb-grid/src/types/grid_options.ts +97 -0
  179. package/treb-grid/src/types/grid_selection.ts +60 -0
  180. package/treb-grid/src/types/named_range.ts +369 -0
  181. package/treb-grid/src/types/scale-control.ts +202 -0
  182. package/treb-grid/src/types/serialize_options.ts +72 -0
  183. package/treb-grid/src/types/set_range_options.ts +52 -0
  184. package/treb-grid/src/types/sheet.ts +3099 -0
  185. package/treb-grid/src/types/sheet_types.ts +95 -0
  186. package/treb-grid/src/types/tab_bar.ts +464 -0
  187. package/treb-grid/src/types/tile.ts +59 -0
  188. package/treb-grid/src/types/update_flags.ts +75 -0
  189. package/treb-grid/src/util/dom_utilities.ts +44 -0
  190. package/treb-grid/src/util/fontmetrics2.ts +179 -0
  191. package/treb-grid/src/util/ua.ts +104 -0
  192. package/treb-logo.svg +18 -0
  193. package/treb-parser/package.json +5 -0
  194. package/treb-parser/src/csv-parser.ts +122 -0
  195. package/treb-parser/src/index.ts +25 -0
  196. package/treb-parser/src/md-parser.ts +526 -0
  197. package/treb-parser/src/parser-types.ts +397 -0
  198. package/treb-parser/src/parser.test.ts +298 -0
  199. package/treb-parser/src/parser.ts +2673 -0
  200. package/treb-utils/package.json +5 -0
  201. package/treb-utils/src/dispatch.ts +57 -0
  202. package/treb-utils/src/event_source.ts +147 -0
  203. package/treb-utils/src/ievent_source.ts +33 -0
  204. package/treb-utils/src/index.ts +31 -0
  205. package/treb-utils/src/measurement.ts +174 -0
  206. package/treb-utils/src/resizable.ts +160 -0
  207. package/treb-utils/src/scale.ts +137 -0
  208. package/treb-utils/src/serialize_html.ts +124 -0
  209. package/treb-utils/src/template.ts +70 -0
  210. package/treb-utils/src/validate_uri.ts +61 -0
  211. package/tsconfig.json +10 -0
  212. package/tsproject.json +30 -0
  213. package/util/license-plugin-esbuild.js +86 -0
  214. package/util/list-css-vars.sh +46 -0
  215. package/README-esm.md +0 -37
  216. package/treb-bundle.css +0 -2
  217. package/treb-bundle.mjs +0 -15
@@ -0,0 +1,1172 @@
1
+
2
+ import * as ts from 'typescript';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+
6
+ import type { Config, ReadTypeArgs } from './api-generator-types';
7
+
8
+ let config_file = './api-config.json';
9
+ for (let i = 0; i < process.argv.length; i++) {
10
+ if (process.argv[i] === '-c' || process.argv[i] === '--config') {
11
+ config_file = process.argv[++i];
12
+ }
13
+ }
14
+
15
+ // all files should be relative to the config file.
16
+ const config_dir = path.dirname(config_file);
17
+
18
+ let config: Config = {
19
+ root: '',
20
+ index: '',
21
+ package: '',
22
+ drop_types: [],
23
+ convert_to_any: [],
24
+ exclude_tags: [],
25
+ rename_types: {},
26
+ drop_generics: [],
27
+ map: {},
28
+ include: [],
29
+ flatten_enums: false,
30
+ };
31
+
32
+ let api_version = '';
33
+
34
+ const ReadConfigData = async (file: string) => {
35
+
36
+ const text = await fs.promises.readFile(file, {encoding: 'utf8'});
37
+ const obj = JSON.parse(text);
38
+ config = {
39
+ ...config,
40
+ ...obj,
41
+ };
42
+
43
+ if (config.package) {
44
+ const pkg = await fs.promises.readFile(path.join(config_dir, config.package), {encoding: 'utf8'});
45
+ const data = JSON.parse(pkg);
46
+ api_version = data.version.replace(/\.\d+$/, '');
47
+ console.info('v', api_version);
48
+ }
49
+
50
+ };
51
+
52
+ ///
53
+
54
+ const FlattenQualifiedName = (node: ts.QualifiedName): string[] => {
55
+
56
+ const stack: string[] = [];
57
+
58
+ if (ts.isIdentifier(node.left)) {
59
+ stack.push(node.left.escapedText.toString());
60
+ }
61
+ else {
62
+ stack.push(...FlattenQualifiedName(node.left));
63
+ }
64
+
65
+ stack.push(node.right.escapedText.toString());
66
+
67
+ return stack;
68
+
69
+ };
70
+
71
+ /*
72
+ const FlattenEntityName = (name: ts.EntityName, base?: string): string => {
73
+ if (ts.isIdentifier(name)) {
74
+ return name.escapedText.toString() + (base ? '.' + base : '');
75
+ }
76
+ base = name.right.escapedText.toString() + (base ? '.' + base : '');
77
+ return FlattenEntityName(name.left, base);
78
+ };
79
+ */
80
+
81
+ const GetDocTags = (node: ts.Node): string[] => {
82
+ const tags = ts.getAllJSDocTags(node, (tag: ts.JSDocTag): tag is ts.JSDocTag => true);
83
+ return tags.map(tag => {
84
+ return tag.tagName.escapedText as string;
85
+ });
86
+ }
87
+
88
+ /**
89
+ * when adding fake (synthetic) comments, the printer will add multiline
90
+ * comment markers \/* *\/. we need to remove them.
91
+ * @param text
92
+ */
93
+ function CleanComment(text: string): string {
94
+
95
+ if (/^\/\*/.test(text)) {
96
+ text = text.substring(2);
97
+ }
98
+ if (/\*\/$/.test(text)) {
99
+ text = text.substring(0, text.length - 2);
100
+ }
101
+
102
+ return text;
103
+ }
104
+
105
+ /**
106
+ *
107
+ * @param args
108
+ * @returns
109
+ */
110
+ function CleanTransformer<T extends ts.Node>(): ts.TransformerFactory<T> {
111
+
112
+ const rename_keys = Object.keys(config.rename_types);
113
+
114
+ /**
115
+ * flag indicates we're in an exported module. in this case, export is
116
+ * implicit so don't gate on that (otherwise we drop types that should be
117
+ * included).
118
+ */
119
+ let exported_module = false;
120
+
121
+ return context => {
122
+ const visit: ts.Visitor = node => {
123
+
124
+ const modifiers = (node.modifiers || []).map(member => {
125
+ return ts.SyntaxKind[member.kind];
126
+ });
127
+
128
+ const tags = GetDocTags(node);
129
+ const internal =
130
+ tags.some(test => config.exclude_tags.includes(test));
131
+
132
+ const exported = modifiers.includes('ExportKeyword');
133
+ const is_public = !(modifiers.includes('ProtectedKeyword') || modifiers.includes('PrivateKeyword'));
134
+
135
+ if (ts.isModuleDeclaration(node)
136
+ || ts.isClassDeclaration(node)
137
+ || ts.isInterfaceDeclaration(node)
138
+ || ts.isTypeAliasDeclaration(node)
139
+ || ts.isEnumDeclaration(node)) {
140
+
141
+ // FIXME: one of these declarations might be exported via
142
+ // its module, and not independently; in that case we might
143
+ // still need it.
144
+
145
+ if ((!exported && !exported_module) || internal) {
146
+ if (node.name && ts.isIdentifier(node.name)) {
147
+ // console.info('dropping', node.name.escapedText.toString());
148
+ }
149
+ return undefined;
150
+ }
151
+
152
+ let name = '';
153
+
154
+ if (node.name && ts.isIdentifier(node.name)) {
155
+ name = node.name.escapedText.toString();
156
+ // console.info('keeping', node.name.escapedText.toString());
157
+ }
158
+
159
+ if (ts.isModuleDeclaration(node)) {
160
+ exported_module = true;
161
+ const result = ts.visitEachChild(node, child => visit(child), context);
162
+ exported_module = false;
163
+ return result;
164
+ }
165
+
166
+ if (ts.isClassDeclaration(node)) {
167
+ if (config.drop_generics.includes(name)) {
168
+
169
+ const tmp = ts.factory.updateClassDeclaration(node,
170
+ // node.decorators,
171
+ node.modifiers,
172
+ node.name,
173
+ [], // node.typeParameters,
174
+ node.heritageClauses,
175
+ node.members);
176
+
177
+ return ts.visitEachChild(tmp, child => visit(child), context);
178
+
179
+ }
180
+ }
181
+
182
+ if (ts.isEnumDeclaration(node)) {
183
+ if (config.flatten_enums) {
184
+
185
+ const alias = ts.factory.createTypeAliasDeclaration(
186
+ // node.decorators,
187
+ node.modifiers,
188
+ node.name,
189
+ [],
190
+ ts.factory.createUnionTypeNode(
191
+ node.members.map((member, i) => {
192
+
193
+ if (member.initializer) {
194
+
195
+ if (ts.isNumericLiteral(member.initializer)
196
+ || ts.isStringLiteral(member.initializer)) {
197
+ return ts.factory.createLiteralTypeNode(member.initializer);
198
+ }
199
+ }
200
+
201
+ // this may be wrong if there are some initializers [FIXME].
202
+ // what happens if you say
203
+ //
204
+ // enum X = { A, B = 3, C }
205
+ //
206
+ // it's probably something like resetting the automatic counter,
207
+ // which we could do. need to investigate though.
208
+
209
+ return ts.factory.createLiteralTypeNode(ts.factory.createNumericLiteral(i));
210
+
211
+ })
212
+ ));
213
+
214
+ if ((node as any).jsDoc) {
215
+
216
+ const source_text = node.getSourceFile().text;
217
+ const jsDoc: ts.JSDoc[] = (node as any).jsDoc;
218
+ const comment = CleanComment(source_text.substring(jsDoc[0].pos, jsDoc[0].end));
219
+
220
+ ts.addSyntheticLeadingComment(alias, ts.SyntaxKind.MultiLineCommentTrivia, comment);
221
+
222
+ }
223
+
224
+ return ts.visitEachChild(alias, child => visit(child), context);
225
+ }
226
+
227
+ }
228
+
229
+ if (ts.isInterfaceDeclaration(node)) {
230
+
231
+ // drop any internals
232
+
233
+ const tmp = ts.factory.updateInterfaceDeclaration(node,
234
+ // node.decorators,
235
+ node.modifiers,
236
+ node.name,
237
+ node.typeParameters,
238
+ node.heritageClauses,
239
+ node.members.filter(member => {
240
+
241
+ const member_tags = GetDocTags(member);
242
+ const internal = member_tags.some(test => config.exclude_tags.includes(test));
243
+
244
+ if (internal) {
245
+ return false;
246
+ }
247
+
248
+ return true;
249
+
250
+ }));
251
+
252
+ return ts.visitEachChild(tmp, child => visit(child), context);
253
+
254
+ }
255
+
256
+ }
257
+
258
+ if (ts.isIdentifier(node)) {
259
+ const name = node.escapedText.toString();
260
+ if (rename_keys.includes(name)) {
261
+ // console.info( ' ** ', name);
262
+ return ts.factory.createIdentifier(config.rename_types[name]);
263
+ }
264
+ }
265
+
266
+ if (ts.isMethodDeclaration(node)
267
+ || ts.isConstructorDeclaration(node)
268
+ || ts.isPropertyDeclaration(node)
269
+ || ts.isAccessor(node)) {
270
+
271
+ if (internal || !is_public) {
272
+ return undefined;
273
+ }
274
+
275
+ // FIXME: fix ctor parameters like method parameters
276
+
277
+ if (ts.isMethodDeclaration(node)) {
278
+
279
+ // UPDATE: convert to any -> handle return type
280
+
281
+ let return_type = node.type;
282
+ if (return_type && ts.isTypeReferenceNode(return_type)) {
283
+ if (ts.isIdentifier(return_type.typeName)) {
284
+ const name = return_type.typeName.escapedText.toString();
285
+ if (config.convert_to_any.includes(name)) {
286
+ return_type = ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword);
287
+ }
288
+ }
289
+ }
290
+
291
+ const tmp = ts.factory.updateMethodDeclaration(node,
292
+ // node.decorators,
293
+ node.modifiers,
294
+ node.asteriskToken,
295
+ node.name,
296
+ node.questionToken,
297
+ node.typeParameters,
298
+ node.parameters.filter((test, index) => {
299
+ if (test.type && ts.isTypeReferenceNode(test.type)) {
300
+ if (ts.isIdentifier(test.type.typeName)) {
301
+ const name = test.type.typeName.escapedText.toString();
302
+ if (config.drop_types.includes(name)) {
303
+
304
+ // we want to drop it. it must be optional and
305
+ // at the end... (of course that won't work if
306
+ // there are 2, but we don't have that problem atm).
307
+
308
+ // you could solve that by reversing the array, then
309
+ // you would only ever drop from the end. remember
310
+ // to reverse it again before returning.
311
+
312
+ if (test.questionToken && index === node.parameters.length - 1) {
313
+ return false;
314
+ }
315
+
316
+ }
317
+ }
318
+ }
319
+ return true;
320
+ }).map(test => {
321
+ if (test.type && ts.isTypeReferenceNode(test.type)) {
322
+ if (ts.isIdentifier(test.type.typeName)) {
323
+ const name = test.type.typeName.escapedText.toString();
324
+ if (config.convert_to_any.includes(name)) {
325
+
326
+ // convert this type to any
327
+
328
+ return ts.factory.createParameterDeclaration(
329
+ // test.decorators,
330
+ test.modifiers,
331
+ test.dotDotDotToken,
332
+ test.name,
333
+ test.questionToken,
334
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword),
335
+ // test.type,
336
+ test.initializer
337
+ );
338
+
339
+ }
340
+ }
341
+ }
342
+ return test;
343
+ }),
344
+ return_type, // node.type,
345
+ node.body);
346
+
347
+ return ts.visitEachChild(tmp, child => visit(child), context);
348
+
349
+ }
350
+ }
351
+
352
+ if (exported_module) {
353
+ if (ts.isVariableStatement(node)) {
354
+
355
+ const internal = tags.some(test => config.exclude_tags.includes(test));
356
+
357
+ if (internal || !is_public) {
358
+ return undefined;
359
+ }
360
+ }
361
+ }
362
+
363
+ return ts.visitEachChild(node, child => visit(child), context);
364
+ }
365
+ return node => ts.visitNode(node, visit);
366
+ };
367
+
368
+ }
369
+
370
+ /**
371
+ * collect all dependencies, recursively.
372
+ *
373
+ * FIXME: namespacing
374
+ * FIXME: collisions
375
+ *
376
+ */
377
+ function CollectDependencyTransformer<T extends ts.Node>(
378
+ args: ReadTypeArgs): ts.TransformerFactory<T> {
379
+
380
+ const containing_type: string[] = [''];
381
+
382
+ const AddFoundType = (name: string, text: string): boolean => {
383
+
384
+ if (config.drop_types.includes(name) || config.convert_to_any.includes(name)) {
385
+ return false; // aggressive
386
+ }
387
+
388
+ if (!args.types) {
389
+ args.found_types[name] = text;
390
+ }
391
+ else {
392
+ if (args.types.includes(name)) {
393
+ args.found_types[name] = text;
394
+ args.types = args.types.filter(test => test !== name);
395
+ }
396
+ else {
397
+ args.extra_types[name] = text;
398
+ }
399
+ }
400
+
401
+ return true;
402
+
403
+ };
404
+
405
+ const AddReferencedType = (name: string, track: number) => {
406
+
407
+ // we're trying to block intrinsic types here but this will still
408
+ // miss DOM types since they're not present in node... either we
409
+ // need a more robust mechanism or we should just not bother.
410
+
411
+ const check = (global as any)[name];
412
+ if (check) {
413
+ return;
414
+ }
415
+
416
+ if (config.drop_types.includes(name) || config.convert_to_any.includes(name)) {
417
+ return false; // aggressive
418
+ }
419
+
420
+ const container = containing_type[0];
421
+
422
+ const list = args.referenced_type_map[container] || [];
423
+ if (!list.includes(name)) {
424
+ list.push(name);
425
+ }
426
+ args.referenced_type_map[container] = list;
427
+
428
+ args.referenced_types[name] = (args.referenced_types[name]||0) + 1;
429
+ return true;
430
+
431
+ };
432
+
433
+ return context => {
434
+ const visit: ts.Visitor = node => {
435
+
436
+ const modifiers = ts.canHaveModifiers(node) ? (ts.getModifiers(node) || []).map(member => {
437
+ return ts.SyntaxKind[member.kind];
438
+ }) : [];
439
+
440
+ /*
441
+ const modifiers = (node.modifiers || []).map(member => {
442
+ return ts.SyntaxKind[member.kind];
443
+ });
444
+
445
+ if (modifiers.length) {
446
+ console.info({modifiers, modifiers2});
447
+ }
448
+ */
449
+
450
+ const tags = GetDocTags(node);
451
+
452
+ const internal =
453
+ tags.some(test => config.exclude_tags.includes(test));
454
+
455
+ const exported = modifiers.includes('ExportKeyword');
456
+ const declared = modifiers.includes('DeclareKeyword');
457
+ const is_public = !(modifiers.includes('ProtectedKeyword') || modifiers.includes('PrivateKeyword'));
458
+
459
+ /*
460
+ if ((node as any).name && ts.isIdentifier((node as any).name)) {
461
+ const name = (node as any).name.escapedText.toString();
462
+ if (/treb/i.test(name)) {
463
+ console.info(name, node.kind, ts.SyntaxKind[node.kind] );
464
+ }
465
+ }
466
+ */
467
+
468
+ /*
469
+ if ((node as any).name && ts.isIdentifier((node as any).name)) {
470
+ const name = (node as any).name.escapedText.toString();
471
+ if (/trebglobal$/i.test(name)) {
472
+ console.info({name, exported, internal, modifiers});
473
+ console.info(node);
474
+ console.info('');
475
+ }
476
+ }
477
+ */
478
+
479
+ /*
480
+ if (exported && declared) {
481
+ if ((node as any).name && ts.isIdentifier((node as any).name)) {
482
+ const name = (node as any).name.escapedText.toString();
483
+ //if (/treb$/i.test(name)) {
484
+ console.info({name, exported, internal, modifiers});
485
+ // console.info(node);
486
+ // console.info('');
487
+ //}
488
+ }
489
+
490
+ }
491
+ */
492
+
493
+ if (ts.isModuleDeclaration(node)
494
+ || ts.isClassDeclaration(node)
495
+ || ts.isInterfaceDeclaration(node)
496
+ || ts.isTypeAliasDeclaration(node)
497
+ || ts.isEnumDeclaration(node)) {
498
+
499
+ if (exported && !internal) {
500
+
501
+ if (node.name && ts.isIdentifier(node.name)) {
502
+
503
+ if (!AddFoundType(node.name.escapedText.toString(), node.getFullText())) {
504
+ return undefined;
505
+ }
506
+
507
+ containing_type.unshift(node.name.escapedText.toString());
508
+
509
+ if (ts.isClassDeclaration(node)) {
510
+ const name = node.name?.escapedText;
511
+ if (name && config.drop_generics.includes(name)) {
512
+ node = ts.factory.updateClassDeclaration(node,
513
+ // node.decorators,
514
+ node.modifiers,
515
+ node.name,
516
+ [], // node.typeParameters,
517
+ node.heritageClauses,
518
+ node.members);
519
+ }
520
+ }
521
+
522
+ if (ts.isInterfaceDeclaration(node)) {
523
+
524
+ // drop any internals, so we don't reference types
525
+
526
+ node = ts.factory.updateInterfaceDeclaration(node,
527
+ // node.decorators,
528
+ node.modifiers,
529
+ node.name,
530
+ node.typeParameters,
531
+ node.heritageClauses,
532
+ node.members.filter(member => {
533
+
534
+ const member_tags = GetDocTags(member);
535
+ const internal = member_tags.some(test => config.exclude_tags.includes(test));
536
+
537
+ if (internal) {
538
+ return false;
539
+ }
540
+ return true;
541
+
542
+ }));
543
+
544
+ }
545
+
546
+ const result = ts.visitEachChild(node, child => visit(child), context);
547
+ containing_type.shift();
548
+ return result;
549
+
550
+ }
551
+ else {
552
+ throw new Error('unhandled case (12)');
553
+ }
554
+ }
555
+ else {
556
+ return undefined; // do not recurse
557
+ }
558
+
559
+ }
560
+
561
+ else if (ts.isVariableStatement(node)) {
562
+ if (exported && !internal) {
563
+
564
+ // the type will be found, so we don't have to worry about that.
565
+ // should we be concerned with invalid/removed types? (...)
566
+
567
+ // we may see this more than once, if a file is included by
568
+ // other files. is there a better way to identify variables?
569
+ // maybe we should affirmatively declare exports with a tag
570
+
571
+ const text = node.getFullText();
572
+ args.exported_variables.push(text);
573
+
574
+ }
575
+ else {
576
+ return undefined; // end
577
+ }
578
+ }
579
+
580
+ else if (ts.isExpressionWithTypeArguments(node)) {
581
+ if (ts.isIdentifier(node.expression)) {
582
+ const key = node.expression.escapedText.toString();
583
+ AddReferencedType(key, 0);
584
+ }
585
+ else if (ts.isQualifiedName(node.expression)) {
586
+ const stack = FlattenQualifiedName(node.expression);
587
+ if (stack.length) {
588
+ AddReferencedType(stack[0], 1);
589
+ }
590
+ }
591
+ }
592
+
593
+ else if (ts.isTypeReferenceNode(node)) {
594
+
595
+ if (ts.isIdentifier(node.typeName)) {
596
+ const key = node.typeName.escapedText.toString();
597
+ AddReferencedType(key, 2);
598
+ }
599
+ else if (ts.isQualifiedName(node.typeName)) {
600
+
601
+ // do we want the qualified name, or just the thing we need
602
+ // to import (right-most)?
603
+
604
+ const stack = FlattenQualifiedName(node.typeName);
605
+ // AddReferencedType(FlattenQualifiedName(node.typeName).join('.'));
606
+ if (stack.length) {
607
+ AddReferencedType(stack[0], 3);
608
+ }
609
+
610
+ }
611
+ else {
612
+ throw new Error('unhandled case (13)');
613
+ }
614
+ }
615
+
616
+ else if (ts.isPropertyDeclaration(node)
617
+ || ts.isMethodDeclaration(node)
618
+ || ts.isAccessor(node)) {
619
+
620
+ // FIXME: do we want static? in some cases, maybe yes...
621
+ // we should probably filter later, and on a case-by-case basis
622
+
623
+ // we're inside a method in a class... we should only get here
624
+ // if the containing class was exported. here we are only looking
625
+ // for types, and only on public methods. (same for properties;
626
+ // must be public).
627
+
628
+ if (ts.isIdentifier(node.name)) {
629
+
630
+ if (!is_public || internal) {
631
+ return undefined; // don't recurse
632
+ }
633
+
634
+ }
635
+ else {
636
+ throw new Error('unhandled case (15)');
637
+ }
638
+
639
+ }
640
+
641
+ else if (ts.isConstructorDeclaration(node)) {
642
+
643
+ if (!is_public || internal) {
644
+ return undefined; // don't recurse
645
+ }
646
+ else {
647
+ // console.info(node);
648
+ // console.info('public?', is_public, 'tags?', tags);
649
+ // throw new Error('no');
650
+ }
651
+ }
652
+
653
+ else if (ts.isImportDeclaration(node)) {
654
+
655
+ let target = node.moduleSpecifier.getText();
656
+ if (/^['"][\s\S]*?['"]$/.test(target)) {
657
+ target = target.substr(1, target.length - 2);
658
+ }
659
+
660
+ if (node.importClause && ts.isImportClause(node.importClause)) {
661
+ if (node.importClause.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {
662
+ for (const element of node.importClause.namedBindings.elements) {
663
+ const name = element.name.escapedText.toString();
664
+ args.imported_types[name] = target;
665
+ }
666
+ }
667
+ }
668
+
669
+ return undefined;
670
+
671
+ }
672
+ else if (ts.isExportDeclaration(node)) {
673
+
674
+ // this is export {A} from 'B', or export * from 'C'.
675
+
676
+ if (node.moduleSpecifier) {
677
+ let target = node.moduleSpecifier.getText();
678
+ if (/^['"][\s\S]*?['"]$/.test(target)) {
679
+ target = target.substr(1, target.length - 2);
680
+ }
681
+
682
+ const targets: string[] = args.recursive_targets[target] || [];
683
+
684
+ if (node.exportClause && ts.isNamedExports(node.exportClause)) {
685
+ for (const element of node.exportClause.elements) {
686
+ const name = element.name.escapedText.toString();
687
+ //if (args.types && args.types.includes(name)) {
688
+ // if (!args.recursive_targets[target]) { args.recursive_targets[target] = []; }
689
+ // args.recursive_targets[target].push(element.name.escapedText.toString());
690
+ //}
691
+ targets.push(name);
692
+ AddReferencedType(name, 4);
693
+ }
694
+ }
695
+ else {
696
+ // this is 'export * from SRC' type
697
+ // if (!args.recursive_targets[target]) { args.recursive_targets[target] = []; }
698
+ // args.recursive_targets[target].push(...args.types);
699
+ targets.push('*');
700
+ }
701
+
702
+ // console.info(targets);
703
+
704
+ args.recursive_targets[target] = targets;
705
+
706
+ }
707
+
708
+ return undefined;
709
+
710
+ }
711
+
712
+ return ts.visitEachChild(node, child => visit(child), context);
713
+ }
714
+ return node => ts.visitNode(node, visit);
715
+ }
716
+ }
717
+
718
+ let invoke = 0;
719
+
720
+ const lookups: Record<string, boolean|string> = {};
721
+ const master: Record<string, string> = {};
722
+ const exported_variables: string[] = [];
723
+
724
+ let var_index = 0;
725
+
726
+ const ReadTypes = async (file: string, types?: string[], origination = 'C', depth = 0, stack: string[] = []): Promise<ReadTypeArgs> => {
727
+
728
+ // console.info('read types:', file, types);
729
+
730
+ if (stack.includes(file)) {
731
+ console.info(file, stack);
732
+ throw new Error('circular');
733
+ }
734
+
735
+ if (++invoke > 1e6) {
736
+ console.info(file, stack);
737
+ throw new Error('runaway');
738
+ }
739
+
740
+ // console.info("R", file, (types||[]).join(', '));
741
+
742
+ /*
743
+ if (types && types.includes('Sheet')) {
744
+ console.info('want sheet', file, stack);
745
+ throw new Error('want sheet');
746
+ }
747
+ */
748
+
749
+ let depth_prefix = '';
750
+ for (let i = 0; i < depth; i++) { depth_prefix += ' '; }
751
+
752
+ const RelativeFilePath = (key: string): string => {
753
+ for (const prefix of Object.keys(config.map)) {
754
+ if (key.startsWith(prefix)) { // should === ?
755
+ const replaced = key.replace(prefix, config.map[prefix]);
756
+ return path.join(config_dir, replaced);
757
+ }
758
+ }
759
+
760
+ if (key.startsWith('.')) {
761
+ return path.join(path.dirname(file), key + '.d.ts');
762
+ }
763
+ else if (/\//.test(key)) {
764
+ return path.join(config_dir, config.root, key + '.d.ts');
765
+ }
766
+ else {
767
+ return path.join(config_dir, config.root, key, 'src', 'index.d.ts');
768
+ // return path.join(config_dir, config.root, key, 'src', 'index.d.ts');
769
+ }
770
+ };
771
+
772
+ // console.info("READ", depth_prefix, origination, file, types);
773
+
774
+ const args: ReadTypeArgs = {
775
+ types,
776
+ recursive_targets: {},
777
+ found_types: {},
778
+ referenced_types: {},
779
+ referenced_type_map: {},
780
+ imported_types: {},
781
+ extra_types: {},
782
+ exported_variables: [],
783
+ };
784
+
785
+ const text = await fs.promises.readFile(file, { encoding: 'utf8' });
786
+ const node = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true);
787
+
788
+ ts.transform(node, [CollectDependencyTransformer(args)]);
789
+
790
+ let keys = Object.keys(args.referenced_types);
791
+ const found = Object.keys(args.found_types);
792
+
793
+ // console.info("T", (types||[]).join(', '))
794
+ // console.info(' K1', keys.join(', '));
795
+
796
+ // we can drop anything from keys that does not have a proper
797
+ // containing type... although the containing type may _itself_
798
+ // have a valid containing type... and so on...
799
+
800
+ // what we should do is climb up the containing type list. note
801
+ // that there could be more than one highest-level type...
802
+
803
+ //============================================================================
804
+ // Q: what is this for? it's broken. temporarily removing.
805
+ //============================================================================
806
+
807
+ const containing_keys = Object.keys(args.referenced_type_map);
808
+
809
+ /*
810
+ {
811
+ fs.writeFileSync('check.json', JSON.stringify(args.referenced_type_map, undefined, 2), {encoding: 'utf8'});
812
+ }
813
+ */
814
+
815
+ const ResolveContainingTypes = (base: string, list: string[] = [], depth = 0) => {
816
+ // find any types that contain this type
817
+
818
+ /*
819
+ let s = '';
820
+ for (let i = 0; i< depth; i++) s += ' ';
821
+ console.info(s, 'rct', base, '');
822
+ */
823
+
824
+ for (const container of containing_keys) {
825
+ if (args.referenced_type_map[container].includes(base)) {
826
+ if (!list.includes(container)) {
827
+ // console.info(s, ' check [2]', container);
828
+ list.push(container);
829
+ //const sublist = ResolveContainingTypes(container, list, depth + 1);
830
+ ResolveContainingTypes(container, list, depth + 1);
831
+
832
+ // list.push(...sublist);
833
+ }
834
+ }
835
+ }
836
+ return list;
837
+ }
838
+
839
+ /**
840
+ const ResolveContainingTypes = (base: string, list: string[] = []) => {
841
+
842
+ // find any types that contain this type
843
+ for (const container of containing_keys) {
844
+ if (args.referenced_type_map[container].includes(base)) {
845
+ if (!list.includes(container)) {
846
+ list.push(container);
847
+ const sublist = ResolveContainingTypes(container, list);
848
+ list.push(...sublist);
849
+ }
850
+ }
851
+ }
852
+ return list;
853
+ };
854
+ */
855
+
856
+ // console.info('\n');
857
+
858
+ if (types) {
859
+ keys = keys.filter(key => {
860
+ const list = ResolveContainingTypes(key);
861
+ for (const entry of list) {
862
+ if (types.includes(entry)) { return true; }
863
+ }
864
+ // console.info("DROPPING", key);
865
+ return false;
866
+ });
867
+ }
868
+
869
+ // console.info(' KX', args.referenced_type_map);
870
+ // console.info(' K2', keys.join(', '));
871
+ // console.info(' F1', found.join(', '));
872
+
873
+ // we may have referenced types from the same file, in which case we
874
+ // need to add them to our "found" list.
875
+
876
+ for (const extra of Object.keys(args.extra_types)) {
877
+ if (keys.includes(extra) && !found.includes(extra)) {
878
+ found.push(extra);
879
+ args.found_types[extra] = args.extra_types[extra];
880
+ lookups[`${file}:${extra}`] = true;
881
+ }
882
+ }
883
+
884
+ // console.info(' F2', found.join(', '));
885
+
886
+ const mapped: Record<string, string[]> = {};
887
+
888
+ // if we were looking for a particular type in this file, did we
889
+ // find it? note that we're setting a boolean here, indicating simple
890
+ // found or not found at this point.
891
+
892
+ if (types) {
893
+ for (const type of types) {
894
+ lookups[`${file}:${type}`] = found.includes(type);
895
+ }
896
+ }
897
+
898
+ /*
899
+ console.info('file:', file);
900
+ console.info('want:', types ? types : 'all');
901
+ console.info('found:', found);
902
+ console.info('recursive:', args.recursive_targets);
903
+ console.info('');
904
+ */
905
+
906
+ const recursive = Object.keys(args.recursive_targets);
907
+ // console.info({recursive});
908
+
909
+ if (recursive.length) {
910
+
911
+ let filtered: string[] | undefined;
912
+ if (types) {
913
+ filtered = [];
914
+ for (const type of types) {
915
+ if (!found.includes(type)) {
916
+ filtered.push(type);
917
+ }
918
+ }
919
+ }
920
+
921
+ // console.info({types, found, filtered});
922
+
923
+ if (!filtered || filtered.length) {
924
+ for (const key of recursive) {
925
+ const file_path = RelativeFilePath(key);
926
+
927
+ let sublist: string[] | undefined = args.recursive_targets[key];
928
+ let result: ReadTypeArgs;
929
+
930
+ // console.info(0, {file_path, key, sublist, filtered});
931
+
932
+ if (sublist.includes('*')) {
933
+ sublist = filtered;
934
+ }
935
+ else if (filtered) {
936
+ // console.info({sublist, filtered})
937
+ sublist = sublist.filter(test => (filtered||[]).includes(test));
938
+ }
939
+ else {
940
+ // console.info("using sublist without filter:", sublist);
941
+ }
942
+
943
+ // console.info(1, {file_path, key, sublist});
944
+
945
+ // NOW filter on whether we've checked this path for this
946
+ // type before. if so, even if we missed, we can drop it.
947
+
948
+ sublist = (sublist||[]).filter(test => {
949
+ const composite = `${file_path}:${test}`;
950
+ const check = lookups[composite];
951
+ return typeof check === 'undefined';
952
+ });
953
+
954
+ // console.info(2, {sublist});
955
+
956
+ if (sublist.length) {
957
+ result = await ReadTypes(file_path, sublist, 'X', depth + 1, [...stack, file]);
958
+ const resolved = Object.keys(result.found_types);
959
+
960
+ // console.info({resolved});
961
+
962
+ // if we found a type in a child that we were looking for, we can
963
+ // point our record (which should be false) to the child record
964
+
965
+ // UPDATE: this changes a bit when we have "extra" types, which
966
+ // were not originally referenced... in that case our record could
967
+ // be undefined, or even a string...
968
+
969
+ for (const test of resolved) {
970
+ const ours = `${file}:${test}`;
971
+ const theirs = `${file_path}:${test}`;
972
+ // console.info("CHECK 1", ours, master[ours], theirs, master[theirs]);
973
+
974
+ // validate
975
+ if (/*(lookups[ours] === false || lookups[ours] === undefined) &&*/ lookups[theirs] === true) {
976
+ lookups[ours] = theirs;
977
+ }
978
+ else {
979
+ // console.info("CHECK 1", ours, lookups[ours], theirs, lookups[theirs]);
980
+ // console.info("F", file);
981
+ throw new Error('??');
982
+ }
983
+
984
+ }
985
+
986
+ if (filtered) {
987
+ filtered = (filtered || []).filter(test => !resolved.includes(test));
988
+ if (!filtered.length) { break; }
989
+ }
990
+ }
991
+
992
+ }
993
+
994
+ }
995
+
996
+ }
997
+
998
+ for (const key of keys) {
999
+ if (!found.includes(key) && args.imported_types[key]) {
1000
+ const source = args.imported_types[key];
1001
+ const list = mapped[source] || [];
1002
+ mapped[source] = [...list, key];
1003
+ }
1004
+ }
1005
+
1006
+ for (const key of found) {
1007
+ master[key] = args.found_types[key];
1008
+ }
1009
+
1010
+ for (const statement of args.exported_variables) {
1011
+ if (!exported_variables.includes(statement)) {
1012
+ master[`__variable_${var_index++}`] = statement;
1013
+ // console.info(statement);
1014
+ exported_variables.push(statement);
1015
+ }
1016
+ }
1017
+
1018
+ // console.info(file, Object.keys(mapped).join(', '));
1019
+
1020
+ /*
1021
+ if (!types) {
1022
+ console.info("I AM TOP")
1023
+ console.info(mapped);
1024
+ }
1025
+ */
1026
+
1027
+ for (const key of Object.keys(mapped)) {
1028
+
1029
+ let list = mapped[key];
1030
+ const file_path = RelativeFilePath(key);
1031
+
1032
+ // filter types we've already read from this file
1033
+ list = list.filter(test => {
1034
+ const composite = `${file_path}:${test}`;
1035
+ const check = lookups[composite];
1036
+ return typeof check === 'undefined';
1037
+ });
1038
+
1039
+ if (list.length) {
1040
+ await ReadTypes(file_path, list, 'I', depth + 1, [...stack, file]);
1041
+ }
1042
+
1043
+ // if (2>1) throw new Error('ending after 1st import')
1044
+
1045
+ }
1046
+
1047
+ // console.info("ARGS", args, '\n');
1048
+
1049
+ return args;
1050
+
1051
+ };
1052
+
1053
+ const Run = async () => {
1054
+
1055
+ await ReadConfigData(config_file);
1056
+ console.info(config);
1057
+
1058
+ // read index file
1059
+ const index = path.join(config_dir, config.root, config.index);
1060
+
1061
+ await ReadTypes(index);
1062
+
1063
+ // console.info(`(done, ${invoke})`);
1064
+
1065
+ const text: string[] = [];
1066
+ for (const key of Object.keys(master)) {
1067
+ text.push(master[key]);
1068
+ }
1069
+
1070
+ const composite = text.join('\n');
1071
+ const node = ts.createSourceFile('composite', composite, ts.ScriptTarget.Latest, true);
1072
+ const result = ts.transform(node, [CleanTransformer()])
1073
+
1074
+ const printer = ts.createPrinter();
1075
+ let printed = printer.printFile(result.transformed[0]); // FIXME: options
1076
+
1077
+ // TS doesn't really like spaces
1078
+ printed = printed.replace(/(\s+?\/\*)/g, '\n$1');
1079
+
1080
+ // prepend any include files
1081
+ for (let include of config.include) {
1082
+ include = path.join(config_dir, include);
1083
+ const text = await fs.promises.readFile(include, {encoding: 'utf8'});
1084
+ printed = text + printed;
1085
+ }
1086
+
1087
+ if (api_version) {
1088
+ const banner = `/*! API v${api_version}. Copyright 2018-${new Date().getFullYear()} trebco, llc. All rights reserved. LGPL: https://treb.app/license */`;
1089
+ printed = banner + '\n' + printed;
1090
+ }
1091
+
1092
+ // can't figure out how to transform jsdoc nodes using transformers.
1093
+ // so, back to hacks. the aim here is to remove @privateRemarks, up
1094
+ // to the next tag (@) or close comment (*/). this often results in
1095
+ // an extra empty line in the comment, which is unfortunate but not
1096
+ // the end of the world.
1097
+
1098
+ printed = printed.replace(/(\s*\*)\s*@privateRemarks[\s\S]*?((?: @|\*\/))/g, '$1$2');
1099
+
1100
+ //
1101
+ // attempting to clean up... this somewhat confusing regexp
1102
+ // is intended to convert
1103
+ //
1104
+ // /**
1105
+ // * build version
1106
+ // *
1107
+ // **/
1108
+ // version: string;
1109
+ //
1110
+ // (caused by removing @privateRemarks) to
1111
+ //
1112
+ // /**
1113
+ // * build version
1114
+ // */
1115
+ // version: string;
1116
+ //
1117
+ printed = printed.replace(/(\*\n[ ]+)\*\*\//g, '*/')
1118
+
1119
+ if (config.output) {
1120
+ await fs.promises.writeFile(config.output, printed, {encoding: 'utf8'});
1121
+ }
1122
+ else {
1123
+ console.info(printed);
1124
+ }
1125
+
1126
+
1127
+ /*
1128
+ const text = await fs.promises.readFile(index, { encoding: 'utf8' });
1129
+ const node = ts.createSourceFile(index, text, ts.ScriptTarget.Latest, true);
1130
+
1131
+ const args = {
1132
+ recursive_targets: {},
1133
+ found_types: {},
1134
+ referenced_types: {},
1135
+ imported_types: {},
1136
+ };
1137
+
1138
+ const result = ts.transform(node, [CollectDependencyTransformer(args)]);
1139
+
1140
+ // console.info(Object.keys(args.found_types));
1141
+ // console.info(args.referenced_types);
1142
+
1143
+ const keys = Object.keys(args.referenced_types);
1144
+ keys.sort();
1145
+
1146
+ const found = Object.keys(args.found_types);
1147
+ const mapped: Record<string, string[]> = {};
1148
+
1149
+ for (const key of keys) {
1150
+ if (found.includes(key)) {
1151
+ // console.info(`${key} => FOUND`);
1152
+ }
1153
+ else if (args.imported_types[key]) {
1154
+ const source = args.imported_types[key];
1155
+ // console.info(`${key} => ${args.imported_types[key]}`);
1156
+ const list = mapped[source] || [];
1157
+ mapped[source] = [...list, key];
1158
+ }
1159
+ else {
1160
+ console.info(`${key} => missing!`);
1161
+ }
1162
+ }
1163
+ console.info('---');
1164
+ console.info(mapped);
1165
+ */
1166
+
1167
+
1168
+ };
1169
+
1170
+ Run();
1171
+
1172
+