@trebco/treb 25.0.1 → 25.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{.eslintrc.js → .eslintrc.cjs} +4 -0
- package/api-config.json +1 -1
- package/api-generator/api-generator.ts +25 -55
- package/dist/treb-spreadsheet.mjs +14 -0
- package/{build → dist}/treb.d.ts +1 -1
- package/esbuild-custom-element.mjs +17 -265
- package/esbuild-utils.mjs +273 -0
- package/package.json +5 -4
- package/treb-base-types/src/cell.ts +23 -22
- package/treb-base-types/src/cells.ts +55 -2
- package/treb-base-types/src/union.ts +2 -1
- package/treb-calculator/src/calculator.ts +8 -5
- package/treb-calculator/src/dag/array-vertex.ts +22 -22
- package/treb-calculator/src/dag/graph.ts +25 -23
- package/treb-calculator/src/dag/leaf_vertex.ts +23 -22
- package/treb-calculator/src/dag/spreadsheet_vertex.ts +25 -23
- package/treb-calculator/src/expression-calculator.ts +23 -22
- package/treb-calculator/src/function-error.ts +23 -22
- package/treb-calculator/src/functions/base-functions.ts +3 -2
- package/treb-calculator/src/functions/checkbox.ts +23 -22
- package/treb-calculator/src/functions/complex-functions.ts +2 -1
- package/treb-calculator/src/functions/finance-functions.ts +22 -22
- package/treb-calculator/src/functions/information-functions.ts +22 -22
- package/treb-calculator/src/functions/matrix-functions.ts +2 -1
- package/treb-calculator/src/functions/statistics-functions.ts +22 -22
- package/treb-calculator/src/functions/text-functions.ts +23 -22
- package/treb-calculator/src/primitives.ts +23 -22
- package/treb-calculator/src/utilities.ts +23 -24
- package/treb-charts/src/chart-functions.ts +22 -22
- package/treb-charts/src/chart.ts +6 -3
- package/treb-charts/src/renderer.ts +25 -23
- package/treb-charts/src/util.ts +23 -22
- package/treb-embed/markup/toolbar.html +2 -2
- package/treb-embed/modern.tsconfig.json +3 -2
- package/treb-embed/src/custom-element/spreadsheet-constructor.ts +17 -14
- package/treb-embed/src/embedded-spreadsheet.ts +100 -69
- package/treb-embed/src/progress-dialog.ts +0 -3
- package/treb-embed/src/types.ts +13 -3
- package/treb-embed/style/dialog.scss +2 -0
- package/treb-embed/style/layout.scss +43 -40
- package/treb-embed/style/toolbar.scss +38 -38
- package/treb-embed/style/treb-icons.scss +53 -43
- package/treb-export/src/drawing2/chart2.ts +2 -2
- package/treb-export/src/drawing2/drawing2.ts +6 -4
- package/treb-export/src/export-worker/export-worker.ts +22 -24
- package/treb-export/src/export-worker/index-modern.ts +2 -1
- package/treb-export/src/export2.ts +15 -8
- package/treb-export/src/import2.ts +10 -5
- package/treb-export/src/workbook-sheet2.ts +2 -1
- package/treb-format/src/format.ts +23 -22
- package/treb-format/src/format_parser.ts +23 -22
- package/treb-format/src/value_parser.ts +23 -22
- package/treb-grid/src/editors/formula_bar.ts +2 -1
- package/treb-grid/src/editors/formula_editor_base.ts +4 -2
- package/treb-grid/src/editors/overlay_editor.ts +2 -1
- package/treb-grid/src/index.ts +12 -9
- package/treb-grid/src/layout/base_layout.ts +4 -2
- package/treb-grid/src/render/selection-renderer.ts +25 -23
- package/treb-grid/src/render/tile_renderer.ts +6 -4
- package/treb-grid/src/types/annotation.ts +33 -37
- package/treb-grid/src/types/data_model.ts +30 -22
- package/treb-grid/src/types/grid.ts +55 -584
- package/treb-grid/src/types/grid_base.ts +401 -7
- package/treb-grid/src/types/grid_events.ts +3 -0
- package/treb-grid/src/types/grid_selection.ts +22 -22
- package/treb-grid/src/types/named_range.ts +22 -22
- package/treb-grid/src/types/sheet.ts +8 -7
- package/treb-grid/src/types/sheet_types.ts +11 -7
- package/treb-grid/src/types/tab_bar.ts +1 -1
- package/treb-parser/src/parser.ts +5 -4
- package/tsproject.json +4 -5
- package/util/list-css-vars.sh +8 -11
- package/build/treb-spreadsheet.mjs +0 -14
- package/esbuild.js +0 -305
- package/tsconfig.json +0 -10
- /package/treb-embed/src/{custom-element/content-types.d.ts → content-types.d.ts} +0 -0
package/{build → dist}/treb.d.ts
RENAMED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
import * as esbuild from 'esbuild';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import sass from 'sass';
|
|
8
|
-
import cssnano from 'cssnano';
|
|
9
|
-
import postcss from 'postcss';
|
|
4
|
+
|
|
5
|
+
import { SassPlugin, WorkerPlugin, NotifyPlugin, HTMLPlugin } from './esbuild-utils.mjs';
|
|
10
6
|
|
|
11
7
|
import pkg from './package.json' assert { type: 'json' };
|
|
12
8
|
|
|
13
|
-
/** @type {import('html-minifier').Options} */
|
|
14
|
-
const html_minifier_options = {
|
|
15
|
-
removeComments: true,
|
|
16
|
-
collapseWhitespace: true,
|
|
17
|
-
};
|
|
18
9
|
|
|
19
10
|
/**
|
|
20
11
|
* @typedef {Object} Options
|
|
@@ -22,6 +13,8 @@ const html_minifier_options = {
|
|
|
22
13
|
* @property {boolean} watch
|
|
23
14
|
* @property {boolean} verbose - log all plugin inputs. helpful for dev/debug.
|
|
24
15
|
* @property {boolean} minify - separate from dev/production, in case we need to test
|
|
16
|
+
* @property {boolean} xlsx_support - import/export xlsx files
|
|
17
|
+
* @property {string} output_filename - generated filename. we enforce the directory.
|
|
25
18
|
*/
|
|
26
19
|
|
|
27
20
|
/**
|
|
@@ -35,256 +28,8 @@ const options = {
|
|
|
35
28
|
watch: false,
|
|
36
29
|
minify: true,
|
|
37
30
|
verbose: false,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @function
|
|
42
|
-
* @param {string} [label] - optional label for build messages
|
|
43
|
-
* @returns {esbuild.Plugin}
|
|
44
|
-
*
|
|
45
|
-
* add notifications on build start/end. we also want to use this
|
|
46
|
-
* to notify worker sub-builds, so we can be sure they're working
|
|
47
|
-
* properly.
|
|
48
|
-
*/
|
|
49
|
-
const NotifyPlugin = (label) => {
|
|
50
|
-
return {
|
|
51
|
-
name: 'notify',
|
|
52
|
-
setup(build) {
|
|
53
|
-
build.onStart(() => {
|
|
54
|
-
console.info(`${label ? `${label} ` : ''}build started @ ${new Date().toLocaleTimeString()}`);
|
|
55
|
-
});
|
|
56
|
-
build.onEnd(result => {
|
|
57
|
-
if (!result.errors.length) {
|
|
58
|
-
|
|
59
|
-
const keys = Object.keys(result.metafile?.outputs||{});
|
|
60
|
-
const bytes = keys.length ? result.metafile?.outputs[keys[0]]?.bytes : 0;
|
|
61
|
-
const size = bytes ? `; build size: ${FormatSize(bytes)}` : '';
|
|
62
|
-
|
|
63
|
-
console.info(`${label ? `${label} ` : ''}build complete @ ${new Date().toLocaleTimeString()}${size}`);
|
|
64
|
-
// console.info(result.metafile);
|
|
65
|
-
}
|
|
66
|
-
if (!label) {
|
|
67
|
-
console.info('');
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @function
|
|
76
|
-
* @param {number} size - size in bytes
|
|
77
|
-
* @returns {string} - size as a human readable string
|
|
78
|
-
*/
|
|
79
|
-
const FormatSize = (size, precision = 1) => {
|
|
80
|
-
|
|
81
|
-
const units = ['B', 'KB', 'MB'];
|
|
82
|
-
let index = 0;
|
|
83
|
-
|
|
84
|
-
for (let i = 0; i < units.length; i++) {
|
|
85
|
-
if (size > 1024) {
|
|
86
|
-
size = size / 1024;
|
|
87
|
-
index++;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return `${size.toFixed(2)} ${units[index]}`;
|
|
92
|
-
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @type esbuild.Plugin
|
|
97
|
-
*
|
|
98
|
-
* inlining the worker build. this works out well with one limitation:
|
|
99
|
-
* at the moment, we're not caching the build for watching. OTOH esbuild
|
|
100
|
-
* is so fast it doesn't really matter at the moment.
|
|
101
|
-
*
|
|
102
|
-
* if you import a worker script like this
|
|
103
|
-
* ```
|
|
104
|
-
* import worker_script from 'worker:path/to/worker.ts';
|
|
105
|
-
* ```
|
|
106
|
-
* the plugin will compile the target (with esbuild) and then return the
|
|
107
|
-
* compiled script as a string. the child build inherits minify settings
|
|
108
|
-
* from the parent build.
|
|
109
|
-
*
|
|
110
|
-
* you can then use it in the containing script by creating a worker:
|
|
111
|
-
* ```
|
|
112
|
-
* const worker = new Worker(URL.createObjectURL(new Blob([worker_script], { type: 'application/javascript' })));
|
|
113
|
-
* ```
|
|
114
|
-
*
|
|
115
|
-
* this might cause problems with CSP. if so, we'll sort that out separately.
|
|
116
|
-
*
|
|
117
|
-
*/
|
|
118
|
-
const worker_plugin = {
|
|
119
|
-
name: 'worker',
|
|
120
|
-
setup(build) {
|
|
121
|
-
|
|
122
|
-
build.onResolve({ filter: /^worker:/}, async (args) => {
|
|
123
|
-
args.path = args.path.substring(7);
|
|
124
|
-
const result = await build.resolve(args.path, {
|
|
125
|
-
kind: args.kind,
|
|
126
|
-
resolveDir: args.resolveDir,
|
|
127
|
-
});
|
|
128
|
-
return { path: result.path, namespace: 'worker', };
|
|
129
|
-
}),
|
|
130
|
-
|
|
131
|
-
// for some reason I can't get the filter to work here, but using
|
|
132
|
-
// namespace works. as long as we don't collide with anybody else.
|
|
133
|
-
//
|
|
134
|
-
// with the assumption that esbuild will eventually have a solution
|
|
135
|
-
// for inlining workers, we might want to use a more distinctive
|
|
136
|
-
// namespace that has less possibility of collision in the future.
|
|
137
|
-
// of course if that happens we will probably use the native version,
|
|
138
|
-
// so maybe it doesn't matter.
|
|
139
|
-
|
|
140
|
-
build.onLoad({ filter: /./, namespace: 'worker' }, async(args) => {
|
|
141
|
-
|
|
142
|
-
if (options.verbose) {
|
|
143
|
-
console.info('worker:', args.path);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
|
|
148
|
-
const result = await esbuild.build({
|
|
149
|
-
|
|
150
|
-
entryPoints: [ args.path ],
|
|
151
|
-
|
|
152
|
-
// we can use this as a key later
|
|
153
|
-
outfile: 'worker',
|
|
154
|
-
|
|
155
|
-
// inherit options
|
|
156
|
-
minify: options.minify,
|
|
157
|
-
bundle: true,
|
|
158
|
-
format: 'esm',
|
|
159
|
-
|
|
160
|
-
// don't write to filesystem
|
|
161
|
-
write: false,
|
|
162
|
-
|
|
163
|
-
// use the metafile to get deps
|
|
164
|
-
metafile: true,
|
|
165
|
-
|
|
166
|
-
// write to stdout
|
|
167
|
-
plugins: [
|
|
168
|
-
NotifyPlugin('- worker'),
|
|
169
|
-
],
|
|
170
|
-
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
if (options.verbose) {
|
|
174
|
-
console.info(' worker build size: ' + FormatSize(result.outputFiles[0].text.length));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// here's where we use that name as a key
|
|
178
|
-
|
|
179
|
-
const inputs = result.metafile.outputs['worker'].inputs;
|
|
180
|
-
const watchFiles = Object.keys(inputs).map(relative => path.resolve(relative));
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
errors: result.errors,
|
|
184
|
-
warnings: result.warnings,
|
|
185
|
-
loader: 'text',
|
|
186
|
-
contents: result.outputFiles[0].text,
|
|
187
|
-
watchFiles,
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
catch (err) {
|
|
192
|
-
|
|
193
|
-
// on error, we pass the file that threw as a dependency so we can
|
|
194
|
-
// watch updates and trigger a rebuild (nice that this works, btw)
|
|
195
|
-
|
|
196
|
-
const watchFiles = [];
|
|
197
|
-
for (const error of err.errors) {
|
|
198
|
-
if (error.location?.file) {
|
|
199
|
-
watchFiles.push(path.resolve(error.location.file));
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return {
|
|
203
|
-
errors: err.errors,
|
|
204
|
-
watchFiles,
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* @type esbuild.Plugin
|
|
215
|
-
*
|
|
216
|
-
* html -> string, optionally minified
|
|
217
|
-
*/
|
|
218
|
-
const html_plugin = {
|
|
219
|
-
name: 'html',
|
|
220
|
-
setup(build) {
|
|
221
|
-
build.onLoad({ filter: /\.html$/ }, async (args) => {
|
|
222
|
-
|
|
223
|
-
if (options.verbose) {
|
|
224
|
-
console.info('html:', args.path);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const text = await fs.readFile(args.path, 'utf8');
|
|
228
|
-
return {
|
|
229
|
-
contents: options.minify ? minify(text, html_minifier_options) : text,
|
|
230
|
-
loader: 'text',
|
|
231
|
-
};
|
|
232
|
-
});
|
|
233
|
-
},
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* @type esbuild.Plugin
|
|
238
|
-
*
|
|
239
|
-
* sass -> string, optionally minified
|
|
240
|
-
*/
|
|
241
|
-
const sass_plugin = {
|
|
242
|
-
name: 'sass',
|
|
243
|
-
setup(build) {
|
|
244
|
-
build.onLoad({ filter: /\.scss$/ }, async (args) => {
|
|
245
|
-
|
|
246
|
-
if (options.verbose) {
|
|
247
|
-
console.info('sass:', args.path);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
try {
|
|
251
|
-
|
|
252
|
-
const result = await sass.compile(args.path, {
|
|
253
|
-
loadPaths: ['.'],
|
|
254
|
-
// charset: false,
|
|
255
|
-
// style: 'compressed',
|
|
256
|
-
});
|
|
257
|
-
const files = (result.loadedUrls || []).map(url => url.pathname);
|
|
258
|
-
|
|
259
|
-
let contents = result.css;
|
|
260
|
-
if (options.minify) {
|
|
261
|
-
const minified = await postcss([cssnano]).process(result.css, { from: undefined });
|
|
262
|
-
contents = minified.css;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
return {
|
|
266
|
-
contents,
|
|
267
|
-
loader: 'text',
|
|
268
|
-
watchFiles: files,
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
catch (err) {
|
|
273
|
-
const watchFiles = [];
|
|
274
|
-
if (err.span?.file?.url?.path) {
|
|
275
|
-
watchFiles.push(path.resolve(err.span.file.url.path));
|
|
276
|
-
}
|
|
277
|
-
return {
|
|
278
|
-
errors: [{
|
|
279
|
-
text: err.message,
|
|
280
|
-
// ...location...
|
|
281
|
-
}],
|
|
282
|
-
watchFiles,
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
});
|
|
287
|
-
},
|
|
31
|
+
xlsx_support: true,
|
|
32
|
+
output_filename: 'treb-spreadsheet.mjs',
|
|
288
33
|
};
|
|
289
34
|
|
|
290
35
|
//------------------------------------------------------------------------------
|
|
@@ -304,6 +49,12 @@ for (let i = 0; i < process.argv.length; i++) {
|
|
|
304
49
|
if (process.argv[i] === '--verbose') {
|
|
305
50
|
options.verbose = true;
|
|
306
51
|
}
|
|
52
|
+
if (process.argv[i] === '--no-xlsx') {
|
|
53
|
+
options.xlsx_support = false;
|
|
54
|
+
}
|
|
55
|
+
if (process.argv[i] === '--output-filename') {
|
|
56
|
+
options.output_filename = process.argv[++i];
|
|
57
|
+
}
|
|
307
58
|
}
|
|
308
59
|
|
|
309
60
|
/** @type esbuild.BuildOptions */
|
|
@@ -315,21 +66,22 @@ const build_options = {
|
|
|
315
66
|
js: `/*! TREB v${pkg.version}. Copyright 2018-${new Date().getFullYear()} trebco, llc. All rights reserved. LGPL: https://treb.app/license */`
|
|
316
67
|
},
|
|
317
68
|
bundle: true,
|
|
318
|
-
outfile: '
|
|
69
|
+
outfile: 'dist/' + options.output_filename,
|
|
319
70
|
outExtension: { '.js': '.mjs' },
|
|
320
71
|
minify: options.minify,
|
|
321
72
|
metafile: true,
|
|
322
73
|
format: 'esm',
|
|
323
74
|
define: {
|
|
75
|
+
'process.env.XLSX_SUPPORT': `${options.xlsx_support}`,
|
|
324
76
|
'process.env.NODE_ENV': `"${options.version}"`,
|
|
325
77
|
'process.env.BUILD_VERSION': `"${pkg.version}"`,
|
|
326
78
|
'process.env.BUILD_NAME': `"${pkg.name}"`,
|
|
327
79
|
},
|
|
328
80
|
plugins: [
|
|
329
81
|
NotifyPlugin(),
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
82
|
+
WorkerPlugin(options),
|
|
83
|
+
HTMLPlugin(options),
|
|
84
|
+
SassPlugin(options),
|
|
333
85
|
],
|
|
334
86
|
};
|
|
335
87
|
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
|
|
2
|
+
// @ts-check
|
|
3
|
+
|
|
4
|
+
import * as esbuild from 'esbuild';
|
|
5
|
+
import { promises as fs } from 'fs';
|
|
6
|
+
import { minify } from 'html-minifier';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import sass from 'sass';
|
|
9
|
+
import cssnano from 'cssnano';
|
|
10
|
+
import postcss from 'postcss';
|
|
11
|
+
|
|
12
|
+
/** @type {import('html-minifier').Options} */
|
|
13
|
+
const html_minifier_options = {
|
|
14
|
+
removeComments: true,
|
|
15
|
+
collapseWhitespace: true,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @function
|
|
20
|
+
* @param {string} [label] - optional label for build messages
|
|
21
|
+
* @returns {esbuild.Plugin}
|
|
22
|
+
*
|
|
23
|
+
* add notifications on build start/end. we also want to use this
|
|
24
|
+
* to notify worker sub-builds, so we can be sure they're working
|
|
25
|
+
* properly.
|
|
26
|
+
*/
|
|
27
|
+
export const NotifyPlugin = (label) => {
|
|
28
|
+
return {
|
|
29
|
+
name: 'notify',
|
|
30
|
+
setup(build) {
|
|
31
|
+
build.onStart(() => {
|
|
32
|
+
console.info(`${label ? `${label} ` : ''}build started @ ${new Date().toLocaleTimeString()}`);
|
|
33
|
+
});
|
|
34
|
+
build.onEnd(result => {
|
|
35
|
+
if (!result.errors.length) {
|
|
36
|
+
|
|
37
|
+
const keys = Object.keys(result.metafile?.outputs||{});
|
|
38
|
+
const bytes = keys.length ? result.metafile?.outputs[keys[0]]?.bytes : 0;
|
|
39
|
+
const size = bytes ? `; build size: ${FormatSize(bytes, 2)}` : '';
|
|
40
|
+
|
|
41
|
+
console.info(`${label ? `${label} ` : ''}build complete @ ${new Date().toLocaleTimeString()}${size}`);
|
|
42
|
+
// console.info(result.metafile);
|
|
43
|
+
}
|
|
44
|
+
if (!label) {
|
|
45
|
+
console.info('');
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @function
|
|
54
|
+
* @param {number} size - size in bytes
|
|
55
|
+
* @returns {string} - size as a human readable string
|
|
56
|
+
*/
|
|
57
|
+
export const FormatSize = (size, precision = 1) => {
|
|
58
|
+
|
|
59
|
+
const units = ['B', 'KB', 'MB'];
|
|
60
|
+
let index = 0;
|
|
61
|
+
|
|
62
|
+
for (let i = 0; i < units.length; i++) {
|
|
63
|
+
if (size > 1024) {
|
|
64
|
+
size = size / 1024;
|
|
65
|
+
index++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return `${size.toFixed(precision)} ${units[index]}`;
|
|
70
|
+
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @function
|
|
75
|
+
* @param {{verbose?: boolean, minify?: boolean}} [options]
|
|
76
|
+
* @returns {esbuild.Plugin}
|
|
77
|
+
*
|
|
78
|
+
* inlining the worker build. this works out well with one limitation:
|
|
79
|
+
* at the moment, we're not caching the build for watching. OTOH esbuild
|
|
80
|
+
* is so fast it doesn't really matter at the moment.
|
|
81
|
+
*
|
|
82
|
+
* if you import a worker script like this
|
|
83
|
+
* ```
|
|
84
|
+
* import worker_script from 'worker://path/to/worker.ts';
|
|
85
|
+
* ```
|
|
86
|
+
* the plugin will compile the target (with esbuild) and then return the
|
|
87
|
+
* compiled script as a string. the child build inherits minify settings
|
|
88
|
+
* from the parent build.
|
|
89
|
+
*
|
|
90
|
+
* you can then use it in the containing script by creating a worker:
|
|
91
|
+
* ```
|
|
92
|
+
* const worker = new Worker(URL.createObjectURL(new Blob([worker_script], { type: 'application/javascript' })));
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* this might cause problems with CSP. if so, we'll sort that out separately.
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
export const WorkerPlugin = (options) => ({
|
|
99
|
+
name: 'worker',
|
|
100
|
+
setup(build) {
|
|
101
|
+
|
|
102
|
+
build.onResolve({ filter: /^worker:\/\//}, async (args) => {
|
|
103
|
+
args.path = args.path.substring(9);
|
|
104
|
+
const result = await build.resolve(args.path, {
|
|
105
|
+
kind: args.kind,
|
|
106
|
+
resolveDir: args.resolveDir,
|
|
107
|
+
});
|
|
108
|
+
return { path: result.path, namespace: 'worker', };
|
|
109
|
+
}),
|
|
110
|
+
|
|
111
|
+
// for some reason I can't get the filter to work here, but using
|
|
112
|
+
// namespace works. as long as we don't collide with anybody else.
|
|
113
|
+
//
|
|
114
|
+
// with the assumption that esbuild will eventually have a solution
|
|
115
|
+
// for inlining workers, we might want to use a more distinctive
|
|
116
|
+
// namespace that has less possibility of collision in the future.
|
|
117
|
+
// of course if that happens we will probably use the native version,
|
|
118
|
+
// so maybe it doesn't matter.
|
|
119
|
+
|
|
120
|
+
build.onLoad({ filter: /./, namespace: 'worker' }, async(args) => {
|
|
121
|
+
|
|
122
|
+
if (options?.verbose) {
|
|
123
|
+
console.info('worker:', args.path);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
|
|
128
|
+
const result = await esbuild.build({
|
|
129
|
+
|
|
130
|
+
entryPoints: [ args.path ],
|
|
131
|
+
|
|
132
|
+
// we can use this as a key later
|
|
133
|
+
outfile: 'worker',
|
|
134
|
+
|
|
135
|
+
// inherit options
|
|
136
|
+
minify: options?.minify,
|
|
137
|
+
bundle: true,
|
|
138
|
+
format: 'esm',
|
|
139
|
+
|
|
140
|
+
// don't write to filesystem
|
|
141
|
+
write: false,
|
|
142
|
+
|
|
143
|
+
// use the metafile to get deps
|
|
144
|
+
metafile: true,
|
|
145
|
+
|
|
146
|
+
// write to stdout
|
|
147
|
+
plugins: [
|
|
148
|
+
NotifyPlugin('- worker'),
|
|
149
|
+
],
|
|
150
|
+
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
if (options?.verbose) {
|
|
154
|
+
console.info(' worker build size: ' + FormatSize(result.outputFiles[0].text.length));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// here's where we use that name as a key
|
|
158
|
+
|
|
159
|
+
const inputs = result.metafile.outputs['worker'].inputs;
|
|
160
|
+
const watchFiles = Object.keys(inputs).map(relative => path.resolve(relative));
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
errors: result.errors,
|
|
164
|
+
warnings: result.warnings,
|
|
165
|
+
loader: 'text',
|
|
166
|
+
contents: result.outputFiles[0].text,
|
|
167
|
+
watchFiles,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
|
|
173
|
+
// on error, we pass the file that threw as a dependency so we can
|
|
174
|
+
// watch updates and trigger a rebuild (nice that this works, btw)
|
|
175
|
+
|
|
176
|
+
const watchFiles = [];
|
|
177
|
+
for (const error of err.errors) {
|
|
178
|
+
if (error.location?.file) {
|
|
179
|
+
watchFiles.push(path.resolve(error.location.file));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
errors: err.errors,
|
|
184
|
+
watchFiles,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* @function
|
|
195
|
+
* @param {{verbose?: boolean, minify?: boolean}} [options]
|
|
196
|
+
* @returns {esbuild.Plugin}
|
|
197
|
+
*
|
|
198
|
+
* plugin loads html as string, optionally minified
|
|
199
|
+
*
|
|
200
|
+
*/
|
|
201
|
+
export const HTMLPlugin = (options) => ({
|
|
202
|
+
name: 'html',
|
|
203
|
+
setup(build) {
|
|
204
|
+
build.onLoad({ filter: /\.html$/ }, async (args) => {
|
|
205
|
+
|
|
206
|
+
if (options?.verbose) {
|
|
207
|
+
console.info('html:', args.path);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const text = await fs.readFile(args.path, 'utf8');
|
|
211
|
+
return {
|
|
212
|
+
contents: options?.minify ? minify(text, html_minifier_options) : text,
|
|
213
|
+
loader: 'text',
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @function
|
|
221
|
+
* @param {{verbose?: boolean, minify?: boolean}} [options]
|
|
222
|
+
* @returns {esbuild.Plugin}
|
|
223
|
+
*
|
|
224
|
+
* plugin compiles sass and returns generated css as string, optionally minified
|
|
225
|
+
*/
|
|
226
|
+
export const SassPlugin = (options) => ({
|
|
227
|
+
name: 'sass',
|
|
228
|
+
setup(build) {
|
|
229
|
+
build.onLoad({ filter: /\.scss$/ }, async (args) => {
|
|
230
|
+
|
|
231
|
+
if (options?.verbose) {
|
|
232
|
+
console.info('sass:', args.path);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
|
|
237
|
+
const result = await sass.compile(args.path, {
|
|
238
|
+
loadPaths: ['.'],
|
|
239
|
+
// charset: false,
|
|
240
|
+
// style: 'compressed',
|
|
241
|
+
});
|
|
242
|
+
const files = (result.loadedUrls || []).map(url => url.pathname);
|
|
243
|
+
|
|
244
|
+
let contents = result.css;
|
|
245
|
+
if (options?.minify) {
|
|
246
|
+
const minified = await postcss([cssnano]).process(result.css, { from: undefined });
|
|
247
|
+
contents = minified.css;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
contents,
|
|
252
|
+
loader: 'text',
|
|
253
|
+
watchFiles: files,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
const watchFiles = [];
|
|
259
|
+
if (err.span?.file?.url?.path) {
|
|
260
|
+
watchFiles.push(path.resolve(err.span.file.url.path));
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
errors: [{
|
|
264
|
+
text: err.message,
|
|
265
|
+
// ...location...
|
|
266
|
+
}],
|
|
267
|
+
watchFiles,
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trebco/treb",
|
|
3
|
-
"version": "25.
|
|
3
|
+
"version": "25.4.2",
|
|
4
4
|
"license": "LGPL-3.0-or-later",
|
|
5
5
|
"homepage": "https://treb.app",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/trebco/treb.git"
|
|
9
9
|
},
|
|
10
|
-
"main": "
|
|
11
|
-
"types": "
|
|
10
|
+
"main": "dist/treb-spreadsheet.mjs",
|
|
11
|
+
"types": "dist/treb.d.ts",
|
|
12
12
|
"type": "module",
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@types/html-minifier": "^4.0.2",
|
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
"treb-utils": "file:treb-utils",
|
|
33
33
|
"ts-node-dev": "^2.0.0",
|
|
34
34
|
"tslib": "^2.2.0",
|
|
35
|
-
"typescript": "^
|
|
35
|
+
"typescript": "^5.0.2"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "node esbuild-custom-element.mjs",
|
|
39
|
+
"build-light": "node esbuild-custom-element.mjs --no-xlsx --output-filename treb-spreadsheet-light.mjs",
|
|
39
40
|
"dev": "node esbuild-custom-element.mjs --dev",
|
|
40
41
|
"clean": "rm -fr build dist declaration",
|
|
41
42
|
"watch": "node --watch esbuild-custom-element.mjs --watch --dev",
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This file is part of TREB.
|
|
3
|
-
*
|
|
4
|
-
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
-
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
-
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
-
* later version.
|
|
8
|
-
*
|
|
9
|
-
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
-
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
-
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
-
* details.
|
|
13
|
-
*
|
|
14
|
-
* You should have received a copy of the GNU General Public License along
|
|
15
|
-
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
-
*
|
|
17
|
-
* Copyright 2022-2023 trebco, llc.
|
|
18
|
-
* info@treb.app
|
|
19
|
-
*
|
|
20
|
-
*/
|
|
21
|
-
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of TREB.
|
|
3
|
+
*
|
|
4
|
+
* TREB is free software: you can redistribute it and/or modify it under the
|
|
5
|
+
* terms of the GNU General Public License as published by the Free Software
|
|
6
|
+
* Foundation, either version 3 of the License, or (at your option) any
|
|
7
|
+
* later version.
|
|
8
|
+
*
|
|
9
|
+
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
10
|
+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
11
|
+
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
12
|
+
* details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU General Public License along
|
|
15
|
+
* with TREB. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*
|
|
17
|
+
* Copyright 2022-2023 trebco, llc.
|
|
18
|
+
* info@treb.app
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
22
|
// import { Parser } from 'treb-parser';
|
|
23
23
|
|
|
24
24
|
import type { Area, IArea } from './area';
|
|
25
25
|
import type { Style } from './style';
|
|
26
26
|
import type { TextPart } from './text_part';
|
|
27
|
-
import {
|
|
27
|
+
import type { Complex } from './value-type';
|
|
28
|
+
import { ValueType, GetValueType } from './value-type';
|
|
28
29
|
import type { CellValue, UnionValue } from './union';
|
|
29
30
|
import type { PreparedText } from './render_text';
|
|
30
31
|
import type { Table } from './table';
|