sqlmath 0.0.1 → 2021.11.20

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 (96) hide show
  1. package/.npmignore +10 -0
  2. package/CHANGELOG.md +53 -2
  3. package/LICENSE +16 -22
  4. package/README.md +18 -219
  5. package/_binary_sqlmath_napi8_darwin_x64.node +0 -0
  6. package/_binary_sqlmath_napi8_linux_x64.node +0 -0
  7. package/_binary_sqlmath_napi8_win32_x64.node +0 -0
  8. package/jslint.mjs +10998 -0
  9. package/package.json +23 -8
  10. package/sqlmath.mjs +1713 -0
  11. package/.gitconfig +0 -25
  12. package/.github/workflows/ci.yml +0 -61
  13. package/.gitignore +0 -24
  14. package/extension-functions.c +0 -2047
  15. package/jslint_ci.sh +0 -1968
  16. package/node_sqlite3.cc +0 -11877
  17. package/sqlite-autoconf-3360000/INSTALL +0 -370
  18. package/sqlite-autoconf-3360000/Makefile.am +0 -20
  19. package/sqlite-autoconf-3360000/Makefile.fallback +0 -19
  20. package/sqlite-autoconf-3360000/Makefile.in +0 -1028
  21. package/sqlite-autoconf-3360000/Makefile.msc +0 -1037
  22. package/sqlite-autoconf-3360000/README.txt +0 -113
  23. package/sqlite-autoconf-3360000/Replace.cs +0 -223
  24. package/sqlite-autoconf-3360000/aclocal.m4 +0 -10199
  25. package/sqlite-autoconf-3360000/compile +0 -347
  26. package/sqlite-autoconf-3360000/config.guess +0 -1480
  27. package/sqlite-autoconf-3360000/config.sub +0 -1801
  28. package/sqlite-autoconf-3360000/configure +0 -16135
  29. package/sqlite-autoconf-3360000/configure.ac +0 -285
  30. package/sqlite-autoconf-3360000/depcomp +0 -791
  31. package/sqlite-autoconf-3360000/install-sh +0 -508
  32. package/sqlite-autoconf-3360000/ltmain.sh +0 -11156
  33. package/sqlite-autoconf-3360000/missing +0 -215
  34. package/sqlite-autoconf-3360000/shell.c +0 -22381
  35. package/sqlite-autoconf-3360000/sqlite3.1 +0 -286
  36. package/sqlite-autoconf-3360000/sqlite3.c +0 -235517
  37. package/sqlite-autoconf-3360000/sqlite3.h +0 -12353
  38. package/sqlite-autoconf-3360000/sqlite3.pc.in +0 -13
  39. package/sqlite-autoconf-3360000/sqlite3.rc +0 -83
  40. package/sqlite-autoconf-3360000/sqlite3ext.h +0 -663
  41. package/sqlite-autoconf-3360000/sqlite3rc.h +0 -3
  42. package/sqlite-autoconf-3360000/tea/Makefile.in +0 -440
  43. package/sqlite-autoconf-3360000/tea/README +0 -36
  44. package/sqlite-autoconf-3360000/tea/aclocal.m4 +0 -9
  45. package/sqlite-autoconf-3360000/tea/configure +0 -9989
  46. package/sqlite-autoconf-3360000/tea/configure.ac +0 -201
  47. package/sqlite-autoconf-3360000/tea/doc/sqlite3.n +0 -15
  48. package/sqlite-autoconf-3360000/tea/generic/tclsqlite3.c +0 -4016
  49. package/sqlite-autoconf-3360000/tea/license.terms +0 -6
  50. package/sqlite-autoconf-3360000/tea/pkgIndex.tcl.in +0 -7
  51. package/sqlite-autoconf-3360000/tea/tclconfig/install-sh +0 -528
  52. package/sqlite-autoconf-3360000/tea/tclconfig/tcl.m4 +0 -4168
  53. package/sqlite-autoconf-3360000/tea/win/makefile.vc +0 -419
  54. package/sqlite-autoconf-3360000/tea/win/nmakehlp.c +0 -815
  55. package/sqlite-autoconf-3360000/tea/win/rules.vc +0 -711
  56. package/sqlmath.js +0 -238
  57. package/test/backup.test.js +0 -279
  58. package/test/blob.test.js +0 -54
  59. package/test/cache.test.js +0 -42
  60. package/test/constants.test.js +0 -44
  61. package/test/database_fail.test.js +0 -153
  62. package/test/each.test.js +0 -39
  63. package/test/exec.test.js +0 -39
  64. package/test/extension.test.js +0 -26
  65. package/test/extension_functions.test.js +0 -29
  66. package/test/fts-content.test.js +0 -13
  67. package/test/interrupt.test.js +0 -80
  68. package/test/issue-108.test.js +0 -28
  69. package/test/json.test.js +0 -22
  70. package/test/map.test.js +0 -63
  71. package/test/named_columns.test.js +0 -38
  72. package/test/named_params.test.js +0 -69
  73. package/test/null_error.test.js +0 -41
  74. package/test/nw/.gitignore +0 -3
  75. package/test/nw/Makefile +0 -39
  76. package/test/nw/index.html +0 -14
  77. package/test/nw/package.json +0 -9
  78. package/test/open_close.test.js +0 -187
  79. package/test/other_objects.test.js +0 -98
  80. package/test/parallel_insert.test.js +0 -44
  81. package/test/prepare.test.js +0 -427
  82. package/test/profile.test.js +0 -57
  83. package/test/rerun.test.js +0 -50
  84. package/test/scheduling.test.js +0 -44
  85. package/test/serialization.test.js +0 -104
  86. package/test/support/createdb-electron.js +0 -10
  87. package/test/support/createdb.js +0 -47
  88. package/test/support/elmo.png +0 -0
  89. package/test/support/helper.js +0 -37
  90. package/test/support/script.sql +0 -70
  91. package/test/trace.test.js +0 -67
  92. package/test/unicode.test.js +0 -114
  93. package/test/upsert.test.js +0 -27
  94. package/test/verbose.test.js +0 -60
  95. package/test.js +0 -141
  96. package/test.slr.mjs +0 -212
