diff --git a/.gitpod.yml b/.gitpod.yml index 914a89919..360da5b5f 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -2,7 +2,7 @@ image: file: .gitpod.dockerfile tasks: - - before: nvm install 16.19.0 && nvm use 16.19.0 + - before: nvm install 18.14.0 && nvm use 18.14.0 init: npm install command: npm run start-server diff --git a/Dockerfile b/Dockerfile index c1a425e3f..d6f47ed03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # !!! Don't try to build this Dockerfile directly, run it through bin/build-docker.sh script !!! -FROM node:16.19.0-alpine +FROM node:18.14.0-alpine # Create app directory WORKDIR /usr/src/app diff --git a/bin/build-api-docs.sh b/bin/build-api-docs.sh new file mode 100644 index 000000000..9d6fb61f5 --- /dev/null +++ b/bin/build-api-docs.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +rm -rf ./tmp/api_docs/backend_api +rm -rf ./tmp/api_docs/frontend_api + +./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./tmp/api_docs/backend_api src/becca/entities/*.js \ + src/services/backend_script_api.js src/services/sql.js + +./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./tmp/api_docs/frontend_api src/public/app/entities/*.js \ + src/public/app/services/frontend_script_api.js src/public/app/widgets/right_panel_widget.js + +rm -rf ./docs/api_docs/backend_api ./docs/api_docs/frontend_api + +node src/transform_api_docs.js + +rm -rf ./docs/api_docs/fonts ./docs/api_docs/styles ./docs/api_docs/scripts ./docs/api_docs/backend_api/index.html ./docs/api_docs/frontend_api/index.html diff --git a/bin/build-server.sh b/bin/build-server.sh index 2c42c9105..9173288b0 100755 --- a/bin/build-server.sh +++ b/bin/build-server.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash PKG_DIR=dist/trilium-linux-x64-server -NODE_VERSION=16.19.0 +NODE_VERSION=18.14.0 if [ "$1" != "DONTCOPY" ] then diff --git a/bin/copy-trilium.sh b/bin/copy-trilium.sh index fdcb99a40..8b87bbd12 100755 --- a/bin/copy-trilium.sh +++ b/bin/copy-trilium.sh @@ -5,7 +5,7 @@ if [[ $# -eq 0 ]] ; then exit 1 fi -n exec 16.19.0 npm run webpack +n exec 18.14.0 npm run webpack DIR=$1 @@ -27,7 +27,7 @@ cp -r electron.js $DIR/ cp webpack-* $DIR/ # run in subshell (so we return to original dir) -(cd $DIR && n exec 16.19.0 npm install --only=prod) +(cd $DIR && n exec 18.14.0 npm install --only=prod) # cleanup of useless files in dependencies rm -r $DIR/node_modules/image-q/demo diff --git a/bin/tpl/anonymize-database.sql b/bin/tpl/anonymize-database.sql index fca3b4e53..e4d9b7129 100644 --- a/bin/tpl/anonymize-database.sql +++ b/bin/tpl/anonymize-database.sql @@ -4,6 +4,7 @@ UPDATE notes SET title = 'title' WHERE title NOT IN ('root', '_hidden', '_share' UPDATE note_contents SET content = 'text' WHERE content IS NOT NULL; UPDATE note_revisions SET title = 'title'; UPDATE note_revision_contents SET content = 'text' WHERE content IS NOT NULL; +UPDATE note_ancillary_contents SET content = 'text' WHERE content IS NOT NULL; UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label' AND name NOT IN('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'noteRevisionsWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor', 'searchHome', 'workspaceInbox', 'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', 'bookmarkFolder', 'sorted', 'top', 'fullContentWidth', 'shareHiddenFromTree', 'shareAlias', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', 'runOnNoteTitleChange', 'runOnNoteContentChange', 'runOnNoteChange', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', 'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon'); UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name NOT IN ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'cssClass', 'iconClass', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'noteRevisionsWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor', 'searchHome', 'workspaceInbox', 'workspaceSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', 'bookmarkFolder', 'sorted', 'top', 'fullContentWidth', 'shareHiddenFromTree', 'shareAlias', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', 'runOnNoteTitleChange', 'runOnNoteContentChange', 'runOnNoteChange', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', 'inherit', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon'); diff --git a/db/migrations/0213__note_ancillaries.sql b/db/migrations/0213__note_ancillaries.sql new file mode 100644 index 000000000..03cadd8d8 --- /dev/null +++ b/db/migrations/0213__note_ancillaries.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS "note_ancillaries" +( + noteAncillaryId TEXT not null primary key, + noteId TEXT not null, + name TEXT not null, + mime TEXT not null, + isProtected INT not null DEFAULT 0, + contentCheckSum TEXT not null, + utcDateModified TEXT not null, + isDeleted INT not null, + `deleteId` TEXT DEFAULT NULL); + +CREATE TABLE IF NOT EXISTS "note_ancillary_contents" (`noteAncillaryId` TEXT NOT NULL PRIMARY KEY, + `content` TEXT DEFAULT NULL, + `utcDateModified` TEXT NOT NULL); + +CREATE INDEX IDX_note_ancillaries_name + on note_ancillaries (name); +CREATE UNIQUE INDEX IDX_note_ancillaries_noteId_name + on note_ancillaries (noteId, name); diff --git a/db/migrations/0214__migrate_canvas_note_to_ancillary.js b/db/migrations/0214__migrate_canvas_note_to_ancillary.js new file mode 100644 index 000000000..44aaaa939 --- /dev/null +++ b/db/migrations/0214__migrate_canvas_note_to_ancillary.js @@ -0,0 +1,39 @@ +module.exports = async () => { + const cls = require("../../src/services/cls"); + const beccaLoader = require("../../src/becca/becca_loader"); + const becca = require("../../src/becca/becca"); + const log = require("../../src/services/log"); + + await cls.init(async () => { + beccaLoader.load(); + + for (const note of Object.values(becca.notes)) { + if (note.type !== 'canvas') { + continue; + } + + if (note.isProtected) { + // can't migrate protected notes, but that's not critical. + continue; + } + + const content = note.getContent(true); + let svg; + + try { + const payload = JSON.parse(content); + svg = payload?.svg; + + if (!svg) { + continue; + } + } + catch (e) { + log.info(`Could not create a note ancillary for canvas "${note.noteId}" with error: ${e.message} ${e.stack}`); + continue; + } + + note.saveNoteAncillary('canvasSvg', 'image/svg+xml', svg); + } + }); +}; diff --git a/db/schema.sql b/db/schema.sql index 01a40c554..6537ea720 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -112,3 +112,21 @@ CREATE TABLE IF NOT EXISTS "recent_notes" notePath TEXT not null, utcDateCreated TEXT not null ); +CREATE TABLE IF NOT EXISTS "note_ancillaries" +( + noteAncillaryId TEXT not null primary key, + noteId TEXT not null, + name TEXT not null, + mime TEXT not null, + isProtected INT not null DEFAULT 0, + contentCheckSum TEXT not null, + utcDateModified TEXT not null, + isDeleted INT not null, + `deleteId` TEXT DEFAULT NULL); +CREATE TABLE IF NOT EXISTS "note_ancillary_contents" (`noteAncillaryId` TEXT NOT NULL PRIMARY KEY, + `content` TEXT DEFAULT NULL, + `utcDateModified` TEXT NOT NULL); +CREATE INDEX IDX_note_ancillaries_name + on note_ancillaries (name); +CREATE UNIQUE INDEX IDX_note_ancillaries_noteId_name + on note_ancillaries (noteId, name); diff --git a/jsdoc-conf.json b/jsdoc-conf.json index c0451f5b4..3a20f8015 100644 --- a/jsdoc-conf.json +++ b/jsdoc-conf.json @@ -1,7 +1,8 @@ { "templates": { "default": { - "includeDate": false + "includeDate": false, + "outputSourceFiles": false } } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 72f6edf04..6e78a6cc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "archiver": "5.3.1", "async-mutex": "0.4.0", "axios": "1.3.3", - "better-sqlite3": "7.4.5", + "better-sqlite3": "8.1.0", + "canvas": "2.11.0", "chokidar": "3.5.3", "cls-hooked": "4.2.2", "commonmark": "0.30.0", @@ -51,12 +52,13 @@ "multer": "1.4.5-lts.1", "node-abi": "3.33.0", "normalize-strings": "1.1.1", + "ocrad.js": "antimatter15/ocrad.js#master", "open": "8.4.1", + "pdfjs-dist": "3.3.122", "rand-token": "1.0.1", "react": "17.0.2", "react-dom": "17.0.2", "request": "2.88.2", - "rimraf": "3.0.2", "safe-compare": "1.1.4", "sanitize-filename": "1.6.3", "sanitize-html": "2.9.0", @@ -78,13 +80,13 @@ }, "devDependencies": { "cross-env": "7.0.3", - "electron": "16.2.8", + "electron": "23.1.0", "electron-builder": "23.6.0", "electron-packager": "17.1.1", "electron-rebuild": "3.2.9", "esm": "3.2.25", "jasmine": "4.5.0", - "jsdoc": "4.0.0", + "jsdoc": "4.0.1", "lorem-ipsum": "2.0.8", "rcedit": "3.0.1", "webpack": "5.75.0", @@ -162,7 +164,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", - "dev": true, "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", @@ -183,7 +184,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -197,7 +197,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -869,8 +868,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", - "optional": true, - "peer": true, "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -928,7 +925,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, "engines": { "node": ">=10" }, @@ -940,7 +936,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "dependencies": { "defer-to-connect": "^2.0.0" }, @@ -965,7 +960,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "dev": true, "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "*", @@ -1030,8 +1024,7 @@ "node_modules/@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "node_modules/@types/json-schema": { "version": "7.0.9", @@ -1043,7 +1036,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1085,8 +1077,7 @@ "node_modules/@types/node": { "version": "16.11.46", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.46.tgz", - "integrity": "sha512-x+sfpb2dMrhCQPL4NAGs64Z9hh0t72aP0dg+PuZidmPr/0Gj5ELQTjD/t46dq3DF/8ZvSHOaIyDIbAsdPshyVQ==", - "devOptional": true + "integrity": "sha512-x+sfpb2dMrhCQPL4NAGs64Z9hh0t72aP0dg+PuZidmPr/0Gj5ELQTjD/t46dq3DF/8ZvSHOaIyDIbAsdPshyVQ==" }, "node_modules/@types/plist": { "version": "3.0.2", @@ -1103,7 +1094,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -1134,7 +1124,6 @@ "version": "2.9.2", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, "optional": true, "dependencies": { "@types/node": "*" @@ -1356,8 +1345,7 @@ "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "devOptional": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/accepts": { "version": "1.3.8", @@ -1474,7 +1462,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true, "engines": { "node": ">=8" } @@ -1677,8 +1664,7 @@ "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "devOptional": true + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "node_modules/archiver": { "version": "5.3.1", @@ -1739,8 +1725,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "peer": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -1753,8 +1737,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -1977,14 +1959,13 @@ } }, "node_modules/better-sqlite3": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.4.5.tgz", - "integrity": "sha512-mybC3dgrtJeHkIRGP36tST7wjBlIMgTRAXhhO4bMpPZ17EG23FZxZeFcwKWy6o8mV1SKQFnQNyeAZlQpGrgheQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.1.0.tgz", + "integrity": "sha512-p1m09H+Oi8R9TPj810pdNswMFuVgRNgCJEWypp6jlkOgSwMIrNyuj3hW78xEuBRGok5RzeaUW8aBtTWF3l/TQA==", "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", - "prebuild-install": "^7.0.0", - "tar": "^6.1.11" + "prebuild-install": "^7.1.0" } }, "node_modules/binary-extensions": { @@ -2399,7 +2380,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, "engines": { "node": ">=10.6.0" } @@ -2408,7 +2388,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -2449,8 +2428,6 @@ "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.0.tgz", "integrity": "sha512-bdTjFexjKJEwtIo0oRx8eD4G2yWoUOXP9lj279jmQ2zMnTQhT8C3512OKz3s+ZOaQlLbE7TuVvRDYDB3Llyy5g==", "hasInstallScript": true, - "optional": true, - "peer": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", @@ -2464,8 +2441,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "optional": true, - "peer": true, "dependencies": { "mimic-response": "^2.0.0" }, @@ -2477,8 +2452,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "optional": true, - "peer": true, "engines": { "node": ">=8" }, @@ -2490,8 +2463,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "optional": true, - "peer": true, "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -2765,7 +2736,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "devOptional": true, "bin": { "color-support": "bin.js" } @@ -2917,27 +2887,10 @@ "typedarray": "^0.0.6" } }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "optional": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-chain/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "optional": true - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "devOptional": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "node_modules/content-disposition": { "version": "0.5.4", @@ -3343,7 +3296,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, "engines": { "node": ">=10" } @@ -3383,8 +3335,7 @@ "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "devOptional": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "node_modules/depd": { "version": "1.1.2", @@ -3618,11 +3569,6 @@ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, - "node_modules/duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" - }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3652,20 +3598,20 @@ } }, "node_modules/electron": { - "version": "16.2.8", - "resolved": "https://registry.npmjs.org/electron/-/electron-16.2.8.tgz", - "integrity": "sha512-KSOytY6SPLsh3iCziztqa/WgJyfDOKzCvNqku9gGIqSdT8CqtV66dTU1SOrKZQjRFLxHaF8LbyxUL1vwe4taqw==", + "version": "23.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-23.1.0.tgz", + "integrity": "sha512-LRgACMpVrmjfYWPgCSyJ+TFQ/FPeniOowpO57z0xUcTchfC7EH+5rUncgYN+uMvqePiYDce+ywZeCIFaO8x/Nw==", "hasInstallScript": true, "dependencies": { - "@electron/get": "^1.13.0", - "@types/node": "^14.6.2", - "extract-zip": "^1.0.3" + "@electron/get": "^2.0.0", + "@types/node": "^16.11.26", + "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" }, "engines": { - "node": ">= 8.6" + "node": ">= 12.20.55" } }, "node_modules/electron-builder": { @@ -4258,212 +4204,6 @@ "node": ">=8.0.0" } }, - "node_modules/electron/node_modules/@electron/get": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", - "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^9.6.0", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=8.6" - }, - "optionalDependencies": { - "global-agent": "^3.0.0", - "global-tunnel-ng": "^2.7.1" - } - }, - "node_modules/electron/node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/electron/node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/electron/node_modules/@types/node": { - "version": "14.18.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", - "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==" - }, - "node_modules/electron/node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/electron/node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/electron/node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "node_modules/electron/node_modules/extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dependencies": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - } - }, - "node_modules/electron/node_modules/extract-zip/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/electron/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/electron/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/electron/node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/electron/node_modules/got/node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron/node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" - }, - "node_modules/electron/node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/electron/node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/electron/node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/electron/node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/electron/node_modules/responselike/node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/emitter-listener": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", @@ -4475,8 +4215,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -4952,7 +4691,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", @@ -5372,8 +5110,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, - "peer": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -5546,21 +5282,6 @@ "node": ">=10.0" } }, - "node_modules/global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "optional": true, - "dependencies": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", @@ -5580,7 +5301,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -5678,8 +5398,7 @@ "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "devOptional": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "node_modules/he": { "version": "1.2.0", @@ -5833,7 +5552,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -6106,7 +5824,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true, "engines": { "node": ">=8" } @@ -6382,9 +6099,9 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "node_modules/jsdoc": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.0.tgz", - "integrity": "sha512-tzTgkklbWKrlaQL2+e3NNgLcZu3NaK2vsHRx7tyHQ+H5jcB9Gx0txSd2eJWlMC/xU1+7LQu4s58Ry0RkuaEQVg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.1.tgz", + "integrity": "sha512-UjvSrLYb270Mq25RN4AGGg2uqKRV90nCqkGsI4gD3RIR1lgMN8nWxK/am8Rsj33tWyprzZdA+0q1qY07m0Ar7w==", "dev": true, "dependencies": { "@babel/parser": "^7.9.4", @@ -6531,8 +6248,7 @@ "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -6612,7 +6328,6 @@ "version": "4.5.2", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -6891,8 +6606,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "optional": true, - "peer": true, "dependencies": { "semver": "^6.0.0" }, @@ -6907,8 +6620,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "optional": true, - "peer": true, "bin": { "semver": "bin/semver.js" } @@ -7268,9 +6979,7 @@ "node_modules/nan": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true, - "peer": true + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" }, "node_modules/nanoid": { "version": "3.1.30", @@ -7473,7 +7182,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "devOptional": true, "dependencies": { "abbrev": "1" }, @@ -7522,7 +7230,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, "engines": { "node": ">=10" }, @@ -7530,34 +7237,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "optional": true, - "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-conf/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "optional": true, - "engines": { - "node": ">=4" - } - }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "peer": true, "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -7614,6 +7297,11 @@ "node": ">= 0.4" } }, + "node_modules/ocrad.js": { + "version": "0.1.0", + "resolved": "git+ssh://git@github.com/antimatter15/ocrad.js.git#41daf0d2c2d0fc46db0633a6c6516af779b9f0bc", + "license": "GPL-3.0" + }, "node_modules/omggif": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", @@ -7745,7 +7433,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, "engines": { "node": ">=8" } @@ -7947,6 +7634,26 @@ "node": ">=4" } }, + "node_modules/path2d-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pdfjs-dist": { + "version": "3.3.122", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.3.122.tgz", + "integrity": "sha512-98WC09jOq3OuqrmF5+LZfcyzTlGA0sY9ocMBbWZ/H6Pwni7deptxwkNZVLieOz+4nSoTEW25PsfnfOj3ELrHdA==", + "dependencies": { + "path2d-polyfill": "^2.0.1", + "web-streams-polyfill": "^3.2.1" + }, + "optionalDependencies": { + "canvas": "^2.11.0" + } + }, "node_modules/peek-readable": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", @@ -8115,14 +7822,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", - "engines": { - "node": ">=4" - } - }, "node_modules/printj": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", @@ -8174,12 +7873,6 @@ "node": ">=10" } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "optional": true - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -8253,7 +7946,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "engines": { "node": ">=10" }, @@ -8617,8 +8309,7 @@ "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/resolve-cwd": { "version": "3.0.0", @@ -8645,7 +8336,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "dependencies": { "lowercase-keys": "^2.0.0" }, @@ -9044,8 +8734,7 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "devOptional": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "node_modules/setprototypeof": { "version": "1.1.1", @@ -9410,7 +9099,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9429,7 +9117,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -9769,14 +9456,6 @@ "tmp": "^0.2.0" } }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "engines": { - "node": ">=6" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9878,15 +9557,6 @@ "node": ">=0.6.x" } }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "optional": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -10064,17 +9734,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", @@ -10174,6 +9833,14 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -10366,7 +10033,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "devOptional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -10657,7 +10323,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.2.tgz", "integrity": "sha512-eFZVFoRXb3GFGd7Ak7W4+6jBl9wBtiZ4AaYOse97ej6mKj5tkyO0dUnUChs1IhJZtx1BENo4/p4WUTXpi6vT+g==", - "dev": true, "requires": { "debug": "^4.1.1", "env-paths": "^2.2.0", @@ -10673,7 +10338,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -10683,8 +10347,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -11194,8 +10857,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", - "optional": true, - "peer": true, "requires": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -11239,14 +10900,12 @@ "@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" }, "@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "requires": { "defer-to-connect": "^2.0.0" } @@ -11265,7 +10924,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", - "dev": true, "requires": { "@types/http-cache-semantics": "*", "@types/keyv": "*", @@ -11330,8 +10988,7 @@ "@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, "@types/json-schema": { "version": "7.0.9", @@ -11343,7 +11000,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", - "dev": true, "requires": { "@types/node": "*" } @@ -11385,8 +11041,7 @@ "@types/node": { "version": "16.11.46", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.46.tgz", - "integrity": "sha512-x+sfpb2dMrhCQPL4NAGs64Z9hh0t72aP0dg+PuZidmPr/0Gj5ELQTjD/t46dq3DF/8ZvSHOaIyDIbAsdPshyVQ==", - "devOptional": true + "integrity": "sha512-x+sfpb2dMrhCQPL4NAGs64Z9hh0t72aP0dg+PuZidmPr/0Gj5ELQTjD/t46dq3DF/8ZvSHOaIyDIbAsdPshyVQ==" }, "@types/plist": { "version": "3.0.2", @@ -11403,7 +11058,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, "requires": { "@types/node": "*" } @@ -11434,7 +11088,6 @@ "version": "2.9.2", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", - "dev": true, "optional": true, "requires": { "@types/node": "*" @@ -11633,8 +11286,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "devOptional": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "accepts": { "version": "1.3.8", @@ -11721,8 +11373,7 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -11886,8 +11537,7 @@ "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "devOptional": true + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" }, "archiver": { "version": "5.3.1", @@ -11941,8 +11591,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "peer": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -11952,8 +11600,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "optional": true, - "peer": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -12128,13 +11774,12 @@ } }, "better-sqlite3": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.4.5.tgz", - "integrity": "sha512-mybC3dgrtJeHkIRGP36tST7wjBlIMgTRAXhhO4bMpPZ17EG23FZxZeFcwKWy6o8mV1SKQFnQNyeAZlQpGrgheQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.1.0.tgz", + "integrity": "sha512-p1m09H+Oi8R9TPj810pdNswMFuVgRNgCJEWypp6jlkOgSwMIrNyuj3hW78xEuBRGok5RzeaUW8aBtTWF3l/TQA==", "requires": { "bindings": "^1.5.0", - "prebuild-install": "^7.0.0", - "tar": "^6.1.11" + "prebuild-install": "^7.1.0" } }, "binary-extensions": { @@ -12480,14 +12125,12 @@ "cacheable-lookup": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" }, "cacheable-request": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -12517,8 +12160,6 @@ "version": "2.11.0", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.0.tgz", "integrity": "sha512-bdTjFexjKJEwtIo0oRx8eD4G2yWoUOXP9lj279jmQ2zMnTQhT8C3512OKz3s+ZOaQlLbE7TuVvRDYDB3Llyy5g==", - "optional": true, - "peer": true, "requires": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", @@ -12529,8 +12170,6 @@ "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "optional": true, - "peer": true, "requires": { "mimic-response": "^2.0.0" } @@ -12538,16 +12177,12 @@ "mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "optional": true, - "peer": true + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" }, "simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "optional": true, - "peer": true, "requires": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -12755,8 +12390,7 @@ "color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "devOptional": true + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "colorette": { "version": "2.0.16", @@ -12878,29 +12512,10 @@ "typedarray": "^0.0.6" } }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "optional": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - }, - "dependencies": { - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "optional": true - } - } - }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "devOptional": true + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, "content-disposition": { "version": "0.5.4", @@ -13197,8 +12812,7 @@ "defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" }, "define-lazy-prop": { "version": "2.0.0", @@ -13223,8 +12837,7 @@ "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "devOptional": true + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, "depd": { "version": "1.1.2", @@ -13400,11 +13013,6 @@ "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true }, - "duplexer3": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", - "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -13428,183 +13036,13 @@ } }, "electron": { - "version": "16.2.8", - "resolved": "https://registry.npmjs.org/electron/-/electron-16.2.8.tgz", - "integrity": "sha512-KSOytY6SPLsh3iCziztqa/WgJyfDOKzCvNqku9gGIqSdT8CqtV66dTU1SOrKZQjRFLxHaF8LbyxUL1vwe4taqw==", + "version": "23.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-23.1.0.tgz", + "integrity": "sha512-LRgACMpVrmjfYWPgCSyJ+TFQ/FPeniOowpO57z0xUcTchfC7EH+5rUncgYN+uMvqePiYDce+ywZeCIFaO8x/Nw==", "requires": { - "@electron/get": "^1.13.0", - "@types/node": "^14.6.2", - "extract-zip": "^1.0.3" - }, - "dependencies": { - "@electron/get": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", - "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", - "requires": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "global-agent": "^3.0.0", - "global-tunnel-ng": "^2.7.1", - "got": "^9.6.0", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - } - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "@types/node": { - "version": "14.18.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.36.tgz", - "integrity": "sha512-FXKWbsJ6a1hIrRxv+FoukuHnGTgEzKYGi7kilfMae96AL9UNkPFNWJEEYWzdRI9ooIkbr4AKldyuSTLql06vLQ==" - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - } - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "requires": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - } - } - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", - "requires": { - "lowercase-keys": "^1.0.0" - }, - "dependencies": { - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - } - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "@electron/get": "^2.0.0", + "@types/node": "^16.11.26", + "extract-zip": "^2.0.1" } }, "electron-builder": { @@ -14075,8 +13513,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -14420,7 +13857,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "requires": { "@types/yauzl": "^2.9.1", "debug": "^4.1.1", @@ -14752,8 +14188,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, - "peer": true, "requires": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -14895,18 +14329,6 @@ "serialize-error": "^7.0.1" } }, - "global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "optional": true, - "requires": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" - } - }, "globalthis": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", @@ -14920,7 +14342,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "requires": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", @@ -14990,8 +14411,7 @@ "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "devOptional": true + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, "he": { "version": "1.2.0", @@ -15109,7 +14529,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "requires": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" @@ -15305,8 +14724,7 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-function": { "version": "1.0.2", @@ -15523,9 +14941,9 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdoc": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.0.tgz", - "integrity": "sha512-tzTgkklbWKrlaQL2+e3NNgLcZu3NaK2vsHRx7tyHQ+H5jcB9Gx0txSd2eJWlMC/xU1+7LQu4s58Ry0RkuaEQVg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.1.tgz", + "integrity": "sha512-UjvSrLYb270Mq25RN4AGGg2uqKRV90nCqkGsI4gD3RIR1lgMN8nWxK/am8Rsj33tWyprzZdA+0q1qY07m0Ar7w==", "dev": true, "requires": { "@babel/parser": "^7.9.4", @@ -15632,8 +15050,7 @@ "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "json-parse-even-better-errors": { "version": "2.3.1", @@ -15701,7 +15118,6 @@ "version": "4.5.2", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, "requires": { "json-buffer": "3.0.1" } @@ -15928,8 +15344,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "optional": true, - "peer": true, "requires": { "semver": "^6.0.0" }, @@ -15937,9 +15351,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "optional": true, - "peer": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -16212,9 +15624,7 @@ "nan": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==", - "optional": true, - "peer": true + "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" }, "nanoid": { "version": "3.1.30", @@ -16375,7 +15785,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "devOptional": true, "requires": { "abbrev": "1" } @@ -16413,33 +15822,12 @@ "normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "optional": true, - "requires": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "optional": true - } - } + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, "npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "peer": true, "requires": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -16481,6 +15869,10 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "optional": true }, + "ocrad.js": { + "version": "git+ssh://git@github.com/antimatter15/ocrad.js.git#41daf0d2c2d0fc46db0633a6c6516af779b9f0bc", + "from": "ocrad.js@antimatter15/ocrad.js#master" + }, "omggif": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", @@ -16583,8 +15975,7 @@ "p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" }, "p-limit": { "version": "2.2.1", @@ -16743,6 +16134,21 @@ "pify": "^2.0.0" } }, + "path2d-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==" + }, + "pdfjs-dist": { + "version": "3.3.122", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.3.122.tgz", + "integrity": "sha512-98WC09jOq3OuqrmF5+LZfcyzTlGA0sY9ocMBbWZ/H6Pwni7deptxwkNZVLieOz+4nSoTEW25PsfnfOj3ELrHdA==", + "requires": { + "canvas": "^2.11.0", + "path2d-polyfill": "^2.0.1", + "web-streams-polyfill": "^3.2.1" + } + }, "peek-readable": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", @@ -16865,11 +16271,6 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==" - }, "printj": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz", @@ -16906,12 +16307,6 @@ "retry": "^0.12.0" } }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "optional": true - }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -16969,8 +16364,7 @@ "quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, "rand-token": { "version": "1.0.1", @@ -17263,8 +16657,7 @@ "resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "resolve-cwd": { "version": "3.0.0", @@ -17285,7 +16678,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "requires": { "lowercase-keys": "^2.0.0" } @@ -17602,8 +16994,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "devOptional": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "setprototypeof": { "version": "1.1.1", @@ -17874,7 +17265,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -17890,7 +17280,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, "requires": { "ansi-regex": "^5.0.1" } @@ -18137,11 +17526,6 @@ "tmp": "^0.2.0" } }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -18217,12 +17601,6 @@ "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "optional": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -18369,14 +17747,6 @@ "requires-port": "^1.0.0" } }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", - "requires": { - "prepend-http": "^2.0.0" - } - }, "utf8-byte-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", @@ -18457,6 +17827,11 @@ "defaults": "^1.0.3" } }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, "webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -18585,7 +17960,6 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "devOptional": true, "requires": { "string-width": "^1.0.2 || 2 || 3 || 4" } diff --git a/package.json b/package.json index 599c24dd1..b2cf4758b 100644 --- a/package.json +++ b/package.json @@ -19,14 +19,12 @@ "start-electron-no-dir": "cross-env TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 electron --inspect=5858 .", "switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install", "switch-electron": "rm -rf ./node_modules/better-sqlite3 && npm install && ./node_modules/.bin/electron-rebuild", - "build-backend-docs": "rm -rf ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js", - "build-frontend-docs": "rm -rf ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js", - "build-docs": "npm run build-backend-docs && npm run build-frontend-docs", + "build-api-docs": "./bin/build-api-docs.sh", "webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js", "test-jasmine": "jasmine", "test-es6": "node -r esm spec-es6/attribute_parser.spec.js ", "test": "npm run test-jasmine && npm run test-es6", - "postinstall": "rimraf ./node_modules/canvas" + "postinstall": "node src-build/fix_pdfjs.js" }, "dependencies": { "@braintree/sanitize-url": "6.0.2", @@ -35,7 +33,8 @@ "archiver": "5.3.1", "async-mutex": "0.4.0", "axios": "1.3.3", - "better-sqlite3": "7.4.5", + "better-sqlite3": "8.1.0", + "canvas": "2.11.0", "chokidar": "3.5.3", "cls-hooked": "4.2.2", "commonmark": "0.30.0", @@ -71,12 +70,13 @@ "multer": "1.4.5-lts.1", "node-abi": "3.33.0", "normalize-strings": "1.1.1", + "ocrad.js": "antimatter15/ocrad.js#master", "open": "8.4.1", + "pdfjs-dist": "3.3.122", "rand-token": "1.0.1", "react": "17.0.2", "react-dom": "17.0.2", "request": "2.88.2", - "rimraf": "3.0.2", "safe-compare": "1.1.4", "sanitize-filename": "1.6.3", "sanitize-html": "2.9.0", @@ -95,13 +95,13 @@ }, "devDependencies": { "cross-env": "7.0.3", - "electron": "16.2.8", + "electron": "23.1.0", "electron-builder": "23.6.0", "electron-packager": "17.1.1", "electron-rebuild": "3.2.9", "esm": "3.2.25", "jasmine": "4.5.0", - "jsdoc": "4.0.0", + "jsdoc": "4.0.1", "lorem-ipsum": "2.0.8", "rcedit": "3.0.1", "webpack": "5.75.0", diff --git a/src-build/docs-website/build_docs_website.js b/src-build/docs-website/build_docs_website.js new file mode 100644 index 000000000..bdcb913c5 --- /dev/null +++ b/src-build/docs-website/build_docs_website.js @@ -0,0 +1,129 @@ +const fs = require("fs-extra"); +const utils = require("../../src/services/utils"); +const html = require("html"); + +const SRC_DIR = './src-build/docs-website'; +const USER_GUIDE_DIR = './docs/user_guide'; +const META_PATH = USER_GUIDE_DIR + '/!!!meta.json'; +const WEB_TMP_DIR = './tmp/user_guide_web'; +fs.copySync(USER_GUIDE_DIR, WEB_TMP_DIR); + +const meta = JSON.parse(readFile(META_PATH)); +const rootNoteMeta = meta.files[0]; +const noteIdToMeta = {}; +createNoteIdToMetaMapping(rootNoteMeta); + +addNavigationAndStyle(rootNoteMeta, WEB_TMP_DIR); + +fs.writeFileSync(WEB_TMP_DIR + '/main.js', readFile(SRC_DIR + "/main.js")); +fs.writeFileSync(WEB_TMP_DIR + '/main.css', readFile(SRC_DIR + "/main.css")); +fs.cpSync('libraries/ckeditor/ckeditor-content.css' ,WEB_TMP_DIR + '/ckeditor-content.css'); + +function addNavigationAndStyle(noteMeta, parentDirPath) { + const nav = createNavigation(rootNoteMeta, noteMeta); + + if (noteMeta.dataFileName) { + const filePath = parentDirPath + "/" + noteMeta.dataFileName; + + console.log(`Adding nav to ${filePath}`); + + const content = readFile(filePath); + const depth = noteMeta.notePath.length - 1; + const updatedContent = content + .replaceAll("", ` + + +`) + .replaceAll("", nav + ""); + const prettified = html.prettyPrint(updatedContent, {indent_size: 2}); + fs.writeFileSync(filePath, prettified); + } + + for (const childNoteMeta of noteMeta.children || []) { + addNavigationAndStyle(childNoteMeta, parentDirPath + '/' + noteMeta.dirFileName); + } +} + +function createNavigation(rootMeta, sourceMeta) { + function saveNavigationInner(meta, parentNoteId = 'root') { + let html = `
  • `; + + const escapedTitle = utils.escapeHtml(`${meta.prefix ? `${meta.prefix} - ` : ''}${meta.title}`); + + if (meta.dataFileName) { + const targetUrl = getTargetUrl(meta.noteId, sourceMeta); + + html += `${escapedTitle}`; + } + else { + html += escapedTitle; + } + + if (meta.children && meta.children.length > 0) { + html += '' + } + + return `${html}
  • `; + } + + return ``; +} + +function createNoteIdToMetaMapping(noteMeta) { + noteIdToMeta[noteMeta.noteId] = noteMeta; + + for (const childNoteMeta of noteMeta.children || []) { + createNoteIdToMetaMapping(childNoteMeta); + } +} + +function getTargetUrl(targetNoteId, sourceMeta) { + const targetMeta = noteIdToMeta[targetNoteId]; + + if (!targetMeta) { + throw new Error(`Could not find note meta for noteId '${targetNoteId}'`); + } + + const targetPath = targetMeta.notePath.slice(); + const sourcePath = sourceMeta.notePath.slice(); + + // > 1 for edge case that targetPath and sourcePath are exact same (link to itself) + while (targetPath.length > 1 && sourcePath.length > 1 && targetPath[0] === sourcePath[0]) { + targetPath.shift(); + sourcePath.shift(); + } + + let url = "../".repeat(sourcePath.length - 1); + + for (let i = 0; i < targetPath.length - 1; i++) { + const meta = noteIdToMeta[targetPath[i]]; + + if (!meta) { + throw new Error(`Cannot resolve note '${targetPath[i]}' from path '${targetPath.toString()}'`); + } + + url += `${encodeURIComponent(meta.dirFileName)}/`; + } + + const targetPathNoteId = targetPath[targetPath.length - 1]; + const meta = noteIdToMeta[targetPathNoteId]; + + if (!meta) { + throw new Error(`Cannot resolve note '${targetPathNoteId}' from path '${targetPath.toString()}'`); + } + + // link can target note which is only "folder-note" and as such will not have a file in an export + url += encodeURIComponent(meta.dataFileName || meta.dirFileName); + + return url; +} + +function readFile(filePath) { + return fs.readFileSync(filePath).toString(); +} diff --git a/src-build/docs-website/main.css b/src-build/docs-website/main.css new file mode 100644 index 000000000..7ae2ed218 --- /dev/null +++ b/src-build/docs-website/main.css @@ -0,0 +1,45 @@ +body { + display: flex; + flex-direction: row-reverse; + width: 1100px; + margin: auto; + font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif; +} + +.note-tree-nav { + padding-top: 10px; + width: 300px; + margin-right: 20px; + overflow-x: auto; +} + +.note-tree-nav ul { + padding-left: 20px; + list-style-type: none; +} + +.note-tree-nav ul li { + line-height: 150%; + font-size: 105%; +} + +.note-tree-nav > ul > li > a { + font-size: x-large; +} + +.note-tree-nav a { + text-decoration: none; +} + +.note-tree-nav li span.expander, .note-tree-nav li span.spacer { + width: 1em; + display: inline-block; +} + +.note-tree-nav li span.expander { + cursor: pointer; +} + +.content { + width: 780px; +} diff --git a/src-build/docs-website/main.js b/src-build/docs-website/main.js new file mode 100644 index 000000000..16c04cd58 --- /dev/null +++ b/src-build/docs-website/main.js @@ -0,0 +1,30 @@ +document.addEventListener('DOMContentLoaded', function () { + for (const li of document.querySelectorAll('.note-tree-nav li')) { + const branchId = li.getAttribute("data-branch-id"); + if (branchId.startsWith("root_")) { + // first level is expanded and cannot be collapsed + continue; + } + + const newDiv = document.createElement("span"); + const subList = li.querySelector('ul'); + + if (subList) { + const toggleVisibility = (show) => { + newDiv.innerHTML = show ? "▾ " : "▸ "; + subList.style.display = show ? 'block' : 'none'; + + localStorage.setItem(branchId, show ? "true" : "false"); + }; + + newDiv.classList.add("expander"); + newDiv.addEventListener('click', () => toggleVisibility(subList.style.display === 'none')); + + toggleVisibility(localStorage.getItem(branchId) === "true"); + } else { + newDiv.classList.add("spacer"); + } + + li.prepend(newDiv); + } +}, false); diff --git a/src-build/fix_pdfjs.js b/src-build/fix_pdfjs.js new file mode 100644 index 000000000..7bf78bb30 --- /dev/null +++ b/src-build/fix_pdfjs.js @@ -0,0 +1,12 @@ +const fs = require("fs"); + +const PACKAGE_JSON_PATH = './node_modules/pdfjs-dist/package.json'; + +const packageJson = JSON.parse( + fs.readFileSync(PACKAGE_JSON_PATH).toString() +); + +// non-legacy build doesn't work on node 16 at least +packageJson.main = "legacy/build/pdf.js"; + +fs.writeFileSync(PACKAGE_JSON_PATH, JSON.stringify(packageJson, null, 2)); \ No newline at end of file diff --git a/src-build/transform_api_docs.js b/src-build/transform_api_docs.js new file mode 100644 index 000000000..ed944481d --- /dev/null +++ b/src-build/transform_api_docs.js @@ -0,0 +1,260 @@ +const sanitizeHtml = require('sanitize-html'); + +const fs = require("fs"); +const path = require("path"); +const html = require("html"); + +const TMP_API_DOCS = './tmp/api_docs'; +const TMP_FE_DOCS = TMP_API_DOCS + '/frontend_api'; +const TMP_BE_DOCS = TMP_API_DOCS + '/backend_api'; + +const sourceFiles = getFilesRecursively(TMP_API_DOCS); + +for (const sourcePath of sourceFiles) { + const content = fs.readFileSync(sourcePath).toString(); + const transformedContent = transform(content); + const prettifiedContent = html.prettyPrint(transformedContent, {indent_size: 2}); + const filteredContent = prettifiedContent + .replace(/
    Documentation generated by [^<]+<\/a>/gi, '') + .replace(/JSDoc: (Class|Module): [a-z]+/gi, ''); + + const destPath = sourcePath.replaceAll("tmp", "docs"); + + fs.mkdirSync(path.dirname(destPath), {recursive: true}); + fs.writeFileSync(destPath, filteredContent.trim()); + + console.log(destPath); +} + +const USER_GUIDE_DIR = './docs/user_guide'; +const META_PATH = USER_GUIDE_DIR + '/!!!meta.json'; + +const meta = JSON.parse(fs.readFileSync(META_PATH).toString()); +const rootNoteMeta = meta.files[0]; + +const {noteMeta: scriptApiDocsRoot, filePath: scriptApiDocsRootFilePath, notePath: scriptApiDocsRootNotePath} = + findNoteMeta(rootNoteMeta, 'Script API', []); +const BE_FILES = ['AbstractBeccaEntity', 'BAttribute', 'BBranch', 'BEtapiToken', 'BNote', 'BNoteRevision', 'BOption', 'BRecentNote', 'module-sql']; + +const FE_FILES = ['FNote', 'FAttribute', 'FBranch', 'FNoteComplement']; + +scriptApiDocsRoot.dirFileName = scriptApiDocsRoot.dataFileName.substr(0, scriptApiDocsRoot.dataFileName.length - 5); +scriptApiDocsRoot.children = getScriptApiMeta(); + +fs.writeFileSync(META_PATH, JSON.stringify(meta, null, 2)); +const scriptApiDocsRootDir = USER_GUIDE_DIR + scriptApiDocsRootFilePath; + +fs.mkdirSync(scriptApiDocsRootDir, {recursive: true}); +fs.mkdirSync(scriptApiDocsRootDir + '/BackendScriptApi', {recursive: true}); +fs.mkdirSync(scriptApiDocsRootDir + '/FrontendScriptApi', {recursive: true}); + +const BE_ROOT = scriptApiDocsRootDir + '/BackendScriptApi.html'; +const FE_ROOT = scriptApiDocsRootDir + '/FrontendScriptApi.html'; + +fs.copyFileSync(TMP_BE_DOCS + '/BackendScriptApi.html', BE_ROOT); +fs.copyFileSync(TMP_FE_DOCS + '/FrontendScriptApi.html', FE_ROOT); + +for (const file of BE_FILES) { + fs.copyFileSync(TMP_BE_DOCS + '/' + file + '.html', `${scriptApiDocsRootDir}/BackendScriptApi/${file}.html`); +} +rewriteLinks(BE_ROOT, BE_FILES, 'BackendScriptApi'); + +for (const file of FE_FILES) { + fs.copyFileSync(TMP_FE_DOCS + '/' + file + '.html', `${scriptApiDocsRootDir}/FrontendScriptApi/${file}.html`); +} +rewriteLinks(FE_ROOT, FE_FILES, 'FrontendScriptApi'); + +fs.rmSync(USER_GUIDE_DIR + '/index.html', {force: true}); +fs.rmSync(USER_GUIDE_DIR + '/navigation.html', {force: true}); +fs.rmSync(USER_GUIDE_DIR + '/style.css', {force: true}); + + + + + + + + + +function getFilesRecursively(directory) { + const files = []; + + function getFilesRecursivelyInner(directory) { + const filesInDirectory = fs.readdirSync(directory); + for (const file of filesInDirectory) { + const absolute = path.join(directory, file); + if (fs.statSync(absolute).isDirectory()) { + getFilesRecursivelyInner(absolute); + } else if (file.endsWith('.html')) { + files.push(absolute); + } + } + } + + getFilesRecursivelyInner(directory); + + return files; +} + +function transform(content) { + const result = sanitizeHtml(content, { + allowedTags: [ + 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', + 'li', 'b', 'i', 'strong', 'em', 'strike', 's', 'del', 'abbr', 'code', 'hr', 'br', 'div', + 'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'section', 'img', + 'figure', 'figcaption', 'span', 'label', 'input', + ], + nonTextTags: [ 'style', 'script', 'textarea', 'option', 'h1', 'h2', 'h3', 'nav' ], + allowedAttributes: { + 'a': [ 'href', 'class', 'data-note-path' ], + 'img': [ 'src' ], + 'section': [ 'class', 'data-note-id' ], + 'figure': [ 'class' ], + 'span': [ 'class', 'style' ], + 'label': [ 'class' ], + 'input': [ 'class', 'type', 'disabled' ], + 'code': [ 'class' ], + 'ul': [ 'class' ], + 'table': [ 'class' ], + 'en-media': [ 'hash' ] + }, + allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'data', 'evernote'], + transformTags: { + // 'h5': sanitizeHtml.simpleTransform('strong', {}, false), + 'table': sanitizeHtml.simpleTransform('table', {}, false) + }, + }); + + return result.replace(//gi, '
    ') + .replace(/<\/table>/gi, '
    ') + .replace(/
    <\/div>/gi, '') + .replace(/
    /gi, '

    ') + .replace(/<\/h5>/gi, '

    ') + .replace(/

    /gi, '

    ') + .replace(/<\/h4>/gi, '

    ') + .replace(/opt<\/span>/gi, '') + .replace(/

    .*new (BackendScriptApi|FrontendScriptApi).*<\/h2>/gi, '') + ; +} + +function findNoteMeta(noteMeta, name, notePath) { + if (noteMeta.title === name) { + return { + noteMeta, + filePath: '/' + noteMeta.dirFileName, + notePath + }; + } + + for (const childMeta of noteMeta.children || []) { + const ret = findNoteMeta(childMeta, name, [...notePath, childMeta.noteId]); + + if (ret) { + return { + noteMeta: ret.noteMeta, + filePath: '/' + noteMeta.dirFileName + ret.filePath, + notePath: ret.notePath + }; + } + } + + return null; +} + +function rewriteLinks(rootFilePath, files, dir) { + let content = fs.readFileSync(rootFilePath).toString(); + + for (const file of files) { + content = content.replaceAll(`href="${file}.html"`, `href="${dir}/${file}.html"`); + } + + fs.writeFileSync(rootFilePath, content); +} + +function createChildren(files, notePath) { + let positionCounter = 0; + + const camelCase = name => { + if (name === 'module-sql') { + return 'moduleSql'; + } else if (/[^a-z]+/i.test(name)) { + throw new Error(`Bad name '${name}'`); + } + + return name.charAt(0).toLowerCase() + name.substr(1); + }; + + return files.map(file => { + positionCounter += 10; + + const noteId = "_" + camelCase(file); + + return { + "isClone": false, + "noteId": noteId, + "notePath": [ + ...notePath, + '_' + camelCase(file) + ], + "title": file, + "notePosition": positionCounter, + "prefix": null, + "isExpanded": false, + "type": "text", + "mime": "text/html", + "attributes": [], + "format": "html", + "dataFileName": file + ".html" + } + }); +} + +function getScriptApiMeta() { + return [ + { + "isClone": false, + "noteId": "_frontendApi", + "notePath": [ + ...scriptApiDocsRootNotePath, + "_frontendApi" + ], + "title": "API docs", + "notePosition": 10, + "prefix": null, + "isExpanded": false, + "type": "text", + "mime": "text/html", + "attributes": [], + "format": "html", + "dataFileName": "FrontendScriptApi.html", + "dirFileName": "FrontendScriptApi", + "children": createChildren(FE_FILES, [ + ...scriptApiDocsRootNotePath, + "_frontendApi" + ]) + }, + { + "isClone": false, + "noteId": "_backendApi", + "notePath": [ + ...scriptApiDocsRootNotePath, + "_backendApi" + ], + "title": "API docs", + "notePosition": 20, + "prefix": null, + "isExpanded": false, + "type": "text", + "mime": "text/html", + "attributes": [], + "format": "html", + "dataFileName": "BackendScriptApi.html", + "dirFileName": "BackendScriptApi", + "children": createChildren(BE_FILES, [ + ...scriptApiDocsRootNotePath, + "_backendApi" + ]) + } + ]; +} + diff --git a/src/becca/becca.js b/src/becca/becca.js index 60422e672..3f142f35b 100644 --- a/src/becca/becca.js +++ b/src/becca/becca.js @@ -121,6 +121,14 @@ class Becca { return row ? new BNoteRevision(row) : null; } + /** @returns {BNoteAncillary|null} */ + getNoteAncillary(noteAncillaryId) { + const row = sql.getRow("SELECT * FROM note_ancillaries WHERE noteAncillaryId = ?", [noteAncillaryId]); + + const BNoteAncillary = require("./entities/bnote_ancillary"); // avoiding circular dependency problems + return row ? new BNoteAncillary(row) : null; + } + /** @returns {BOption|null} */ getOption(name) { return this.options[name]; @@ -143,6 +151,8 @@ class Becca { if (entityName === 'note_revisions') { return this.getNoteRevision(entityId); + } else if (entityName === 'note_ancillaries') { + return this.getNoteAncillary(entityId); } const camelCaseEntityName = entityName.toLowerCase().replace(/(_[a-z])/g, diff --git a/src/becca/entities/bbranch.js b/src/becca/entities/bbranch.js index 18b19588c..06912b9fb 100644 --- a/src/becca/entities/bbranch.js +++ b/src/becca/entities/bbranch.js @@ -198,6 +198,10 @@ class BBranch extends AbstractBeccaEntity { relation.markAsDeleted(deleteId); } + for (const noteAncillary of note.getNoteAncillaries()) { + noteAncillary.markAsDeleted(deleteId); + } + note.markAsDeleted(deleteId); return true; diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js index 8a752058a..249c5ce1f 100644 --- a/src/becca/entities/bnote.js +++ b/src/becca/entities/bnote.js @@ -8,6 +8,7 @@ const dateUtils = require('../../services/date_utils'); const entityChangesService = require('../../services/entity_changes'); const AbstractBeccaEntity = require("./abstract_becca_entity"); const BNoteRevision = require("./bnote_revision"); +const BNoteAncillary = require("./bnote_ancillary"); const TaskContext = require("../../services/task_context"); const dayjs = require("dayjs"); const utc = require('dayjs/plugin/utc'); @@ -336,7 +337,7 @@ class BNote extends AbstractBeccaEntity { return this.mime === "application/json"; } - /** @returns {boolean} true if this note is JavaScript (code or attachment) */ + /** @returns {boolean} true if this note is JavaScript (code or file) */ isJavaScript() { return (this.type === "code" || this.type === "file" || this.type === 'launcher') && (this.mime.startsWith("application/javascript") @@ -1135,6 +1136,19 @@ class BNote extends AbstractBeccaEntity { .map(row => new BNoteRevision(row)); } + /** @returns {BNoteAncillary[]} */ + getNoteAncillaries() { + return sql.getRows("SELECT * FROM note_ancillaries WHERE noteId = ? AND isDeleted = 0", [this.noteId]) + .map(row => new BNoteAncillary(row)); + } + + /** @returns {BNoteAncillary|undefined} */ + getNoteAncillaryByName(name) { + return sql.getRows("SELECT * FROM note_ancillaries WHERE noteId = ? AND name = ? AND isDeleted = 0", [this.noteId, name]) + .map(row => new BNoteAncillary(row)) + [0]; + } + /** * @returns {string[][]} - array of notePaths (each represented by array of noteIds constituting the particular note path) */ @@ -1464,6 +1478,31 @@ class BNote extends AbstractBeccaEntity { return noteRevision; } + /** + * @returns {BNoteAncillary} + */ + saveNoteAncillary(name, mime, content) { + let noteAncillary = this.getNoteAncillaryByName(name); + + if (noteAncillary + && noteAncillary.mime === mime + && noteAncillary.contentCheckSum === noteAncillary.calculateCheckSum(content)) { + + return noteAncillary; // no change + } + + noteAncillary = new BNoteAncillary({ + noteId: this.noteId, + name, + mime, + isProtected: this.isProtected + }); + + noteAncillary.setContent(content); + + return noteAncillary; + } + beforeSaving() { super.beforeSaving(); diff --git a/src/becca/entities/bnote_ancillary.js b/src/becca/entities/bnote_ancillary.js new file mode 100644 index 000000000..600889391 --- /dev/null +++ b/src/becca/entities/bnote_ancillary.js @@ -0,0 +1,161 @@ +"use strict"; + +const protectedSessionService = require('../../services/protected_session'); +const utils = require('../../services/utils'); +const sql = require('../../services/sql'); +const dateUtils = require('../../services/date_utils'); +const becca = require('../becca'); +const entityChangesService = require('../../services/entity_changes'); +const AbstractBeccaEntity = require("./abstract_becca_entity"); + +/** + * NoteAncillary represent data related/attached to the note. Conceptually similar to attributes, but intended for + * larger amounts of data and generally not accessible to the user. + * + * @extends AbstractBeccaEntity + */ +class BNoteAncillary extends AbstractBeccaEntity { + static get entityName() { return "note_ancillaries"; } + static get primaryKeyName() { return "noteAncillaryId"; } + static get hashedProperties() { return ["noteAncillaryId", "noteId", "name", "content", "utcDateModified"]; } + + constructor(row) { + super(); + + if (!row.noteId) { + throw new Error("'noteId' must be given to initialize a NoteAncillary entity"); + } + + if (!row.name) { + throw new Error("'name' must be given to initialize a NoteAncillary entity"); + } + + /** @type {string} needs to be set at the initialization time since it's used in the .setContent() */ + this.noteAncillaryId = row.noteAncillaryId || `${this.noteId}_${this.name}`; + /** @type {string} */ + this.noteId = row.noteId; + /** @type {string} */ + this.name = row.name; + /** @type {string} */ + this.mime = row.mime; + /** @type {boolean} */ + this.isProtected = !!row.isProtected; + /** @type {string} */ + this.contentCheckSum = row.contentCheckSum; + /** @type {string} */ + this.utcDateModified = row.utcDateModified; + } + + getNote() { + return becca.notes[this.noteId]; + } + + /** @returns {boolean} true if the note has string content (not binary) */ + isStringNote() { + return utils.isStringNote(this.type, this.mime); + } + + /** @returns {*} */ + getContent(silentNotFoundError = false) { + const res = sql.getRow(`SELECT content FROM note_ancillary_contents WHERE noteAncillaryId = ?`, [this.noteAncillaryId]); + + if (!res) { + if (silentNotFoundError) { + return undefined; + } + else { + throw new Error(`Cannot find note ancillary content for noteAncillaryId=${this.noteAncillaryId}`); + } + } + + let content = res.content; + + if (this.isProtected) { + if (protectedSessionService.isProtectedSessionAvailable()) { + content = protectedSessionService.decrypt(content); + } + else { + content = ""; + } + } + + if (this.isStringNote()) { + return content === null + ? "" + : content.toString("UTF-8"); + } + else { + return content; + } + } + + setContent(content) { + sql.transactional(() => { + this.contentCheckSum = this.calculateCheckSum(content); + this.save(); // also explicitly save note_ancillary to update contentCheckSum + + const pojo = { + noteAncillaryId: this.noteAncillaryId, + content: content, + utcDateModified: dateUtils.utcNowDateTime() + }; + + if (this.isProtected) { + if (protectedSessionService.isProtectedSessionAvailable()) { + pojo.content = protectedSessionService.encrypt(pojo.content); + } else { + throw new Error(`Cannot update content of noteAncillaryId=${this.noteAncillaryId} since we're out of protected session.`); + } + } + + sql.upsert("note_ancillary_contents", "noteAncillaryId", pojo); + + entityChangesService.addEntityChange({ + entityName: 'note_ancillary_contents', + entityId: this.noteAncillaryId, + hash: this.contentCheckSum, + isErased: false, + utcDateChanged: pojo.utcDateModified, + isSynced: true + }); + }); + } + + calculateCheckSum(content) { + return utils.hash(`${this.noteAncillaryId}|${content.toString()}`); + } + + beforeSaving() { + if (!this.name.match(/^[a-z0-9]+$/i)) { + throw new Error(`Name must be alphanumerical, "${this.name}" given.`); + } + + this.noteAncillaryId = `${this.noteId}_${this.name}`; + + super.beforeSaving(); + + this.utcDateModified = dateUtils.utcNowDateTime(); + } + + getPojo() { + return { + noteAncillaryId: this.noteAncillaryId, + noteId: this.noteId, + name: this.name, + mime: this.mime, + isProtected: !!this.isProtected, + contentCheckSum: this.contentCheckSum, + isDeleted: false, + utcDateModified: this.utcDateModified + }; + } + + getPojoToSave() { + const pojo = this.getPojo(); + delete pojo.content; // not getting persisted + + return pojo; + } +} + +module.exports = BNoteAncillary; diff --git a/src/becca/entity_constructor.js b/src/becca/entity_constructor.js index 17f186854..2b2cdf3c7 100644 --- a/src/becca/entity_constructor.js +++ b/src/becca/entity_constructor.js @@ -1,5 +1,6 @@ const BNote = require('./entities/bnote'); const BNoteRevision = require('./entities/bnote_revision'); +const BNoteAncillary = require("./entities/bnote_ancillary"); const BBranch = require('./entities/bbranch'); const BAttribute = require('./entities/battribute'); const BRecentNote = require('./entities/brecent_note'); @@ -13,6 +14,8 @@ const ENTITY_NAME_TO_ENTITY = { "note_contents": BNote, "note_revisions": BNoteRevision, "note_revision_contents": BNoteRevision, + "note_ancillaries": BNoteAncillary, + "note_ancillary_contents": BNoteAncillary, "recent_notes": BRecentNote, "etapi_tokens": BEtapiToken, "options": BOption diff --git a/src/public/app/components/root_command_executor.js b/src/public/app/components/root_command_executor.js index a3d41e48a..12bf68156 100644 --- a/src/public/app/components/root_command_executor.js +++ b/src/public/app/components/root_command_executor.js @@ -124,4 +124,12 @@ export default class RootCommandExecutor extends Component { await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'source' }); } } + + async showNoteAncillariesCommand() { + const notePath = appContext.tabManager.getActiveContextNotePath(); + + if (notePath) { + await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'ancillaries' }); + } + } } diff --git a/src/public/app/services/froca_updater.js b/src/public/app/services/froca_updater.js index 64eb653c0..a858f64ea 100644 --- a/src/public/app/services/froca_updater.js +++ b/src/public/app/services/froca_updater.js @@ -36,7 +36,7 @@ async function processEntityChanges(entityChanges) { loadResults.addOption(ec.entity.name); } - else if (['etapi_tokens'].includes(ec.entityName)) { + else if (['etapi_tokens', 'note_ancillaries', 'note_ancillary_contents'].includes(ec.entityName)) { // NOOP } else { diff --git a/src/public/app/widgets/buttons/note_actions.js b/src/public/app/widgets/buttons/note_actions.js index fb2c19918..b75c118a5 100644 --- a/src/public/app/widgets/buttons/note_actions.js +++ b/src/public/app/widgets/buttons/note_actions.js @@ -28,6 +28,7 @@ const TPL = ` Re-render note Search in note Note source + Note ancillaries Open note externally Import files Export note diff --git a/src/public/app/widgets/mermaid.js b/src/public/app/widgets/mermaid.js index d07ce83e0..2376be779 100644 --- a/src/public/app/widgets/mermaid.js +++ b/src/public/app/widgets/mermaid.js @@ -78,6 +78,14 @@ export default class MermaidWidget extends NoteContextAwareWidget { await this.renderSvg(async renderedSvg => { this.$display.html(renderedSvg); + // not awaiting intentionally + // this is pretty hacky since we update ancillary on render + // but if nothing changed this should not trigger DB write and sync + server.put(`notes/${note.noteId}/ancillaries/mermaidSvg`, { + mime: 'image/svg+xml', + content: renderedSvg + }); + await wheelZoomLoaded; this.$display.attr("id", `mermaid-render-${idCounter}`); diff --git a/src/public/app/widgets/note_detail.js b/src/public/app/widgets/note_detail.js index 4dfa9a2d7..8c2c49695 100644 --- a/src/public/app/widgets/note_detail.js +++ b/src/public/app/widgets/note_detail.js @@ -27,6 +27,7 @@ import NoteMapTypeWidget from "./type_widgets/note_map.js"; import WebViewTypeWidget from "./type_widgets/web_view.js"; import DocTypeWidget from "./type_widgets/doc.js"; import ContentWidgetTypeWidget from "./type_widgets/content_widget.js"; +import AncillariesTypeWidget from "./type_widgets/ancillaries.js"; const TPL = `
    @@ -61,7 +62,8 @@ const typeWidgetClasses = { 'noteMap': NoteMapTypeWidget, 'webView': WebViewTypeWidget, 'doc': DocTypeWidget, - 'contentWidget': ContentWidgetTypeWidget + 'contentWidget': ContentWidgetTypeWidget, + 'ancillaries': AncillariesTypeWidget }; export default class NoteDetailWidget extends NoteContextAwareWidget { @@ -189,6 +191,8 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { if (type === 'text' && this.noteContext.viewScope.viewMode === 'source') { type = 'readOnlyCode'; + } else if (this.noteContext.viewScope.viewMode === 'ancillaries') { + type = 'ancillaries'; } else if (type === 'text' && await this.noteContext.isReadOnly()) { type = 'readOnlyText'; } else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) { diff --git a/src/public/app/widgets/type_widgets/ancillaries.js b/src/public/app/widgets/type_widgets/ancillaries.js new file mode 100644 index 000000000..a88d39f53 --- /dev/null +++ b/src/public/app/widgets/type_widgets/ancillaries.js @@ -0,0 +1,79 @@ +import TypeWidget from "./type_widget.js"; +import server from "../../services/server.js"; + +const TPL = ` +
    + + +
    + Note ancillaries are pieces of data attached to a given note, providing ancillary support. + This view is useful for diagnostics. +
    + +
    +
    `; + +export default class AncillariesTypeWidget extends TypeWidget { + static getType() { return "ancillaries"; } + + doRender() { + this.$widget = $(TPL); + this.$list = this.$widget.find('.note-ancillary-list'); + + super.doRender(); + } + + async doRefresh(note) { + this.$list.empty(); + + const ancillaries = await server.get(`notes/${this.noteId}/ancillaries?includeContent=true`); + + if (ancillaries.length === 0) { + this.$list.html("This note has no ancillaries."); + + return; + } + + for (const ancillary of ancillaries) { + this.$list.append( + $('
    ') + .append( + $('

    ').append($('').text(ancillary.name)) + ) + .append( + $('') + .append( + $('') + .append($('
    ').text('Length:')) + .append($('').text(ancillary.contentLength)) + .append($('').text('MIME:')) + .append($('').text(ancillary.mime)) + .append($('').text('Date modified:')) + .append($('').text(ancillary.utcDateModified)) + ) + ) + .append( + $('
    ')
    +                            .text(ancillary.content)
    +                    )
    +            );
    +        }
    +    }
    +}
    \ No newline at end of file
    diff --git a/src/public/app/widgets/type_widgets/canvas.js b/src/public/app/widgets/type_widgets/canvas.js
    index dbe1eba2e..ac9376c74 100644
    --- a/src/public/app/widgets/type_widgets/canvas.js
    +++ b/src/public/app/widgets/type_widgets/canvas.js
    @@ -277,15 +277,20 @@ export default class ExcalidrawTypeWidget extends TypeWidget {
             })
     
             const content = {
    -            _meta: "This note has type `canvas`. It uses excalidraw and stores an exported svg alongside.",
    -            elements, // excalidraw
    -            appState, // excalidraw
    -            files: activeFiles, // excalidraw
    -            svg: svgString, // not needed for excalidraw, used for note_short, content, and image api
    +            elements,
    +            appState,
    +            files: activeFiles
             };
     
             return {
    -            content: JSON.stringify(content)
    +            content: JSON.stringify(content),
    +            ancillaries: [
    +                {
    +                    name: 'canvasSvg',
    +                    mime: 'image/svg+xml',
    +                    content: svgString
    +                }
    +            ]
             };
         }
     
    diff --git a/src/public/app/widgets/type_widgets/content_widget.js b/src/public/app/widgets/type_widgets/content_widget.js
    index d81fe550a..34577b385 100644
    --- a/src/public/app/widgets/type_widgets/content_widget.js
    +++ b/src/public/app/widgets/type_widgets/content_widget.js
    @@ -28,6 +28,8 @@ import ConsistencyChecksOptions from "./options/advanced/consistency_checks.js";
     import VacuumDatabaseOptions from "./options/advanced/vacuum_database.js";
     import DatabaseAnonymizationOptions from "./options/advanced/database_anonymization.js";
     import BackendLogWidget from "./content/backend_log.js";
    +import OcrOptions from "./options/images/ocr.js";
    +import ExtractTextFromPdfOptions from "./options/images/extract_text_from_pdf.js";
     
     const TPL = `