package/jslint_ci.sh DELETED
@@ -1,1968 +0,0 @@
1
- #!/bin/sh
2
-
3
- # POSIX reference
4
- # http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
5
- # http://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
6
-
7
- # sh one-liner
8
- #
9
- # git branch -d -r origin/aa
10
- # git config --global diff.algorithm histogram
11
- # git fetch origin alpha beta master && git fetch upstream alpha beta master
12
- # git fetch origin alpha beta master --tags
13
- # git fetch upstream "refs/tags/*:refs/tags/*"
14
- # git ls-files --stage | sort
15
- # git ls-remote --heads origin
16
- # git update-index --chmod=+x aa.js
17
- # head CHANGELOG.md -n50
18
- # ln -f jslint.mjs ~/jslint.mjs
19
- # openssl rand -base64 32 # random key
20
- # sh jslint_ci.sh shCiBranchPromote origin alpha beta
21
- # sh jslint_ci.sh shRunWithScreenshotTxt .build/screenshot-changelog.svg head -n50 CHANGELOG.md
22
- # vim rgx-lowercase \L\1\e
23
-
24
- shBrowserScreenshot() {(set -e
25
- # this function will run headless-chrome to screenshot url $1 with
26
- # window-size $2
27
- node --input-type=module -e '
28
- import moduleChildProcess from "child_process";
29
- import modulePath from "path";
30
- import moduleUrl from "url";
31
- // init debugInline
32
- (function () {
33
- let consoleError = console.error;
34
- globalThis.debugInline = globalThis.debugInline || function (...argList) {
35
-
36
- // this function will both print <argList> to stderr and return <argList>[0]
37
-
38
- consoleError("\n\ndebugInline");
39
- consoleError(...argList);
40
- consoleError("\n");
41
- return argList[0];
42
- };
43
- }());
44
- (function () {
45
- let file;
46
- let timeStart;
47
- let url;
48
- if (process.platform !== "linux") {
49
- return;
50
- }
51
- timeStart = Date.now();
52
- url = process.argv[1];
53
- if (!(
54
- /^\w+?:/
55
- ).test(url)) {
56
- url = modulePath.resolve(url);
57
- }
58
- file = moduleUrl.parse(url).pathname;
59
- // remove prefix $PWD from file
60
- if (String(file + "/").startsWith(process.cwd() + "/")) {
61
- file = file.replace(process.cwd(), "");
62
- }
63
- file = ".build/screenshot-browser-" + encodeURIComponent(file).replace((
64
- /%/g
65
- ), "_").toLowerCase() + ".png";
66
- moduleChildProcess.spawn(
67
- (
68
- process.platform === "darwin"
69
- ? "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
70
- : process.platform === "win32"
71
- ? "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
72
- : "/usr/bin/google-chrome-stable"
73
- ),
74
- [
75
- "--headless",
76
- "--ignore-certificate-errors",
77
- "--incognito",
78
- "--screenshot",
79
- "--timeout=30000",
80
- "--user-data-dir=/dev/null",
81
- "--window-size=800x600",
82
- "-screenshot=" + file,
83
- (
84
- (process.getuid && process.getuid() === 0)
85
- ? "--no-sandbox"
86
- : ""
87
- ),
88
- url
89
- ].concat(process.argv.filter(function (elem) {
90
- return elem.startsWith("-");
91
- })).filter(function (elem) {
92
- return elem;
93
- }),
94
- {
95
- stdio: [
96
- "ignore", 1, 2
97
- ]
98
- }
99
- ).on("exit", function (exitCode) {
100
- console.error(
101
- "shBrowserScreenshot"
102
- + "\n - url - " + url
103
- + "\n - wrote - " + file
104
- + "\n - timeElapsed - " + (Date.now() - timeStart) + " ms"
105
- + "\n - EXIT_CODE=" + exitCode
106
- );
107
- });
108
- }());
109
- ' "$@" # "'
110
- )}
111
-
112
- shCiArtifactUpload() {(set -e
113
- # this function will upload build-artifacts to branch-gh-pages
114
- local BRANCH
115
- local SIZE
116
- node --input-type=module -e '
117
- process.exit(Number(
118
- `${process.version.split(".")[0]}.${process.arch}.${process.platform}` !==
119
- process.env.CI_NODE_VERSION_ARCH_PLATFORM
120
- ));
121
- ' || return 0
122
- # init $BRANCH
123
- BRANCH="$(git rev-parse --abbrev-ref HEAD)"
124
- git pull --unshallow origin "$BRANCH"
125
- # init .git/config
126
- git config --local user.email "github-actions@users.noreply.github.com"
127
- git config --local user.name "github-actions"
128
- # screenshot asset-image-jslint
129
- shImageJslintCreate &
130
- # screenshot web-demo
131
- shBrowserScreenshot \
132
- https://jslint-org.github.io/jslint/branch-beta/index.html
133
- node --input-type=module -e '
134
- import moduleFs from "fs";
135
- import moduleChildProcess from "child_process";
136
- (async function () {
137
- let screenshotCurl = await moduleFs.promises.stat("jslint.mjs");
138
- screenshotCurl = String(`
139
- echo "\
140
- % Total % Received % Xferd Average Speed Time Time Time Current
141
- Dload Upload Total Spent Left Speed
142
- 100 250k 100 250k 0 0 250k 0 0:00:01 --:--:-- 0:00:01 250k\
143
- "
144
- `).trim().replace((
145
- /250/g
146
- ), Math.floor(screenshotCurl.size / 1024));
147
- [
148
- // parallel-task - screenshot files
149
- [
150
- "shRunWithScreenshotTxt",
151
- ".build/screenshot-files.svg",
152
- "shGitLsTree"
153
- ],
154
- // parallel-task - screenshot changelog
155
- [
156
- "shRunWithScreenshotTxt",
157
- ".build/screenshot-changelog.svg",
158
- "head",
159
- "-n50",
160
- "CHANGELOG.md"
161
- ]
162
- ].forEach(function (argList) {
163
- moduleChildProcess.spawn("./jslint_ci.sh", argList, {
164
- stdio: [
165
- "ignore", 1, 2
166
- ]
167
- }).on("exit", function (exitCode) {
168
- if (exitCode) {
169
- process.exit(exitCode);
170
- }
171
- });
172
- });
173
- // parallel-task - screenshot example-shell-commands in README.md
174
- Array.from(String(
175
- await moduleFs.promises.readFile("README.md", "utf8")
176
- ).matchAll(
177
- /\n```shell\u0020<!--\u0020shRunWithScreenshotTxt\u0020(.*?)\u0020-->\n([\S\s]*?\n)```\n/g
178
- )).forEach(async function ([
179
- ignore, file, script
180
- ]) {
181
- await moduleFs.promises.writeFile(file + ".sh", (
182
- "printf \u0027"
183
- + script.trim().replace((
184
- /[%\\]/gm
185
- ), "$&$&").replace((
186
- /\u0027/g
187
- ), "\u0027\"\u0027\"\u0027").replace((
188
- /^/gm
189
- ), "> ")
190
- + "\n\n\n\u0027\n"
191
- + script.replace(
192
- "curl -L https://www.jslint.com/jslint.mjs > jslint.mjs",
193
- screenshotCurl
194
- )
195
- ));
196
- moduleChildProcess.spawn(
197
- "./jslint_ci.sh",
198
- [
199
- "shRunWithScreenshotTxt",
200
- file,
201
- "sh",
202
- file + ".sh"
203
- ],
204
- {
205
- stdio: [
206
- "ignore", 1, 2
207
- ]
208
- }
209
- );
210
- });
211
- }());
212
- ' # '
213
- # seo - inline css-assets and invalidate cached-assets
214
- node --input-type=module -e '
215
- import moduleFs from "fs";
216
- (async function () {
217
- let cacheKey = Math.random().toString(36).slice(-4);
218
- let fileDict = {};
219
- await Promise.all([
220
- "asset-codemirror-rollup.css",
221
- "browser.mjs",
222
- "index.html"
223
- ].map(async function (file) {
224
- fileDict[file] = await moduleFs.promises.readFile(file, "utf8");
225
- }));
226
-
227
- // Inline css-assets.
228
-
229
- fileDict["index.html"] = fileDict["index.html"].replace((
230
- "\n<link rel=\"stylesheet\" href=\"asset-codemirror-rollup.css\">\n"
231
- ), function () {
232
- return (
233
- "\n<style>\n"
234
- + fileDict["asset-codemirror-rollup.css"].trim()
235
- + "\n</style>\n"
236
- );
237
- });
238
- fileDict["index.html"] = fileDict["index.html"].replace((
239
- "\n<style class=\"JSLINT_REPORT_STYLE\"></style>\n"
240
- ), function () {
241
- return fileDict["browser.mjs"].match(
242
- /\n<style\sclass="JSLINT_REPORT_STYLE">\n[\S\s]*?\n<\/style>\n/
243
- )[0];
244
- });
245
-
246
- // Invalidate cached-assets.
247
-
248
- fileDict["browser.mjs"] = fileDict["browser.mjs"].replace((
249
- /^import\u0020.+?\u0020from\u0020".+?\.(?:js|mjs)\b/gm
250
- ), function (match0) {
251
- return `${match0}?cc=${cacheKey}`;
252
- });
253
- fileDict["index.html"] = fileDict["index.html"].replace((
254
- /\b(?:href|src)=".+?\.(?:css|js|mjs)\b/g
255
- ), function (match0) {
256
- return `${match0}?cc=${cacheKey}`;
257
- });
258
-
259
- // Write file.
260
-
261
- await Promise.all(Object.entries(fileDict).map(function ([
262
- file, data
263
- ]) {
264
- moduleFs.promises.writeFile(file, data);
265
- }));
266
- }());
267
- ' # '
268
- # add dir .build
269
- git add -f .build jslint.cjs jslint.js
270
- git commit -am "add dir .build"
271
- # checkout branch-gh-pages
272
- git checkout -b gh-pages
273
- git fetch origin gh-pages
274
- git reset --hard origin/gh-pages
275
- # update dir branch-$BRANCH
276
- rm -rf "branch-$BRANCH"
277
- mkdir "branch-$BRANCH"
278
- (set -e
279
- cd "branch-$BRANCH"
280
- git init -b branch1
281
- git pull --depth=1 .. "$BRANCH"
282
- rm -rf .git
283
- git add -f .
284
- )
285
- # update root-dir with branch-beta
286
- if [ "$BRANCH" = beta ]
287
- then
288
- git rm -rf .build
289
- git checkout beta .
290
- fi
291
- # update README.md with branch-$BRANCH and $GITHUB_REPOSITORY
292
- sed -i \
293
- -e "s|/branch-[0-9A-Z_a-z]*/|/branch-$BRANCH/|g" \
294
- -e "s|\bjslint-org/jslint\b|$GITHUB_REPOSITORY|g" \
295
- -e "s|\bjslint-org\.github\.io/jslint\b|$(
296
- printf "$GITHUB_REPOSITORY" | sed -e "s|/|.github.io/|"
297
- )|g" \
298
- "branch-$BRANCH/README.md"
299
- git status
300
- git commit -am "update dir branch-$BRANCH" || true
301
- # if branch-gh-pages has more than 100 commits,
302
- # then backup and squash commits
303
- if [ "$(git rev-list --count gh-pages)" -gt 100 ]
304
- then
305
- # backup
306
- shGitCmdWithGithubToken push origin -f gh-pages:gh-pages-backup
307
- # squash commits
308
- git checkout --orphan squash1
309
- git commit --quiet -am squash || true
310
- # reset branch-gh-pages to squashed-commit
311
- git push . -f squash1:gh-pages
312
- git checkout gh-pages
313
- # force-push squashed-commit
314
- shGitCmdWithGithubToken push origin -f gh-pages
315
- fi
316
- # list files
317
- shGitLsTree
318
- # push branch-gh-pages
319
- shGitCmdWithGithubToken push origin gh-pages
320
- # validate http-links
321
- (set -e
322
- cd "branch-$BRANCH"
323
- sleep 15
324
- shDirHttplinkValidate
325
- )
326
- )}
327
-
328
- shCiBase() {(set -e
329
- # this function will run base-ci
330
- )}
331
-
332
- shCiBranchPromote() {(set -e
333
- # this function will promote branch $REMOTE/$BRANCH1 to branch $REMOTE/$BRANCH2
334
- local BRANCH1
335
- local BRANCH2
336
- local REMOTE
337
- REMOTE="$1"
338
- shift
339
- BRANCH1="$1"
340
- shift
341
- BRANCH2="$1"
342
- shift
343
- git fetch "$REMOTE" "$BRANCH1"
344
- git push "$REMOTE" "$REMOTE/$BRANCH1:$BRANCH2" "$@"
345
- )}
346
-
347
- shDirHttplinkValidate() {(set -e
348
- # this function will validate http-links embedded in .html and .md files
349
- node --input-type=module -e '
350
- import moduleFs from "fs";
351
- import moduleHttps from "https";
352
- import moduleUrl from "url";
353
- (async function () {
354
- let dict = {};
355
- Array.from(
356
- await moduleFs.promises.readdir(".")
357
- ).forEach(async function (file) {
358
- let data;
359
- if (!(
360
- /.\.html$|.\.md$/m
361
- ).test(file)) {
362
- return;
363
- }
364
- data = await moduleFs.promises.readFile(file, "utf8");
365
- data.replace((
366
- /\bhttps?:\/\/.*?(?:[\s")\]]|\W?$)/gm
367
- ), function (url) {
368
- let req;
369
- url = url.slice(0, -1).replace((
370
- /[\u0022\u0027]/g
371
- ), "").replace((
372
- /\/branch-\w+?\//g
373
- ), "/branch-alpha/").replace((
374
- /\bjslint-org\/jslint\b/g
375
- ), process.env.GITHUB_REPOSITORY || "jslint-org/jslint").replace((
376
- /\bjslint-org\.github\.io\/jslint\b/g
377
- ), String(
378
- process.env.GITHUB_REPOSITORY || "jslint-org/jslint"
379
- ).replace("/", ".github.io/"));
380
- if (url.startsWith("http://")) {
381
- throw new Error("shDirHttplinkValidate - insecure link " + url);
382
- }
383
- // ignore duplicate-link
384
- if (dict.hasOwnProperty(url)) {
385
- return "";
386
- }
387
- dict[url] = true;
388
- req = moduleHttps.request(moduleUrl.parse(
389
- url
390
- ), function (res) {
391
- console.error(
392
- "shDirHttplinkValidate " + res.statusCode + " " + url
393
- );
394
- if (!(res.statusCode < 400)) {
395
- throw new Error(
396
- "shDirHttplinkValidate - " + file
397
- + " - unreachable link " + url
398
- );
399
- }
400
- req.abort();
401
- res.destroy();
402
- });
403
- req.setTimeout(30000);
404
- req.end();
405
- return "";
406
- });
407
- data.replace((
408
- /(\bhref=|\bsrc=|\burl\(|\[[^]*?\]\()("?.*?)(?:[")\]]|$)/gm
409
- ), function (ignore, linkType, url) {
410
- if (!linkType.startsWith("[")) {
411
- url = url.slice(1);
412
- }
413
- if (url.length === 0 || url.startsWith("data:")) {
414
- return;
415
- }
416
- // ignore duplicate-link
417
- if (dict.hasOwnProperty(url)) {
418
- return "";
419
- }
420
- dict[url] = true;
421
- if (!(
422
- /^https?|^mailto:|^[#\/]/m
423
- ).test(url)) {
424
- moduleFs.stat(url.split("?")[0], function (ignore, exists) {
425
- console.error(
426
- "shDirHttplinkValidate " + Boolean(exists) + " " + url
427
- );
428
- if (!exists) {
429
- throw new Error(
430
- "shDirHttplinkValidate - " + file
431
- + " - unreachable link " + url
432
- );
433
- }
434
- });
435
- }
436
- return "";
437
- });
438
- });
439
- }());
440
- ' # "'
441
- )}
442
-
443
- shGitCmdWithGithubToken() {(set -e
444
- # this function will run git $CMD with $GITHUB_TOKEN
445
- local CMD
446
- local EXIT_CODE
447
- local REMOTE
448
- local URL
449
- printf "shGitCmdWithGithubToken $*\n"
450
- CMD="$1"
451
- shift
452
- REMOTE="$1"
453
- shift
454
- URL="$(
455
- git config "remote.$REMOTE.url" \
456
- | sed -e "s|https://|https://x-access-token:$GITHUB_TOKEN@|"
457
- )"
458
- EXIT_CODE=0
459
- # hide $GITHUB_TOKEN in case of err
460
- git "$CMD" "$URL" "$@" 2>/dev/null || EXIT_CODE="$?"
461
- printf "shGitCmdWithGithubToken - EXIT_CODE=$EXIT_CODE\n" 1>&2
462
- return "$EXIT_CODE"
463
- )}
464
-
465
- shGitLsTree() {(set -e
466
- # this function will "git ls-tree" all files committed in HEAD
467
- # example use:
468
- # shGitLsTree | sort -rk3 # sort by date
469
- # shGitLsTree | sort -rk4 # sort by size
470
- node --input-type=module -e '
471
- import moduleChildProcess from "child_process";
472
- (async function () {
473
- let result;
474
- // get file, mode, size
475
- result = await new Promise(function (resolve) {
476
- result = "";
477
- moduleChildProcess.spawn("git", [
478
- "ls-tree", "-lr", "HEAD"
479
- ], {
480
- encoding: "utf8",
481
- stdio: [
482
- "ignore", "pipe", 2
483
- ]
484
- }).on("exit", function () {
485
- resolve(result);
486
- }).stdout.on("data", function (chunk) {
487
- result += chunk;
488
- }).setEncoding("utf8");
489
- });
490
- result = Array.from(result.matchAll(
491
- /^(\S+?)\u0020+?\S+?\u0020+?\S+?\u0020+?(\S+?)\t(\S+?)$/gm
492
- )).map(function ([
493
- ignore, mode, size, file
494
- ]) {
495
- return {
496
- file,
497
- mode: mode.slice(-3),
498
- size: Number(size)
499
- };
500
- });
501
- result = result.sort(function (aa, bb) {
502
- return aa.file > bb.file || -1;
503
- });
504
- result = result.slice(0, 1000);
505
- result.unshift({
506
- file: ".",
507
- mode: "755",
508
- size: 0
509
- });
510
- // get date
511
- result.forEach(function (elem) {
512
- result[0].size += elem.size;
513
- moduleChildProcess.spawn("git", [
514
- "log", "--max-count=1", "--format=%at", elem.file
515
- ], {
516
- stdio: [
517
- "ignore", "pipe", 2
518
- ]
519
- }).stdout.on("data", function (chunk) {
520
- elem.date = new Date(
521
- Number(chunk) * 1000
522
- ).toISOString().slice(0, 19) + "Z";
523
- });
524
- });
525
- process.on("exit", function () {
526
- let iiPad;
527
- let sizePad;
528
- iiPad = String(result.length).length + 1;
529
- sizePad = String(Math.ceil(result[0].size / 1024)).length;
530
- process.stdout.write(result.map(function (elem, ii) {
531
- return (
532
- String(ii + ".").padStart(iiPad, " ")
533
- + " " + elem.mode
534
- + " " + elem.date
535
- + " " + String(
536
- Math.ceil(elem.size / 1024)
537
- ).padStart(sizePad, " ") + " KB"
538
- + " " + elem.file
539
- + "\n"
540
- );
541
- }).join(""));
542
- });
543
- }());
544
- ' # "'
545
- )}
546
-
547
- shHttpFileServer() {(set -e
548
- # this function will run simple node http-file-server on port $PORT
549
- if [ ! "$npm_config_mode_auto_restart" ]
550
- then
551
- local EXIT_CODE
552
- EXIT_CODE=0
553
- export npm_config_mode_auto_restart=1
554
- while true
555
- do
556
- printf "\n"
557
- git diff --color 2>/dev/null | cat || true
558
- printf "\nshHttpFileServer - (re)starting $*\n"
559
- (shHttpFileServer "$@") || EXIT_CODE="$?"
560
- printf "process exited with code $EXIT_CODE\n"
561
- # if $EXIT_CODE != 77, then exit process
562
- # http://en.wikipedia.org/wiki/Unix_signal
563
- if [ "$EXIT_CODE" != 77 ]
564
- then
565
- break
566
- fi
567
- # else restart process after 1 second
568
- sleep 1
569
- done
570
- return
571
- fi
572
- node --input-type=module -e '
573
- import moduleChildProcess from "child_process";
574
- import moduleFs from "fs";
575
- import moduleHttp from "http";
576
- import modulePath from "path";
577
- import moduleRepl from "repl";
578
- import moduleUrl from "url";
579
- // init debugInline
580
- (function () {
581
- let consoleError = console.error;
582
- globalThis.debugInline = globalThis.debugInline || function (...argList) {
583
-
584
- // this function will both print <argList> to stderr and return <argList>[0]
585
-
586
- consoleError("\n\ndebugInline");
587
- consoleError(...argList);
588
- consoleError("\n");
589
- return argList[0];
590
- };
591
- }());
592
- (async function httpFileServer() {
593
- /*
594
- * this function will start http-file-server
595
- */
596
- let contentTypeDict = {
597
- ".bmp": "image/bmp",
598
- ".cjs": "application/javascript; charset=utf-8",
599
- ".css": "text/css; charset=utf-8",
600
- ".gif": "image/gif",
601
- ".htm": "text/html; charset=utf-8",
602
- ".html": "text/html; charset=utf-8",
603
- ".jpe": "image/jpeg",
604
- ".jpeg": "image/jpeg",
605
- ".jpg": "image/jpeg",
606
- ".js": "application/javascript; charset=utf-8",
607
- ".json": "application/json; charset=utf-8",
608
- ".md": "text/markdown; charset=utf-8",
609
- ".mjs": "application/javascript; charset=utf-8",
610
- ".pdf": "application/pdf",
611
- ".png": "image/png",
612
- ".svg": "image/svg+xml; charset=utf-8",
613
- ".txt": "text/plain; charset=utf-8",
614
- ".wasm": "application/wasm",
615
- ".woff": "font/woff",
616
- ".woff2": "font/woff2",
617
- ".xml": "application/xml; charset=utf-8",
618
- "/": "text/html; charset=utf-8"
619
- };
620
- if (process.argv[1]) {
621
- await import("file://" + modulePath.resolve(process.argv[1]));
622
- }
623
- process.env.PORT = process.env.PORT || "8080";
624
- console.error("http-file-server listening on port " + process.env.PORT);
625
- moduleHttp.createServer(function (req, res) {
626
- let file;
627
- let pathname;
628
- let timeStart;
629
- // init timeStart
630
- timeStart = Date.now();
631
- // init pathname
632
- pathname = moduleUrl.parse(req.url).pathname;
633
- // debug - serverLog
634
- res.on("close", function () {
635
- if (pathname === "/favicon.ico") {
636
- return;
637
- }
638
- console.error(
639
- "serverLog - " +
640
- new Date(timeStart).toISOString() + " - " +
641
- (Date.now() - timeStart) + "ms - " +
642
- (res.statusCode || 0) + " " + req.method + " " + pathname
643
- );
644
- });
645
- // debug - echo request
646
- if (pathname === "/echo") {
647
- res.write(JSON.stringify(req.headers, undefined, 4) + "\n");
648
- req.pipe(res);
649
- return;
650
- }
651
- // replace trailing "/" with "/index.html"
652
- file = pathname.slice(1).replace((
653
- /\/$/
654
- ), "/index.html");
655
- // resolve file
656
- file = modulePath.resolve(file);
657
- // security - disable parent-directory lookup
658
- if (!file.startsWith(process.cwd() + modulePath.sep)) {
659
- res.statusCode = 404;
660
- res.end();
661
- return;
662
- }
663
- moduleFs.readFile(file, function (err, data) {
664
- let contentType;
665
- if (err) {
666
- res.statusCode = 404;
667
- res.end();
668
- return;
669
- }
670
- contentType = contentTypeDict[(
671
- /^\/$|\.[^.]*?$|$/m
672
- ).exec(file)[0]];
673
- if (contentType) {
674
- res.setHeader("content-type", contentType);
675
- }
676
- res.end(data);
677
- });
678
- }).listen(process.env.PORT);
679
- }());
680
- (function jslintDir() {
681
- /*
682
- * this function will jslint current-directory
683
- */
684
- moduleFs.stat((
685
- process.env.HOME + "/jslint.mjs"
686
- ), function (ignore, exists) {
687
- if (exists) {
688
- moduleChildProcess.spawn("node", [
689
- process.env.HOME + "/jslint.mjs", "."
690
- ], {
691
- stdio: [
692
- "ignore", 1, 2
693
- ]
694
- });
695
- }
696
- });
697
- }());
698
- (function replStart() {
699
- /*
700
- * this function will start repl-debugger
701
- */
702
- let that;
703
- // start repl
704
- that = moduleRepl.start({
705
- useGlobal: true
706
- });
707
- // init history
708
- that.setupHistory(modulePath.resolve(
709
- process.env.HOME + "/.node_repl_history"
710
- ), function () {
711
- return;
712
- });
713
- // save eval-function
714
- that.evalDefault = that.eval;
715
- // hook custom-eval-function
716
- that.eval = function (script, context, file, onError) {
717
- script.replace((
718
- /^(\S+)\u0020(.*?)\n/
719
- ), function (ignore, match1, match2) {
720
- switch (match1) {
721
- // syntax-sugar - run shell-cmd
722
- case "$":
723
- switch (match2.split(" ").slice(0, 2).join(" ")) {
724
- // syntax-sugar - run git diff
725
- case "git diff":
726
- match2 += " --color";
727
- break;
728
- // syntax-sugar - run git log
729
- case "git log":
730
- match2 += " -n 10";
731
- break;
732
- // syntax-sugar - run ll
733
- case "ll":
734
- match2 = "ls -Fal";
735
- break;
736
- }
737
- match2 = match2.replace((
738
- /^git\u0020/
739
- ), "git --no-pager ");
740
- // run shell-cmd
741
- console.error("$ " + match2);
742
- moduleChildProcess.spawn(match2, {
743
- shell: true,
744
- stdio: [
745
- "ignore", 1, 2
746
- ]
747
- // print exitCode
748
- }).on("exit", function (exitCode) {
749
- console.error("$ EXIT_CODE=" + exitCode);
750
- that.evalDefault("\n", context, file, onError);
751
- });
752
- script = "\n";
753
- break;
754
- // syntax-sugar - map text with charCodeAt
755
- case "charCode":
756
- console.error(
757
- match2.split("").map(function (chr) {
758
- return (
759
- "\\u" +
760
- chr.charCodeAt(0).toString(16).padStart(4, 0)
761
- );
762
- }).join("")
763
- );
764
- script = "\n";
765
- break;
766
- // syntax-sugar - sort chr
767
- case "charSort":
768
- console.error(JSON.stringify(match2.split("").sort().join("")));
769
- script = "\n";
770
- break;
771
- // syntax-sugar - list obj-keys, sorted by item-type
772
- // console.error(Object.keys(global).map(function(key){return(typeof global[key]===\u0027object\u0027&&global[key]&&global[key]===global[key]?\u0027global\u0027:typeof global[key])+\u0027 \u0027+key;}).sort().join(\u0027\n\u0027)) //jslint-quiet
773
- case "keys":
774
- script = (
775
- "console.error(Object.keys(" + match2 +
776
- ").map(function(key){return(" +
777
- "typeof " + match2 + "[key]===\u0027object\u0027&&" +
778
- match2 + "[key]&&" +
779
- match2 + "[key]===global[key]" +
780
- "?\u0027global\u0027" +
781
- ":typeof " + match2 + "[key]" +
782
- ")+\u0027 \u0027+key;" +
783
- "}).sort().join(\u0027\\n\u0027))\n"
784
- );
785
- break;
786
- // syntax-sugar - print String(val)
787
- case "print":
788
- script = "console.error(String(" + match2 + "))\n";
789
- break;
790
- }
791
- });
792
- // eval script
793
- that.evalDefault(script, context, file, onError);
794
- };
795
- }());
796
- (function watchDir() {
797
- /*
798
- * this function will watch current-directory for changes
799
- */
800
- moduleFs.readdir(".", function (ignore, fileList) {
801
- fileList.forEach(function (file) {
802
- if (file[0] === ".") {
803
- return;
804
- }
805
- moduleFs.stat(file, function (ignore, stats) {
806
- if (!(stats && stats.isFile())) {
807
- return;
808
- }
809
- moduleFs.watchFile(file, {
810
- interval: 1000,
811
- persistent: false
812
- }, function () {
813
- console.error("watchFile - modified - " + file);
814
- setTimeout(process.exit.bind(undefined, 77), 1000);
815
- });
816
- });
817
- });
818
- });
819
- }());
820
- ' "$@" # '
821
- )}
822
-
823
- shImageJslintCreate() {(set -e
824
- # this function will create .png logo of jslint
825
- echo '
826
- <!DOCTYPE html>
827
- <html lang="en">
828
- <head>
829
- <title>logo</title>
830
- <style>
831
- /* sh jslint_ci.sh shBrowserScreenshot asset-image-jslint.html --window-size=512x512 */
832
- /* csslint box-model:false */
833
- /* csslint ignore:start */
834
- *,
835
- *:after,
836
- *:before {
837
- box-sizing: border-box;
838
- }
839
- @font-face {
840
- font-family: Daley;
841
- font-weight: bold;
842
- src: url("asset-font-daley-bold.woff2") format("woff2");
843
- }
844
- /* csslint ignore:end */
845
- body,
846
- div {
847
- margin: 0;
848
- }
849
- .container1 {
850
- background: antiquewhite;
851
- border: 24px solid darkslategray;
852
- border-radius: 96px;
853
- color: darkslategray;
854
- font-family: Daley;
855
- height: 512px;
856
- margin: 0;
857
- position: relative;
858
- width: 512px;
859
- zoom: 100%;
860
- /*
861
- background: transparent;
862
- border: 24px solid black;
863
- color: black;
864
- */
865
- }
866
- .text1 {
867
- font-size: 256px;
868
- left: 44px;
869
- position: absolute;
870
- top: 32px;
871
- }
872
- .text2 {
873
- bottom: 8px;
874
- font-size: 192px;
875
- left: 44px;
876
- position: absolute;
877
- }
878
- </style>
879
- </head>
880
- <body>
881
- <div class="container1">
882
- <div class="text1">JS</div>
883
- <div class="text2">Lint</div>
884
- </div>
885
- </body>
886
- </html>
887
- ' > .build/asset-image-jslint-512.html
888
- cp asset-font-daley-bold.woff2 .build
889
- # screenshot asset-image-jslint-512.png
890
- shBrowserScreenshot .build/asset-image-jslint-512.html \
891
- --window-size=512x512 \
892
- -screenshot=.build/asset-image-jslint-512.png
893
- # create various smaller thumbnails
894
- for SIZE in 32 64 128 256
895
- do
896
- convert -resize "${SIZE}x${SIZE}" .build/asset-image-jslint-512.png \
897
- ".build/asset-image-jslint-$SIZE.png"
898
- printf \
899
- "shImageJslintCreate - wrote - .build/asset-image-jslint-$SIZE.png\n" 1>&2
900
- done
901
- # convert to svg @ https://convertio.co/png-svg/
902
- )}
903
-
904
- shImageToDataUri() {(set -e
905
- # this function will convert image $1 to data-uri string
906
- node --input-type=module -e '
907
- import moduleFs from "fs";
908
- import moduleHttps from "https";
909
- (async function () {
910
- let file;
911
- let result;
912
- file = process.argv[1];
913
- if ((
914
- /^https:\/\//
915
- ).test(file)) {
916
- result = await new Promise(function (resolve) {
917
- moduleHttps.get(file, function (res) {
918
- let chunkList;
919
- chunkList = [];
920
- res.on("data", function (chunk) {
921
- chunkList.push(chunk);
922
- }).on("end", function () {
923
- resolve(Buffer.concat(chunkList));
924
- });
925
- });
926
- });
927
- } else {
928
- result = await moduleFs.promises.readFile(file);
929
- }
930
- result = String(
931
- "data:image/" + file.match(
932
- /\.[^.]*?$|$/m
933
- )[0].slice(1) + ";base64," + result.toString("base64")
934
- ).replace((
935
- /.{72}/g
936
- ), "$&\\\n");
937
- console.log(result);
938
- }());
939
- ' "$@" # '
940
- )}
941
-
942
- shJsonNormalize() {(set -e
943
- # this function will
944
- # 1. read json-data from file $1
945
- # 2. normalize json-data
946
- # 3. write normalized json-data back to file $1
947
- node --input-type=module -e '
948
- import moduleFs from "fs";
949
- (async function () {
950
- function identity(val) {
951
-
952
- // This function will return <val>.
953
-
954
- return val;
955
- }
956
- function objectDeepCopyWithKeysSorted(obj) {
957
-
958
- // this function will recursively deep-copy <obj> with keys sorted
959
-
960
- let sorted;
961
- if (typeof obj !== "object" || !obj) {
962
- return obj;
963
- }
964
-
965
- // recursively deep-copy list with child-keys sorted
966
-
967
- if (Array.isArray(obj)) {
968
- return obj.map(objectDeepCopyWithKeysSorted);
969
- }
970
-
971
- // recursively deep-copy obj with keys sorted
972
-
973
- sorted = {};
974
- Object.keys(obj).sort().forEach(function (key) {
975
- sorted[key] = objectDeepCopyWithKeysSorted(obj[key]);
976
- });
977
- return sorted;
978
- }
979
- console.error("shJsonNormalize - " + process.argv[1]);
980
- moduleFs.promises.writeFile(
981
- process.argv[1],
982
- JSON.stringify(
983
- objectDeepCopyWithKeysSorted(
984
- JSON.parse(
985
- identity(
986
- await moduleFs.promises.readFile(
987
- process.argv[1],
988
- "utf8"
989
- )
990
- ).replace((
991
- /^\ufeff/
992
- ), "")
993
- )
994
- ),
995
- undefined,
996
- 4
997
- ) + "\n"
998
- );
999
- }());
1000
- ' "$@" # '
1001
- )}
1002
-
1003
- shRawLibFetch() {(set -e
1004
- # this function will fetch raw-lib from $1
1005
- node --input-type=module -e '
1006
- import moduleChildProcess from "child_process";
1007
- import moduleFs from "fs";
1008
- import moduleHttps from "https";
1009
- import modulePath from "path";
1010
- // init debugInline
1011
- (function () {
1012
- let consoleError = console.error;
1013
- globalThis.debugInline = globalThis.debugInline || function (...argList) {
1014
-
1015
- // this function will both print <argList> to stderr and return <argList>[0]
1016
-
1017
- consoleError("\n\ndebugInline");
1018
- consoleError(...argList);
1019
- consoleError("\n");
1020
- return argList[0];
1021
- };
1022
- }());
1023
- (async function () {
1024
- let fetchList;
1025
- let matchObj;
1026
- let replaceList;
1027
- let repoDict;
1028
- function pipeToBuffer(res, dict, key) {
1029
-
1030
- // This function will concat data from <res> to <dict>[<key>].
1031
-
1032
- let data;
1033
- data = [];
1034
- res.on("data", function (chunk) {
1035
- data.push(chunk);
1036
- }).on("end", function () {
1037
- dict[key] = Buffer.concat(data);
1038
- });
1039
- }
1040
- // init matchObj
1041
- matchObj = (
1042
- /^\/\*jslint-disable\*\/\n\/\*\nshRawLibFetch\n(\{\n[\S\s]*?\n\})([\S\s]*?)\n\*\/\n/m
1043
- ).exec(await moduleFs.promises.readFile(process.argv[1], "utf8"));
1044
- // JSON.parse match1 with comment
1045
- fetchList = JSON.parse(matchObj[1]).fetchList;
1046
- replaceList = JSON.parse(matchObj[1]).replaceList || [];
1047
- // init repoDict, fetchList
1048
- repoDict = {};
1049
- fetchList.forEach(function (elem) {
1050
- if (!elem.url) {
1051
- return;
1052
- }
1053
- elem.prefix = elem.url.split("/").slice(0, 7).join("/");
1054
- // fetch dateCommitted
1055
- if (!repoDict.hasOwnProperty(elem.prefix)) {
1056
- repoDict[elem.prefix] = true;
1057
- moduleHttps.request(elem.prefix.replace(
1058
- "/blob/",
1059
- "/commits/"
1060
- ), function (res) {
1061
- pipeToBuffer(res, elem, "dateCommitted");
1062
- }).end();
1063
- }
1064
- // fetch file
1065
- if (elem.node) {
1066
- pipeToBuffer(moduleChildProcess.spawn("node", [
1067
- "-e", elem.node
1068
- ], {
1069
- stdio: [
1070
- "ignore", "pipe", 2
1071
- ]
1072
- }).stdout, elem, "data");
1073
- return;
1074
- }
1075
- if (elem.sh) {
1076
- pipeToBuffer(moduleChildProcess.spawn(elem.sh, {
1077
- shell: true,
1078
- stdio: [
1079
- "ignore", "pipe", 2
1080
- ]
1081
- }).stdout, elem, "data");
1082
- return;
1083
- }
1084
- moduleHttps.get(elem.url2 || elem.url.replace(
1085
- "https://github.com/",
1086
- "https://raw.githubusercontent.com/"
1087
- ).replace("/blob/", "/"), function (res) {
1088
- // http-redirect
1089
- if (res.statusCode === 302) {
1090
- moduleHttps.get(res.headers.location, function (res) {
1091
- pipeToBuffer(res, elem, "data");
1092
- });
1093
- return;
1094
- }
1095
- pipeToBuffer(res, elem, "data");
1096
- });
1097
- });
1098
- // parse fetched data
1099
- process.on("exit", function () {
1100
- let header;
1101
- let result;
1102
- let result0;
1103
- result = "";
1104
- fetchList.forEach(function (elem, ii, list) {
1105
- let prefix;
1106
- if (!elem.url) {
1107
- return;
1108
- }
1109
- // init prefix
1110
- prefix = "exports_" + modulePath.dirname(elem.url).replace(
1111
- "https://github.com/",
1112
- ""
1113
- ).replace((
1114
- /\/blob\/[^\/]*/
1115
- ), "/").replace((
1116
- /\W/g
1117
- ), "_").replace((
1118
- /(_)_+|_+$/g
1119
- ), "$1");
1120
- list[ii].exports = prefix + "_" + modulePath.basename(
1121
- elem.url
1122
- ).replace((
1123
- /\.js$/
1124
- ), "").replace((
1125
- /\W/g
1126
- ), "_");
1127
- if (elem.dataUriType) {
1128
- return;
1129
- }
1130
- if (elem.dateCommitted) {
1131
- result += (
1132
- "\n\n\n/*\n" +
1133
- "repo " + elem.prefix.replace("/blob/", "/tree/") + "\n" +
1134
- "committed " + (
1135
- /\b\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\b/
1136
- ).exec(elem.dateCommitted.toString())[0] + "\n" +
1137
- "*/"
1138
- );
1139
- }
1140
- // comment /*...*/
1141
- if (elem.comment) {
1142
- elem.data = "/*\n" + elem.data.toString().trim().replace((
1143
- /\/\*/g
1144
- ), "/\\*").replace((
1145
- /\*\//g
1146
- ), "*\\/") + "\n*/";
1147
- }
1148
- // mangle module.exports
1149
- result += (
1150
- "\n\n\n/*\nfile " + elem.url + "\n*/\n" +
1151
- elem.data.toString().trim()
1152
- );
1153
- });
1154
- result = (
1155
- "\n" + result.trim() +
1156
- "\n\n\n/*\nfile none\n*/\n/*jslint-enable*/\n"
1157
- );
1158
- // comment #!
1159
- result = result.replace((
1160
- /^#!/gm
1161
- ), "// $&");
1162
- // normalize newline
1163
- result = result.replace((
1164
- /\r\n|\r/g
1165
- ), "\n");
1166
- // remove trailing-whitespace
1167
- result = result.replace((
1168
- /[\t\u0020]+$/gm
1169
- ), "");
1170
- // remove leading-newline before ket
1171
- result = result.replace((
1172
- /\n+?(\n\u0020*?\})/g
1173
- ), "$1");
1174
- // eslint - no-multiple-empty-lines
1175
- // https://github.com/eslint/eslint/blob/v7.2.0/docs/rules/no-multiple-empty-lines.md //jslint-quiet
1176
- result = result.replace((
1177
- /\n{4,}/g
1178
- ), "\n\n\n");
1179
- // replace from replaceList
1180
- replaceList.forEach(function ({
1181
- aa,
1182
- bb,
1183
- flags
1184
- }) {
1185
- result0 = result;
1186
- result = result.replace(new RegExp(aa, flags), bb);
1187
- if (result0 === result) {
1188
- throw new Error(
1189
- "shRawLibFetch - cannot find-and-replace snippet " +
1190
- JSON.stringify(aa)
1191
- );
1192
- }
1193
- });
1194
- // init header
1195
- header = (
1196
- matchObj.input.slice(0, matchObj.index) +
1197
- "/*jslint-disable*/\n/*\nshRawLibFetch\n" +
1198
- JSON.stringify(JSON.parse(matchObj[1]), undefined, 4) + "\n" +
1199
- matchObj[2].split("\n\n").filter(function (elem) {
1200
- return elem.trim();
1201
- }).map(function (elem) {
1202
- return elem.trim().replace((
1203
- /\*\//g
1204
- ), "*\\\\/").replace((
1205
- /\/\*/g
1206
- ), "/\\\\*") + "\n";
1207
- }).sort().join("\n") + "*/\n\n"
1208
- );
1209
- // replace from header-diff
1210
- header.replace((
1211
- /((?:^-.*?\n)+?)((?:^\+.*?\n)+)/gm
1212
- ), function (ignore, aa, bb) {
1213
- aa = "\n" + aa.replace((
1214
- /^-/gm
1215
- ), "").replace((
1216
- /\*\\\\\//g
1217
- ), "*/").replace((
1218
- /\/\\\\\*/g
1219
- ), "/*");
1220
- bb = "\n" + bb.replace((
1221
- /^\+/gm
1222
- ), "").replace((
1223
- /\*\\\\\//g
1224
- ), "*/").replace((
1225
- /\/\\\\\*/g
1226
- ), "/*");
1227
- result0 = result;
1228
- // disable $-escape in replacement-string
1229
- result = result.replace(aa, function () {
1230
- return bb;
1231
- });
1232
- if (result0 === result) {
1233
- throw new Error(
1234
- "shRawLibFetch - cannot find-and-replace snippet " +
1235
- JSON.stringify(aa)
1236
- );
1237
- }
1238
- return "";
1239
- });
1240
- // inline dataUri
1241
- fetchList.forEach(function ({
1242
- data,
1243
- dataUriType,
1244
- exports
1245
- }) {
1246
- if (!dataUriType) {
1247
- return;
1248
- }
1249
- data = (
1250
- "data:" + dataUriType + ";base64," +
1251
- data.toString("base64")
1252
- );
1253
- result0 = result;
1254
- result = result.replace(
1255
- new RegExp("^" + exports + "$", "gm"),
1256
- // disable $-escape in replacement-string
1257
- function () {
1258
- return data;
1259
- }
1260
- );
1261
- if (result0 === result) {
1262
- throw new Error(
1263
- "shRawLibFetch - cannot find-and-replace snippet " +
1264
- JSON.stringify(exports)
1265
- );
1266
- }
1267
- });
1268
- // init footer
1269
- result = header + result;
1270
- matchObj.input.replace((
1271
- /\n\/\*\nfile\u0020none\n\*\/\n\/\*jslint-enable\*\/\n([\S\s]+)/
1272
- ), function (ignore, match1) {
1273
- result += "\n\n" + match1.trim() + "\n";
1274
- });
1275
- // write to file
1276
- moduleFs.writeFileSync(process.argv[1], result); //jslint-quiet
1277
- });
1278
- }());
1279
- ' "$@" # '
1280
- git diff 2>/dev/null || true
1281
- )}
1282
-
1283
- shRunWithCoverage() {(set -e
1284
- # this function will run nodejs command $@ with v8-coverage
1285
- # and create coverage-report .build/coverage/index.html
1286
- local EXIT_CODE
1287
- EXIT_CODE=0
1288
- export DIR_COVERAGE=.build/coverage/
1289
- rm -rf "$DIR_COVERAGE"
1290
- (set -e
1291
- export NODE_V8_COVERAGE="$DIR_COVERAGE"
1292
- "$@"
1293
- ) || EXIT_CODE="$?"
1294
- if [ "$EXIT_CODE" = 0 ]
1295
- then
1296
- node --input-type=module -e '
1297
- import moduleFs from "fs";
1298
- import modulePath from "path";
1299
- // init debugInline
1300
- (function () {
1301
- let consoleError = console.error;
1302
- globalThis.debugInline = globalThis.debugInline || function (...argList) {
1303
-
1304
- // this function will both print <argList> to stderr and return <argList>[0]
1305
-
1306
- consoleError("\n\ndebugInline");
1307
- consoleError(...argList);
1308
- consoleError("\n");
1309
- return argList[0];
1310
- };
1311
- }());
1312
- (async function () {
1313
- let DIR_COVERAGE = process.env.DIR_COVERAGE;
1314
- let cwd;
1315
- let data;
1316
- let fileDict;
1317
- async function htmlRender({
1318
- fileList,
1319
- lineList,
1320
- pathname
1321
- }) {
1322
- let html;
1323
- let padLines;
1324
- let padPathname;
1325
- let txt;
1326
- let txtBorder;
1327
- function stringHtmlSafe(str) {
1328
- /*
1329
- * this function will make <str> html-safe
1330
- * https://stackoverflow.com/questions/7381974/which-characters-need-to-be-escaped-on-html //jslint-quiet
1331
- */
1332
- return str.replace((
1333
- /&/gu
1334
- ), "&amp;").replace((
1335
- /"/gu
1336
- ), "&quot;").replace((
1337
- /\u0027/gu
1338
- ), "&apos;").replace((
1339
- /</gu
1340
- ), "&lt;").replace((
1341
- />/gu
1342
- ), "&gt;").replace((
1343
- /&amp;(amp;|apos;|gt;|lt;|quot;)/igu
1344
- ), "&$1");
1345
- }
1346
- html = "";
1347
- html += `<!DOCTYPE html>
1348
- <html lang="en">
1349
- <head>
1350
- <title>coverage-report</title>
1351
- <style>
1352
- /* csslint ignore:start */
1353
- * {
1354
- box-sizing: border-box;
1355
- font-family: consolas, menlo, monospace;
1356
- }
1357
- /* csslint ignore:end */
1358
- body {
1359
- margin: 0;
1360
- }
1361
- .coverage pre {
1362
- margin: 5px 0;
1363
- }
1364
- .coverage table {
1365
- border-collapse: collapse;
1366
- }
1367
- .coverage td,
1368
- .coverage th {
1369
- border: 1px solid #777;
1370
- margin: 0;
1371
- padding: 5px;
1372
- }
1373
- .coverage td span {
1374
- display: inline-block;
1375
- width: 100%;
1376
- }
1377
- .coverage .content {
1378
- padding: 0 5px;
1379
- }
1380
- .coverage .content a {
1381
- text-decoration: none;
1382
- }
1383
- .coverage .count {
1384
- margin: 0 5px;
1385
- padding: 0 5px;
1386
- }
1387
- .coverage .footer,
1388
- .coverage .header {
1389
- padding: 20px;
1390
- }
1391
- .coverage .percentbar {
1392
- height: 12px;
1393
- margin: 2px 0;
1394
- min-width: 200px;
1395
- position: relative;
1396
- width: 100%;
1397
- }
1398
- .coverage .percentbar div {
1399
- height: 100%;
1400
- position: absolute;
1401
- }
1402
- .coverage .title {
1403
- font-size: large;
1404
- font-weight: bold;
1405
- margin-bottom: 10px;
1406
- }
1407
-
1408
- .coverage td,
1409
- .coverage th {
1410
- background: #fff;
1411
- }
1412
- .coverage .count {
1413
- background: #9d9;
1414
- color: #777;
1415
- }
1416
- .coverage .coverageHigh{
1417
- background: #9d9;
1418
- }
1419
- .coverage .coverageLow{
1420
- background: #ebb;
1421
- }
1422
- .coverage .coverageMedium{
1423
- background: #fd7;
1424
- }
1425
- .coverage .header {
1426
- background: #ddd;
1427
- }
1428
- .coverage .lineno {
1429
- background: #ddd;
1430
- }
1431
- .coverage .percentbar {
1432
- background: #999;
1433
- }
1434
- .coverage .percentbar div {
1435
- background: #666;
1436
- }
1437
- .coverage .uncovered {
1438
- background: #dbb;
1439
- }
1440
-
1441
- .coverage pre:hover span,
1442
- .coverage tr:hover td {
1443
- background: #7d7;
1444
- }
1445
- .coverage pre:hover span.uncovered,
1446
- .coverage tr:hover td.coverageLow {
1447
- background: #d99;
1448
- }
1449
- </style>
1450
- </head>
1451
- <body class="coverage">
1452
- <div class="header">
1453
- <div class="title">coverage-report</div>
1454
- <table>
1455
- <thead>
1456
- <tr>
1457
- <th>files covered</th>
1458
- <th>lines</th>
1459
- </tr>
1460
- </thead>
1461
- <tbody>`;
1462
- if (!lineList) {
1463
- padLines = String("100.00 %").length;
1464
- padPathname = 32;
1465
- fileList.unshift({
1466
- linesCovered: 0,
1467
- linesTotal: 0,
1468
- pathname: "./"
1469
- });
1470
- fileList.slice(1).forEach(function ({
1471
- linesCovered,
1472
- linesTotal,
1473
- pathname
1474
- }) {
1475
- fileList[0].linesCovered += linesCovered;
1476
- fileList[0].linesTotal += linesTotal;
1477
- padPathname = Math.max(padPathname, pathname.length + 2);
1478
- padLines = Math.max(
1479
- padLines,
1480
- String(linesCovered + " / " + linesTotal).length
1481
- );
1482
- });
1483
- }
1484
- txtBorder = (
1485
- "+" + "-".repeat(padPathname + 2) + "+"
1486
- + "-".repeat(padLines + 2) + "+\n"
1487
- );
1488
- txt = "";
1489
- txt += "coverage-report\n";
1490
- txt += txtBorder;
1491
- txt += (
1492
- "| " + String("files covered").padEnd(padPathname, " ") + " | "
1493
- + String("lines").padStart(padLines, " ") + " |\n"
1494
- );
1495
- txt += txtBorder;
1496
- fileList.forEach(function ({
1497
- linesCovered,
1498
- linesTotal,
1499
- pathname
1500
- }, ii) {
1501
- let coverageLevel;
1502
- let coveragePct;
1503
- let fill;
1504
- let str1;
1505
- let str2;
1506
- let xx1;
1507
- let xx2;
1508
- coveragePct = Math.floor(10000 * linesCovered / linesTotal || 0);
1509
- coverageLevel = (
1510
- coveragePct >= 8000
1511
- ? "coverageHigh"
1512
- : coveragePct >= 5000
1513
- ? "coverageMedium"
1514
- : "coverageLow"
1515
- );
1516
- coveragePct = String(coveragePct).replace((
1517
- /..$/m
1518
- ), ".$&");
1519
- if (!lineList && ii === 0) {
1520
- fill = (
1521
- // red
1522
- "#" + Math.round(
1523
- (100 - Number(coveragePct)) * 2.21
1524
- ).toString(16).padStart(2, "0")
1525
- // green
1526
- + Math.round(
1527
- Number(coveragePct) * 2.21
1528
- ).toString(16).padStart(2, "0")
1529
- + // blue
1530
- "00"
1531
- );
1532
- str1 = "coverage";
1533
- str2 = coveragePct + " %";
1534
- xx1 = 6 * str1.length + 20;
1535
- xx2 = 6 * str2.length + 20;
1536
- // fs - write coverage-badge.svg
1537
- moduleFs.promises.writeFile((
1538
- DIR_COVERAGE + "/coverage-badge.svg"
1539
- ), String(`
1540
- <svg height="20" width="${xx1 + xx2}" xmlns="http://www.w3.org/2000/svg">
1541
- <rect fill="#555" height="20" width="${xx1 + xx2}"/>
1542
- <rect fill="${fill}" height="20" width="${xx2}" x="${xx1}"/>
1543
- <g
1544
- fill="#fff"
1545
- font-family="dejavu sans, verdana, geneva, sans-serif"
1546
- font-size="11"
1547
- font-weight="bold"
1548
- text-anchor="middle"
1549
- >
1550
- <text x="${0.5 * xx1}" y="14">${str1}</text>
1551
- <text x="${xx1 + 0.5 * xx2}" y="14">${str2}</text>
1552
- </g>
1553
- </svg>
1554
- `).trim() + "\n");
1555
- pathname = "";
1556
- }
1557
- txt += (
1558
- "| "
1559
- + String("./" + pathname).padEnd(padPathname, " ") + " | "
1560
- + String(coveragePct + " %").padStart(padLines, " ") + " |\n"
1561
- );
1562
- txt += (
1563
- "| " + "*".repeat(
1564
- Math.round(0.01 * coveragePct * padPathname)
1565
- ).padEnd(padPathname, "_") + " | "
1566
- + String(
1567
- linesCovered + " / " + linesTotal
1568
- ).padStart(padLines, " ") + " |\n"
1569
- );
1570
- txt += txtBorder;
1571
- pathname = stringHtmlSafe(pathname);
1572
- html += `<tr>
1573
- <td class="${coverageLevel}">
1574
- ${(
1575
- lineList
1576
- ? (
1577
- "<a href=\"index.html\">./ </a>"
1578
- + pathname + "<br>"
1579
- )
1580
- : (
1581
- "<a href=\"" + (pathname || "index") + ".html\">./ "
1582
- + pathname + "</a><br>"
1583
- )
1584
- )}
1585
- <div class="percentbar">
1586
- <div style="width: ${coveragePct}%;"></div>
1587
- </div>
1588
- </td>
1589
- <td style="text-align: right;">
1590
- ${coveragePct} %<br>
1591
- ${linesCovered} / ${linesTotal}
1592
- </td>
1593
- </tr>`;
1594
- });
1595
- if (lineList) {
1596
- html += `</tbody>
1597
- </table>
1598
- </div>
1599
- <div class="content">
1600
- `;
1601
- lineList.forEach(function ({
1602
- count,
1603
- holeList,
1604
- line,
1605
- startOffset
1606
- }, ii) {
1607
- let chunk;
1608
- let inHole;
1609
- let lineHtml;
1610
- let lineId;
1611
- lineHtml = "";
1612
- lineId = "line_" + (ii + 1);
1613
- switch (count) {
1614
- case -1:
1615
- case 0:
1616
- if (holeList.length === 0) {
1617
- lineHtml += "</span>";
1618
- lineHtml += "<span class=\"uncovered\">";
1619
- lineHtml += stringHtmlSafe(line);
1620
- break;
1621
- }
1622
- line = line.split("").map(function (chr) {
1623
- return {
1624
- chr,
1625
- isHole: undefined
1626
- };
1627
- });
1628
- holeList.forEach(function ([
1629
- aa, bb
1630
- ]) {
1631
- aa = Math.max(aa - startOffset, 0);
1632
- bb = Math.min(bb - startOffset, line.length);
1633
- while (aa < bb) {
1634
- line[aa].isHole = true;
1635
- aa += 1;
1636
- }
1637
- });
1638
- chunk = "";
1639
- line.forEach(function ({
1640
- chr,
1641
- isHole
1642
- }) {
1643
- if (inHole !== isHole) {
1644
- lineHtml += stringHtmlSafe(chunk);
1645
- lineHtml += (
1646
- isHole
1647
- ? "</span><span class=\"uncovered\">"
1648
- : "</span><span>"
1649
- );
1650
- chunk = "";
1651
- inHole = isHole;
1652
- }
1653
- chunk += chr;
1654
- });
1655
- lineHtml += stringHtmlSafe(chunk);
1656
- break;
1657
- default:
1658
- lineHtml += stringHtmlSafe(line);
1659
- }
1660
- html += String(`
1661
- <pre>
1662
- <span class="lineno">
1663
- <a href="#${lineId}" id="${lineId}">${String(ii + 1).padStart(5, " ")}.</a>
1664
- </span>
1665
- <span class="count
1666
- ${(
1667
- count <= 0
1668
- ? "uncovered"
1669
- : ""
1670
- )}"
1671
- >
1672
- ${String(count).padStart(7, " ")}
1673
- </span>
1674
- <span>${lineHtml}</span>
1675
- </pre>
1676
- `).replace((
1677
- /\n/g
1678
- ), "").trim() + "\n";
1679
- });
1680
- }
1681
- html += `
1682
- </div>
1683
- <div class="coverageFooter">
1684
- </div>
1685
- </body>
1686
- </html>`;
1687
- html += "\n";
1688
- await moduleFs.promises.mkdir(modulePath.dirname(pathname), {
1689
- recursive: true
1690
- });
1691
- // fs - write *.html
1692
- moduleFs.promises.writeFile(pathname + ".html", html);
1693
- if (lineList) {
1694
- return;
1695
- }
1696
- // fs - write coverage.txt
1697
- console.error("\n" + txt);
1698
- moduleFs.promises.writeFile((
1699
- DIR_COVERAGE + "/coverage-report.txt"
1700
- ), txt);
1701
- }
1702
- data = await moduleFs.promises.readdir(DIR_COVERAGE);
1703
- await Promise.all(data.map(async function (file) {
1704
- if ((
1705
- /^coverage-.*?\.json$/
1706
- ).test(file)) {
1707
- data = await moduleFs.promises.readFile((
1708
- DIR_COVERAGE + file
1709
- ), "utf8");
1710
- // fs - rename to coverage-v8.json
1711
- moduleFs.promises.rename(
1712
- DIR_COVERAGE + file,
1713
- DIR_COVERAGE + "coverage-v8.json"
1714
- );
1715
- }
1716
- }));
1717
- fileDict = {};
1718
- cwd = process.cwd().replace((
1719
- /\\/g
1720
- ), "/") + "/";
1721
- await Promise.all(JSON.parse(data).result.map(async function ({
1722
- functions,
1723
- url
1724
- }) {
1725
- let lineList;
1726
- let linesCovered;
1727
- let linesTotal;
1728
- let pathname;
1729
- let src;
1730
- if (!url.startsWith("file:///")) {
1731
- return;
1732
- }
1733
- pathname = url.replace((
1734
- process.platform === "win32"
1735
- ? "file:///"
1736
- : "file://"
1737
- ), "").replace((
1738
- /\\\\/g
1739
- ), "/");
1740
- if (
1741
- !pathname.startsWith(cwd)
1742
- || pathname.startsWith(cwd + "[")
1743
- || (
1744
- process.env.npm_config_mode_coverage !== "all"
1745
- && pathname.indexOf("/node_modules/") >= 0
1746
- )
1747
- ) {
1748
- return;
1749
- }
1750
- pathname = pathname.replace(cwd, "");
1751
- src = await moduleFs.promises.readFile(pathname, "utf8");
1752
- lineList = [{}];
1753
- src.replace((
1754
- /^.*$/gm
1755
- ), function (line, startOffset) {
1756
- lineList[lineList.length - 1].endOffset = startOffset - 1;
1757
- lineList.push({
1758
- count: -1,
1759
- endOffset: 0,
1760
- holeList: [],
1761
- line,
1762
- startOffset
1763
- });
1764
- return "";
1765
- });
1766
- lineList.shift();
1767
- lineList[lineList.length - 1].endOffset = src.length;
1768
- functions.reverse().forEach(function ({
1769
- ranges
1770
- }) {
1771
- ranges.reverse().forEach(function ({
1772
- count,
1773
- endOffset,
1774
- startOffset
1775
- }, ii, list) {
1776
- lineList.forEach(function (elem) {
1777
- if (!(
1778
- (
1779
- elem.startOffset <= startOffset
1780
- && startOffset <= elem.endOffset
1781
- ) || (
1782
- elem.startOffset <= endOffset
1783
- && endOffset <= elem.endOffset
1784
- ) || (
1785
- startOffset <= elem.startOffset
1786
- && elem.endOffset <= endOffset
1787
- )
1788
- )) {
1789
- return;
1790
- }
1791
- // handle root-range
1792
- if (ii + 1 === list.length) {
1793
- if (elem.count === -1) {
1794
- elem.count = count;
1795
- }
1796
- return;
1797
- }
1798
- // handle non-root-range
1799
- if (elem.count !== 0) {
1800
- elem.count = Math.max(count, elem.count);
1801
- }
1802
- if (count === 0) {
1803
- elem.count = 0;
1804
- elem.holeList.push([
1805
- startOffset, endOffset
1806
- ]);
1807
- }
1808
- });
1809
- });
1810
- });
1811
- linesTotal = lineList.length;
1812
- linesCovered = lineList.filter(function ({
1813
- count
1814
- }) {
1815
- return count > 0;
1816
- }).length;
1817
- await moduleFs.promises.mkdir((
1818
- modulePath.dirname(DIR_COVERAGE + pathname)
1819
- ), {
1820
- recursive: true
1821
- });
1822
- await htmlRender({
1823
- fileList: [
1824
- {
1825
- linesCovered,
1826
- linesTotal,
1827
- pathname
1828
- }
1829
- ],
1830
- lineList,
1831
- pathname: DIR_COVERAGE + pathname
1832
- });
1833
- fileDict[pathname] = {
1834
- lineList,
1835
- linesCovered,
1836
- linesTotal,
1837
- pathname,
1838
- src
1839
- };
1840
- }));
1841
- await htmlRender({
1842
- fileList: Object.keys(fileDict).sort().map(function (pathname) {
1843
- return fileDict[pathname];
1844
- }),
1845
- pathname: DIR_COVERAGE + "index"
1846
- });
1847
- }());
1848
- ' # "'
1849
- find "$DIR_COVERAGE"
1850
- fi
1851
- printf "shRunWithCoverage - EXIT_CODE=$EXIT_CODE\n" 1>&2
1852
- return "$EXIT_CODE"
1853
- )}
1854
-
1855
- shRunWithScreenshotTxt() {(set -e
1856
- # this function will run cmd $@ and screenshot text-output
1857
- # https://www.cnx-software.com/2011/09/22/how-to-convert-a-command-line-result-into-an-image-in-linux/
1858
- local EXIT_CODE
1859
- EXIT_CODE=0
1860
- export SCREENSHOT_SVG="$1"
1861
- shift
1862
- printf "0\n" > "$SCREENSHOT_SVG.exit_code"
1863
- printf "shRunWithScreenshotTxt - ($* 2>&1)\n" 1>&2
1864
- # run "$@" with screenshot
1865
- (set -e
1866
- "$@" 2>&1 || printf "$?\n" > "$SCREENSHOT_SVG.exit_code"
1867
- ) | tee "$SCREENSHOT_SVG.txt"
1868
- EXIT_CODE="$(cat "$SCREENSHOT_SVG.exit_code")"
1869
- printf "shRunWithScreenshotTxt - EXIT_CODE=$EXIT_CODE\n" 1>&2
1870
- # format text-output
1871
- node --input-type=module -e '
1872
- import moduleFs from "fs";
1873
- (async function () {
1874
- let result = await moduleFs.promises.readFile(
1875
- process.argv[1] + ".txt",
1876
- "utf8"
1877
- );
1878
- let yy = 10;
1879
- // remove ansi escape-code
1880
- result = result.replace((
1881
- /\u001b.*?m/g
1882
- ), "");
1883
- /*
1884
- // format unicode
1885
- result = result.replace((
1886
- /\\u[0-9a-f]{4}/g
1887
- ), function (match0) {
1888
- return String.fromCharCode("0x" + match0.slice(-4));
1889
- });
1890
- */
1891
- // normalize "\r\n"
1892
- result = result.replace((
1893
- /\r\n?/
1894
- ), "\n").trimEnd();
1895
- // 96-column wordwrap
1896
- result = result.split("\n").map(function (line) {
1897
- let wordwrap = line.slice(0, 96).padEnd(96, " ");
1898
- line = line.slice(96);
1899
- while (line) {
1900
- wordwrap += "\\\n " + line.slice(0, 96 - 2).padEnd(96 - 2, " ");
1901
- line = line.slice(96 - 2);
1902
- }
1903
- return wordwrap + " ";
1904
- }).join("\n");
1905
- // html-escape
1906
- result = result.replace((
1907
- /&/g
1908
- ), "&amp;").replace((
1909
- /</g
1910
- ), "&lt;").replace((
1911
- />/g
1912
- ), "&gt;");
1913
- // convert text to svg-tspan
1914
- result = result.split("\n").map(function (line) {
1915
- yy += 22;
1916
- return `<tspan
1917
- lengthAdjust="spacingAndGlyphs"
1918
- textLength="${96 * 8}"
1919
- x="10"
1920
- y="${yy}"
1921
- >${line}</tspan>\n`;
1922
- }).join("");
1923
- result = String(`
1924
- <svg height="${yy + 20}" width="800" xmlns="http://www.w3.org/2000/svg">
1925
- <rect height="${yy + 20}" fill="#222" width="800"></rect>
1926
- <text
1927
- fill="#7f7"
1928
- font-family="consolas, menlo, monospace"
1929
- font-size="14"
1930
- xml:space="preserve"
1931
- >
1932
- ${result}
1933
- </text>
1934
- </svg>
1935
- `).trim() + "\n";
1936
- moduleFs.promises.writeFile(process.argv[1], result);
1937
- }());
1938
- ' "$SCREENSHOT_SVG" # "'
1939
- printf "shRunWithScreenshotTxt - wrote - $SCREENSHOT_SVG\n"
1940
- # cleanup
1941
- rm "$SCREENSHOT_SVG.exit_code" "$SCREENSHOT_SVG.txt"
1942
- return "$EXIT_CODE"
1943
- )}
1944
-
1945
- shCiMain() {(set -e
1946
- # run $@
1947
- # run "$@" with winpty
1948
- export CI_UNAME="${CI_UNAME:-$(uname)}"
1949
- case "$CI_UNAME" in
1950
- MSYS*)
1951
- if [ ! "$CI_WINPTY" ] && [ "$1" != shHttpFileServer ]
1952
- then
1953
- export CI_WINPTY=1
1954
- winpty -Xallow-non-tty -Xplain sh jslint_ci.sh "$@"
1955
- return
1956
- fi
1957
- ;;
1958
- esac
1959
- # run "$@"
1960
- export NODE_OPTIONS="--unhandled-rejections=strict"
1961
- if [ -f ./.ci.sh ]
1962
- then
1963
- . ./.ci.sh "$@"
1964
- fi
1965
- "$@"
1966
- )}
1967
-
1968
- shCiMain "$@"