diff --git a/bin/tpl/anonymize-database.sql b/bin/tpl/anonymize-database.sql index d72e0b29a..cf701e53f 100644 --- a/bin/tpl/anonymize-database.sql +++ b/bin/tpl/anonymize-database.sql @@ -4,6 +4,7 @@ UPDATE notes SET title = 'title' WHERE noteId != 'root' AND noteId NOT LIKE '\_% 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' 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/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/package-lock.json b/package-lock.json index dbd019d3b..87f8406c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@excalidraw/excalidraw": "0.14.2", "archiver": "5.3.1", "async-mutex": "0.4.0", - "axios": "1.3.3", + "axios": "1.3.4", "better-sqlite3": "7.4.5", "chokidar": "3.5.3", "cls-hooked": "4.2.2", @@ -45,7 +45,7 @@ "ini": "3.0.1", "is-animated": "2.0.2", "is-svg": "4.3.2", - "jimp": "0.22.4", + "jimp": "0.22.7", "joplin-turndown-plugin-gfm": "1.0.12", "jsdom": "21.1.0", "mime-types": "2.1.35", @@ -85,7 +85,7 @@ "electron-rebuild": "3.2.9", "esm": "3.2.25", "jasmine": "4.5.0", - "jsdoc": "4.0.1", + "jsdoc": "4.0.2", "lorem-ipsum": "2.0.8", "rcedit": "3.0.1", "webpack": "5.75.0", @@ -96,9 +96,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -386,11 +386,11 @@ "dev": true }, "node_modules/@jimp/bmp": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.4.tgz", - "integrity": "sha512-ZDwQ/tLihpZuTCFGGa0zcyZIWHfhvHkrdbsoHUY0GG/JpH/y2xzlm2I48/TicCpoujN8oGKLHIJje0HmVX3xaA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.7.tgz", + "integrity": "sha512-0cfBPvugURS7G+60vRBL+penDRst8x40alS5Rhn2nlGsgsBHljFDw7+H4o5r6gldw9nv9PR9JA90Wloy7KMZdQ==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "bmp-js": "^0.1.0" }, "peerDependencies": { @@ -398,11 +398,11 @@ } }, "node_modules/@jimp/core": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.4.tgz", - "integrity": "sha512-K7guEYpXV44SCLR35QdPyKqF+mFZaEUAqiSL8qQ/F4N4Ws9JkPzFI/qYTjOkDoKxSWkXlKnlsk1sfMzy0yqA5g==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.7.tgz", + "integrity": "sha512-lg4z+pw23v2Gp9LWQur0NqYtnmoNWnyN/Or96elhJgeEJskrDGwROdajortHCCOI1xDnUZSirg8sFvStC8BIlg==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "any-base": "^1.1.0", "buffer": "^5.2.0", "exif-parser": "^0.1.12", @@ -414,9 +414,9 @@ } }, "node_modules/@jimp/core/node_modules/mkdirp": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", - "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.5.tgz", + "integrity": "sha512-jbjfql+shJtAPrFoKxHOXip4xS+kul9W3OzfzzrqueWK2QMGon2bFH2opl6W9EagBThjEz+iysyi/swOoVfB/w==", "bin": { "mkdirp": "dist/cjs/src/bin.js" }, @@ -428,19 +428,19 @@ } }, "node_modules/@jimp/custom": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.4.tgz", - "integrity": "sha512-k9m/RfxjPjklUsgZ2nszlyNkodUG/4xlxlif70UELhxW8bdqZqqlQGzwA9p+PUiSnlSJYZjL6q+P8cd7yj1ggA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.7.tgz", + "integrity": "sha512-n+1+ZVDNumB1E+sL7KdGKAJ6MbgniX1/v/xOEFEQ46WDZ4cRTqP4+tXjHTuHSlOXiANH+K9zD6qgzqmgO6mCVw==", "dependencies": { - "@jimp/core": "^0.22.4" + "@jimp/core": "^0.22.7" } }, "node_modules/@jimp/gif": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.4.tgz", - "integrity": "sha512-KmN7GoaQTzLAX4JXLBRkIiZAXthgQdKe+Y7BOw4n6CMe6LAS/XCQqrYCG3Av/GqIO7UAKems6D7kIGAUuhpNlQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.7.tgz", + "integrity": "sha512-PGZMS8sYFnDcqg+t8IT3RaSJLrqB+3GzhI0hU5D4mmSuJ5UO/6Bdgu8nrwh3uFPxw0ZH6h9ozYk88cz0pKEhLQ==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "gifwrap": "^0.9.2", "omggif": "^1.0.9" }, @@ -449,11 +449,11 @@ } }, "node_modules/@jimp/jpeg": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.4.tgz", - "integrity": "sha512-mMJNhEtJpne65mxpIXEvT0VIzmsKiZWmaFT/c2eQ2tBLEtWAFpkvoP+F7jEaU+F3Ur4fXKFkJ/xOSXtRr/gGNw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.7.tgz", + "integrity": "sha512-ptwWyX/7RPcREy8SpPN/8IlywbwyPXiuXmoHwM6m4iKcyaCmmnfCdZwLNXYliJzFAFLLOWDuOrwO3cZSkH6Czg==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "jpeg-js": "^0.4.4" }, "peerDependencies": { @@ -461,44 +461,44 @@ } }, "node_modules/@jimp/plugin-blit": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.4.tgz", - "integrity": "sha512-QQHe+rFarsxJQxWKlyHEMfLyXmUG9AiQky+8WfwjZVBYilIFyiBywOc3sThonOsru+7LOSUDmbN6mvbFk4R+gw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.7.tgz", + "integrity": "sha512-8oXcBTSd/sBmTQATrCxQ1ZBER31Lge8vXzWqNCbC3b1ZvRggCcqnDzRRH1+JiI4i+jPRo3Fi6/sdvEUyQ5LY3g==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-blur": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.4.tgz", - "integrity": "sha512-p57Ac5LEQckIogiwf7qyOojGvLOD08eMaQd5ylOhet/fbdwAzD/8flWFhSIKsdAVzvnfGcszuLtrsV07jDutTw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.7.tgz", + "integrity": "sha512-M+0I5CKFIpnIQE27j8o8NECBsOFBd4z7C95ydy2UohYopugFq+hSVtMs1D4pQgb0RW1DJPiXD/4PHqb+lzV5mA==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-circle": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.4.tgz", - "integrity": "sha512-T+TpG+s+wM9kKHlpIEfCAfOM+QrYVqcMoWjkULddc0KtaDEhqgGYFhN+/SlzJfDbZKw0xUgIuAw89sXuzMIUjw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.7.tgz", + "integrity": "sha512-zfZKKpOhlyiDeFjGW5JB9K4h/kvbdaAJWUEwmKrvvGar67G3j8dKu46AX0MeWRNZ1yk/lfz+JIa7TzKfxEBf6w==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-color": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.4.tgz", - "integrity": "sha512-TZqcqepoCcIlF7VodPPfS3WET+LL5Y/XnXOBk4tWnG5i+lhNrs7/U0HOJY6Iw9o4g267DddnlfKWmunvzBcvOQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.7.tgz", + "integrity": "sha512-OXro9pdB0twQjV4LgW0bTEXaX1VgBsTBcFoDAs8q9mtQzD5p3UQmJ+ykCiQ5rTPxNN1Buc44tcCIfp8haB1ZVQ==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "tinycolor2": "^1.6.0" }, "peerDependencies": { @@ -506,11 +506,11 @@ } }, "node_modules/@jimp/plugin-contain": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.4.tgz", - "integrity": "sha512-Hl+TO4v+EpRfEl3R6k/bEgOGOpm6JqNfEIyCFWLi6yqJQjMGzBQ0vt+VHe2u3WIFaFrDWsGxeuFZBDzgtjTwxw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.7.tgz", + "integrity": "sha512-GwUxZp4jMA0O0qbknUPDONJAfHFaTRs8kK+jgRtUfgb1Xi96l5RN/PMMDv4owZCUiPVAON80X1BMj7nSQWNVUw==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -520,11 +520,11 @@ } }, "node_modules/@jimp/plugin-cover": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.4.tgz", - "integrity": "sha512-KMTQjN/B7r/RNzoLFwnhqhLrgT0kMqTkBMEZQSopj5vPLPNjIX0ElEYC8AIVFKeZAV+1mYkyss+IDdxq4fyRng==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.7.tgz", + "integrity": "sha512-PVXeQyofGepMoJaQ5XapLwCcZfsOF1IoAotHosh8AOP8niCP/Erm8T6ZWf5tf0sMJiLHQMPUyns186H5isqEMQ==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -534,55 +534,55 @@ } }, "node_modules/@jimp/plugin-crop": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.4.tgz", - "integrity": "sha512-8krDt7xzBa1fbtlYCzEMZIgNjTkhgywho0FJpgIMkIUMjaZITS1Ea/Veb3UrWt8EsgQS6hxjGVE/Q1FvP5iPLA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.7.tgz", + "integrity": "sha512-XXvUU+hPdodtTBSgyUJUnzh7JgKMVlS1GxjcQsjYU8iGr1dbpuazKMTQxc76ChVmy8ue4goi8bGstacWUHpl/Q==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-displace": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.4.tgz", - "integrity": "sha512-3gBfwYVFrOjp8SUpb7H0UMgqvsG/sxY1PVBIfRW9MUCosiH1eE/Mo5cbxhQ6/w5f3sh23lBmG8W0WuSrnXLorg==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.7.tgz", + "integrity": "sha512-CCNAkmm2OS4QQtNRfQvXqoAMxNE0maSlVEV5DNdioHOUKycy02EJ5hNYR3l0FG+NraQHOuqv9XV37sGRl6QzMA==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-dither": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.4.tgz", - "integrity": "sha512-oOhdZBDJpSGIoTUhPOIvLIVUwILRWgrWdA4Vbzcyz2RHvaPHS8gdBH0EdIPbJ5agNyFnY8sJWFM7YKx/rLNKsw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.7.tgz", + "integrity": "sha512-ndCW5MIGMdh3aBvvgRCO7el9cIPG29kU7xQYlOs5+3JsDk3Vf7X30QGPjzxABOY95qLUNUjf5Qe/p/tqv/vbcw==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-fisheye": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.4.tgz", - "integrity": "sha512-2myNZyDrwUOV8MKd4NeULnEOojYF7XRbnRHiUPsNptpmK6g/gI4xt+5k7BallAYZD8ZLfZVjstUogsObprHd/Q==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.7.tgz", + "integrity": "sha512-boI1QowhZRfb6OF+ZPWtiSJP1GATsTHjd5Oy/lJ+n0L4rp439ZOTB1Elzcgc44O2C1mgZDdybRPQQvYdPF8slA==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-flip": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.4.tgz", - "integrity": "sha512-9FZ0k5N5leLDefeDjizXXTl17dzo23PYtCD/T4xeSVr96d1pQDwbeIk7pEhhHr1rl98tJe0U/OV2dFXFYauKPw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.7.tgz", + "integrity": "sha512-/jkbgtvQPcKadAEV5ZXyoEpSdd7GEvGs/Ya/f48+LNszc+S24u4UXtuP3QPRJ5FHm0Re1t4uztM7xa6IPklAOA==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -590,55 +590,55 @@ } }, "node_modules/@jimp/plugin-gaussian": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.4.tgz", - "integrity": "sha512-irOSwLdZ9kTq5Wd5dpkMgIMJVwemYcqgnzd04+P6TJGYmem2HR6JUCDpjbET3Fpbo/snFLm4mZ+2A+SmeCGjKA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.7.tgz", + "integrity": "sha512-OB1sdnjzq2rfUHmx9Rvi3SJIDbQAgWFgYEw6KhN3TSVOdrJHvwrQkEnwR9PoUzQg992VIpGcVc9Y1s/SOU2oCA==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-invert": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.4.tgz", - "integrity": "sha512-/WtZeLrF+H+mzbjqudeGvvSxudlHy1kyiP1gVWDxhYNQOuZJI57Vn20kSTYvHBNjvy31LV4/uestyX8j8tE2Qg==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.7.tgz", + "integrity": "sha512-dX/TqACJ/M5uXDIEJlVPPwietMD6EWUeA/CV4uvhLz9EMjTgHociJ3TWqGCY/70phhIBLbhLcHUVBL/q65ynfQ==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-mask": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.4.tgz", - "integrity": "sha512-U0SrOwBNKkMYTNPTz5CXeJdZ4c5easFlq2B9Txy0kPsav2OraTv8cZjpMxrWUejo/AQGVUDbaGtXMm9pE13/6w==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.7.tgz", + "integrity": "sha512-rfKHKJLAtJG7qbB4zYAMcQ9ue3CIFRuAJ3xX0lzCxC0fGvCVuXlcxiAEauBxqaTWqiKMnahqpR3/Ah679K2FKQ==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-normalize": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.4.tgz", - "integrity": "sha512-XJiPBJGCHWmIzUdmL4mWP1Ev5LMp77oMmPXdgQGDty1cxfyo3CbkTjZSsnwF/XLlrQ1yfLW+8JB+ihGKcVEOxA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.7.tgz", + "integrity": "sha512-t8x2jjKDmvUAZB4Wbeagr4D0BvoVCIWquy94mpglvSZ8ujKLt0aQBl3CBEIbXFAoVqNif+G36NtxPHNsjxIXOg==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-print": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.4.tgz", - "integrity": "sha512-mayiPhg6c7KYjvq3fYOW9ohhXD1eWdEiseV9dAWqTOEbDbohT8S6eTGhVIiVa2sVySLcpNEKZSk07c5EhJAMcw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.7.tgz", + "integrity": "sha512-kx0+cPeinki1IFg9cJy7LC4uVuOEOa8TIrcERioB6PVgJ7EDzCAfatTKULZ+t4uSs2K/lQF97wPYlbiyxs/Hzg==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "load-bmfont": "^1.4.1" }, "peerDependencies": { @@ -647,22 +647,22 @@ } }, "node_modules/@jimp/plugin-resize": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.4.tgz", - "integrity": "sha512-2wMdpPNGf6Zo2lfJg1QHHQ+ds5baQH75IcFpdjw717dcEISpn1jPG//iClXOGh16OJsRQlwHESaZTgEo/5Dw/g==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.7.tgz", + "integrity": "sha512-pg7i0JIYt7x7ag+CoD/yG70Xvwm1sKRfcFjQh954yestiin14uppPgXchAmTBmctecBjLNdsVlqSXbPvU4Jvxw==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, "node_modules/@jimp/plugin-rotate": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.4.tgz", - "integrity": "sha512-g08LBsPENbeA6NVoeq0iuDgAL89+N+aZrvYVKYkiJZIM7vUvueJyAIq4+bjDl4r54OR8XBFX0GsrKsqrULh1eA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.7.tgz", + "integrity": "sha512-Uh3Gb18IY8uXWk6E1bzMopum2GP+xwohbnMIDE0MSWmLaz7LXrfnvgXFba1uRGgn73CJz8UDS4fC1KIJMuxQZA==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -672,11 +672,11 @@ } }, "node_modules/@jimp/plugin-scale": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.4.tgz", - "integrity": "sha512-cJiLQtTcNk6/+j05R23TFGXy+smDV0BdlmzJVDb+7Ye9qcmWpkdjVSioQQqZr0QScIYKhhRCY/lFTepBx67yzw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.7.tgz", + "integrity": "sha512-3uHUrk5Rl6MCxuoJtHTSeJjSHIxHWqOOgmD2caKIvyxds0Zmofu/Fva+N4V/m80E4q4G2RXNsUplFpFGhUM7hw==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -684,11 +684,11 @@ } }, "node_modules/@jimp/plugin-shadow": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.4.tgz", - "integrity": "sha512-a5hdpzGBzBo91DNiKaGvs8iJbs2bYQmDRm/BrCh4NET+h5l5AwXNu/Ak0bWRhN16YQ55XYNGHer2jOwBPrf2WQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.7.tgz", + "integrity": "sha512-NKEq5VR8U/d0OKf0hxFtrrbMCuNv7by31V+Kwgxb1oTP+j+zZEaww+m3YgEwIwRe7E8/yeDSHa5bJ+CmuyFZjw==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -697,11 +697,11 @@ } }, "node_modules/@jimp/plugin-threshold": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.4.tgz", - "integrity": "sha512-jTT/+p2zb2NESzd7O0bVRowiQszoaHeBf2OgP7lFde10fHd+fn78m5brUmSmlGAdlMRwm8S8ZcxTj5ZjdQns5w==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.7.tgz", + "integrity": "sha512-BH4aLwfmnqjRVhdzMIqUns4ycZ6QoHHFR6Qz+X2iSpH5a33xFA4DRbd3Ehtrs4Gk7XiCjWkUyM6wjmH7l/1hNQ==", "dependencies": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" }, "peerDependencies": { "@jimp/custom": ">=0.3.5", @@ -710,31 +710,31 @@ } }, "node_modules/@jimp/plugins": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.4.tgz", - "integrity": "sha512-yAxcA4UR3Bs7j73I7wt4ty52vm5MzPmr+8DYk8jrS/ng2Z2iuXzbcTe4mf9eEqXYVah3rTIggo4dPjW75DRZtA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.7.tgz", + "integrity": "sha512-AJmzTG/sa+CDpvle/UE89hjHR85gnRGSwLuQqPbhlY6GFCmC3uqHRJz9O5I8A4zdi9+e8LsBphuTlKV7RbuXOw==", "dependencies": { - "@jimp/plugin-blit": "^0.22.4", - "@jimp/plugin-blur": "^0.22.4", - "@jimp/plugin-circle": "^0.22.4", - "@jimp/plugin-color": "^0.22.4", - "@jimp/plugin-contain": "^0.22.4", - "@jimp/plugin-cover": "^0.22.4", - "@jimp/plugin-crop": "^0.22.4", - "@jimp/plugin-displace": "^0.22.4", - "@jimp/plugin-dither": "^0.22.4", - "@jimp/plugin-fisheye": "^0.22.4", - "@jimp/plugin-flip": "^0.22.4", - "@jimp/plugin-gaussian": "^0.22.4", - "@jimp/plugin-invert": "^0.22.4", - "@jimp/plugin-mask": "^0.22.4", - "@jimp/plugin-normalize": "^0.22.4", - "@jimp/plugin-print": "^0.22.4", - "@jimp/plugin-resize": "^0.22.4", - "@jimp/plugin-rotate": "^0.22.4", - "@jimp/plugin-scale": "^0.22.4", - "@jimp/plugin-shadow": "^0.22.4", - "@jimp/plugin-threshold": "^0.22.4", + "@jimp/plugin-blit": "^0.22.7", + "@jimp/plugin-blur": "^0.22.7", + "@jimp/plugin-circle": "^0.22.7", + "@jimp/plugin-color": "^0.22.7", + "@jimp/plugin-contain": "^0.22.7", + "@jimp/plugin-cover": "^0.22.7", + "@jimp/plugin-crop": "^0.22.7", + "@jimp/plugin-displace": "^0.22.7", + "@jimp/plugin-dither": "^0.22.7", + "@jimp/plugin-fisheye": "^0.22.7", + "@jimp/plugin-flip": "^0.22.7", + "@jimp/plugin-gaussian": "^0.22.7", + "@jimp/plugin-invert": "^0.22.7", + "@jimp/plugin-mask": "^0.22.7", + "@jimp/plugin-normalize": "^0.22.7", + "@jimp/plugin-print": "^0.22.7", + "@jimp/plugin-resize": "^0.22.7", + "@jimp/plugin-rotate": "^0.22.7", + "@jimp/plugin-scale": "^0.22.7", + "@jimp/plugin-shadow": "^0.22.7", + "@jimp/plugin-threshold": "^0.22.7", "timm": "^1.6.1" }, "peerDependencies": { @@ -742,11 +742,11 @@ } }, "node_modules/@jimp/png": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.4.tgz", - "integrity": "sha512-kDovx9dTyV/TSR40HQHdRyVgNNb7Cny4/0PPEa+xeR7snuDC3dV5hu9s/QJwY0RMGiAkiuKDpiaBuSZuz8dwRQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.7.tgz", + "integrity": "sha512-LxD3O9FKEwVv+j+HcUV7ez72Miy+823EjhtFZbBYXNp9qjHtHFBpgcSJBftUOCei8OlmmVgULYn9XjyfPsDgGw==", "dependencies": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "pngjs": "^6.0.0" }, "peerDependencies": { @@ -754,9 +754,9 @@ } }, "node_modules/@jimp/tiff": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.4.tgz", - "integrity": "sha512-RStUATRnb+unYzzuGxU+SPZALqh5NxYdcS6UGTBvhCMlijopGiY/iL01wstIOst0ypKIjwbcSVj7mAHn6B7Qbw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.7.tgz", + "integrity": "sha512-/oE8kLumzBfU1Z6h4TrDXYCGQNc4CjbZQvPssjImEqNLr5vbefpIpoy1fVMpsyuHZHsGovsBhBHxTJaRLO4+Og==", "dependencies": { "utif2": "^4.0.1" }, @@ -765,15 +765,15 @@ } }, "node_modules/@jimp/types": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.4.tgz", - "integrity": "sha512-v3hm8LGc3we6P6ML0ticiLX7wtdvywrKthYxqVrJVIu3vRL0Z4q3ngFjwzqDmaIF8wC0neq98s/t7ODWfeIiRQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.7.tgz", + "integrity": "sha512-1T8BxwDh5HJvBh3tt6HUd8r7ir5Ge3JWATXC8O3Y9QYwOaERjA2+FVhGSjtoo5xCeJvLRjSzEtfZ8heowMBL4w==", "dependencies": { - "@jimp/bmp": "^0.22.4", - "@jimp/gif": "^0.22.4", - "@jimp/jpeg": "^0.22.4", - "@jimp/png": "^0.22.4", - "@jimp/tiff": "^0.22.4", + "@jimp/bmp": "^0.22.7", + "@jimp/gif": "^0.22.7", + "@jimp/jpeg": "^0.22.7", + "@jimp/png": "^0.22.7", + "@jimp/tiff": "^0.22.7", "timm": "^1.6.1" }, "peerDependencies": { @@ -781,9 +781,9 @@ } }, "node_modules/@jimp/utils": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.4.tgz", - "integrity": "sha512-EPaBMNg4NvVXnMpSFJEsdCQqdSVU2ACreAL+Ipkq19C/FkDEj9Q10t6Mjx8zOe/AAjBQj1vTALS/DykcHOn4bQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.7.tgz", + "integrity": "sha512-4ax4IOWLIERx4yz9y3fNXKvQaPOY23yJF5h4sizxVkQUObkZHWE0kL0TVHodBt3rS8ksdbCL8Jkz4GeNP/Katg==", "dependencies": { "regenerator-runtime": "^0.13.3" } @@ -1918,9 +1918,9 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "node_modules/axios": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz", - "integrity": "sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -6331,13 +6331,13 @@ } }, "node_modules/jimp": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.4.tgz", - "integrity": "sha512-reGESbcYp38VlGtdAe8qrmbjLLEYXMrQWc2XXb7+czulKfCCidUHEpNfrS3hx5XXMWrAmoYKkxPTqCvll6Q6ug==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.7.tgz", + "integrity": "sha512-TJCTJ4ZcFUw6W8XZnR6ajdEu8vSyPi3AuoChs+zLHalXnhAPZgwkzwcXnxey4LNjh1p9dfIUkg8YSQ+q8pBW0A==", "dependencies": { - "@jimp/custom": "^0.22.4", - "@jimp/plugins": "^0.22.4", - "@jimp/types": "^0.22.4", + "@jimp/custom": "^0.22.7", + "@jimp/plugins": "^0.22.7", + "@jimp/types": "^0.22.7", "regenerator-runtime": "^0.13.3" } }, @@ -6383,12 +6383,12 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "node_modules/jsdoc": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.1.tgz", - "integrity": "sha512-UjvSrLYb270Mq25RN4AGGg2uqKRV90nCqkGsI4gD3RIR1lgMN8nWxK/am8Rsj33tWyprzZdA+0q1qY07m0Ar7w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", "dev": true, "dependencies": { - "@babel/parser": "^7.9.4", + "@babel/parser": "^7.20.15", "@jsdoc/salty": "^0.2.1", "@types/markdown-it": "^12.2.3", "bluebird": "^3.7.2", @@ -8470,9 +8470,9 @@ } }, "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", + "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -10615,9 +10615,9 @@ }, "dependencies": { "@babel/parser": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz", - "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", "dev": true }, "@braintree/sanitize-url": { @@ -10836,20 +10836,20 @@ "dev": true }, "@jimp/bmp": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.4.tgz", - "integrity": "sha512-ZDwQ/tLihpZuTCFGGa0zcyZIWHfhvHkrdbsoHUY0GG/JpH/y2xzlm2I48/TicCpoujN8oGKLHIJje0HmVX3xaA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.7.tgz", + "integrity": "sha512-0cfBPvugURS7G+60vRBL+penDRst8x40alS5Rhn2nlGsgsBHljFDw7+H4o5r6gldw9nv9PR9JA90Wloy7KMZdQ==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "bmp-js": "^0.1.0" } }, "@jimp/core": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.4.tgz", - "integrity": "sha512-K7guEYpXV44SCLR35QdPyKqF+mFZaEUAqiSL8qQ/F4N4Ws9JkPzFI/qYTjOkDoKxSWkXlKnlsk1sfMzy0yqA5g==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.7.tgz", + "integrity": "sha512-lg4z+pw23v2Gp9LWQur0NqYtnmoNWnyN/Or96elhJgeEJskrDGwROdajortHCCOI1xDnUZSirg8sFvStC8BIlg==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "any-base": "^1.1.0", "buffer": "^5.2.0", "exif-parser": "^0.1.12", @@ -10861,272 +10861,272 @@ }, "dependencies": { "mkdirp": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", - "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==" + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.5.tgz", + "integrity": "sha512-jbjfql+shJtAPrFoKxHOXip4xS+kul9W3OzfzzrqueWK2QMGon2bFH2opl6W9EagBThjEz+iysyi/swOoVfB/w==" } } }, "@jimp/custom": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.4.tgz", - "integrity": "sha512-k9m/RfxjPjklUsgZ2nszlyNkodUG/4xlxlif70UELhxW8bdqZqqlQGzwA9p+PUiSnlSJYZjL6q+P8cd7yj1ggA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.7.tgz", + "integrity": "sha512-n+1+ZVDNumB1E+sL7KdGKAJ6MbgniX1/v/xOEFEQ46WDZ4cRTqP4+tXjHTuHSlOXiANH+K9zD6qgzqmgO6mCVw==", "requires": { - "@jimp/core": "^0.22.4" + "@jimp/core": "^0.22.7" } }, "@jimp/gif": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.4.tgz", - "integrity": "sha512-KmN7GoaQTzLAX4JXLBRkIiZAXthgQdKe+Y7BOw4n6CMe6LAS/XCQqrYCG3Av/GqIO7UAKems6D7kIGAUuhpNlQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.7.tgz", + "integrity": "sha512-PGZMS8sYFnDcqg+t8IT3RaSJLrqB+3GzhI0hU5D4mmSuJ5UO/6Bdgu8nrwh3uFPxw0ZH6h9ozYk88cz0pKEhLQ==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "gifwrap": "^0.9.2", "omggif": "^1.0.9" } }, "@jimp/jpeg": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.4.tgz", - "integrity": "sha512-mMJNhEtJpne65mxpIXEvT0VIzmsKiZWmaFT/c2eQ2tBLEtWAFpkvoP+F7jEaU+F3Ur4fXKFkJ/xOSXtRr/gGNw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.7.tgz", + "integrity": "sha512-ptwWyX/7RPcREy8SpPN/8IlywbwyPXiuXmoHwM6m4iKcyaCmmnfCdZwLNXYliJzFAFLLOWDuOrwO3cZSkH6Czg==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "jpeg-js": "^0.4.4" } }, "@jimp/plugin-blit": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.4.tgz", - "integrity": "sha512-QQHe+rFarsxJQxWKlyHEMfLyXmUG9AiQky+8WfwjZVBYilIFyiBywOc3sThonOsru+7LOSUDmbN6mvbFk4R+gw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.7.tgz", + "integrity": "sha512-8oXcBTSd/sBmTQATrCxQ1ZBER31Lge8vXzWqNCbC3b1ZvRggCcqnDzRRH1+JiI4i+jPRo3Fi6/sdvEUyQ5LY3g==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-blur": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.4.tgz", - "integrity": "sha512-p57Ac5LEQckIogiwf7qyOojGvLOD08eMaQd5ylOhet/fbdwAzD/8flWFhSIKsdAVzvnfGcszuLtrsV07jDutTw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.7.tgz", + "integrity": "sha512-M+0I5CKFIpnIQE27j8o8NECBsOFBd4z7C95ydy2UohYopugFq+hSVtMs1D4pQgb0RW1DJPiXD/4PHqb+lzV5mA==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-circle": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.4.tgz", - "integrity": "sha512-T+TpG+s+wM9kKHlpIEfCAfOM+QrYVqcMoWjkULddc0KtaDEhqgGYFhN+/SlzJfDbZKw0xUgIuAw89sXuzMIUjw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.7.tgz", + "integrity": "sha512-zfZKKpOhlyiDeFjGW5JB9K4h/kvbdaAJWUEwmKrvvGar67G3j8dKu46AX0MeWRNZ1yk/lfz+JIa7TzKfxEBf6w==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-color": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.4.tgz", - "integrity": "sha512-TZqcqepoCcIlF7VodPPfS3WET+LL5Y/XnXOBk4tWnG5i+lhNrs7/U0HOJY6Iw9o4g267DddnlfKWmunvzBcvOQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.7.tgz", + "integrity": "sha512-OXro9pdB0twQjV4LgW0bTEXaX1VgBsTBcFoDAs8q9mtQzD5p3UQmJ+ykCiQ5rTPxNN1Buc44tcCIfp8haB1ZVQ==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "tinycolor2": "^1.6.0" } }, "@jimp/plugin-contain": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.4.tgz", - "integrity": "sha512-Hl+TO4v+EpRfEl3R6k/bEgOGOpm6JqNfEIyCFWLi6yqJQjMGzBQ0vt+VHe2u3WIFaFrDWsGxeuFZBDzgtjTwxw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.7.tgz", + "integrity": "sha512-GwUxZp4jMA0O0qbknUPDONJAfHFaTRs8kK+jgRtUfgb1Xi96l5RN/PMMDv4owZCUiPVAON80X1BMj7nSQWNVUw==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-cover": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.4.tgz", - "integrity": "sha512-KMTQjN/B7r/RNzoLFwnhqhLrgT0kMqTkBMEZQSopj5vPLPNjIX0ElEYC8AIVFKeZAV+1mYkyss+IDdxq4fyRng==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.7.tgz", + "integrity": "sha512-PVXeQyofGepMoJaQ5XapLwCcZfsOF1IoAotHosh8AOP8niCP/Erm8T6ZWf5tf0sMJiLHQMPUyns186H5isqEMQ==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-crop": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.4.tgz", - "integrity": "sha512-8krDt7xzBa1fbtlYCzEMZIgNjTkhgywho0FJpgIMkIUMjaZITS1Ea/Veb3UrWt8EsgQS6hxjGVE/Q1FvP5iPLA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.7.tgz", + "integrity": "sha512-XXvUU+hPdodtTBSgyUJUnzh7JgKMVlS1GxjcQsjYU8iGr1dbpuazKMTQxc76ChVmy8ue4goi8bGstacWUHpl/Q==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-displace": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.4.tgz", - "integrity": "sha512-3gBfwYVFrOjp8SUpb7H0UMgqvsG/sxY1PVBIfRW9MUCosiH1eE/Mo5cbxhQ6/w5f3sh23lBmG8W0WuSrnXLorg==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.7.tgz", + "integrity": "sha512-CCNAkmm2OS4QQtNRfQvXqoAMxNE0maSlVEV5DNdioHOUKycy02EJ5hNYR3l0FG+NraQHOuqv9XV37sGRl6QzMA==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-dither": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.4.tgz", - "integrity": "sha512-oOhdZBDJpSGIoTUhPOIvLIVUwILRWgrWdA4Vbzcyz2RHvaPHS8gdBH0EdIPbJ5agNyFnY8sJWFM7YKx/rLNKsw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.7.tgz", + "integrity": "sha512-ndCW5MIGMdh3aBvvgRCO7el9cIPG29kU7xQYlOs5+3JsDk3Vf7X30QGPjzxABOY95qLUNUjf5Qe/p/tqv/vbcw==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-fisheye": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.4.tgz", - "integrity": "sha512-2myNZyDrwUOV8MKd4NeULnEOojYF7XRbnRHiUPsNptpmK6g/gI4xt+5k7BallAYZD8ZLfZVjstUogsObprHd/Q==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.7.tgz", + "integrity": "sha512-boI1QowhZRfb6OF+ZPWtiSJP1GATsTHjd5Oy/lJ+n0L4rp439ZOTB1Elzcgc44O2C1mgZDdybRPQQvYdPF8slA==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-flip": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.4.tgz", - "integrity": "sha512-9FZ0k5N5leLDefeDjizXXTl17dzo23PYtCD/T4xeSVr96d1pQDwbeIk7pEhhHr1rl98tJe0U/OV2dFXFYauKPw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.7.tgz", + "integrity": "sha512-/jkbgtvQPcKadAEV5ZXyoEpSdd7GEvGs/Ya/f48+LNszc+S24u4UXtuP3QPRJ5FHm0Re1t4uztM7xa6IPklAOA==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-gaussian": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.4.tgz", - "integrity": "sha512-irOSwLdZ9kTq5Wd5dpkMgIMJVwemYcqgnzd04+P6TJGYmem2HR6JUCDpjbET3Fpbo/snFLm4mZ+2A+SmeCGjKA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.7.tgz", + "integrity": "sha512-OB1sdnjzq2rfUHmx9Rvi3SJIDbQAgWFgYEw6KhN3TSVOdrJHvwrQkEnwR9PoUzQg992VIpGcVc9Y1s/SOU2oCA==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-invert": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.4.tgz", - "integrity": "sha512-/WtZeLrF+H+mzbjqudeGvvSxudlHy1kyiP1gVWDxhYNQOuZJI57Vn20kSTYvHBNjvy31LV4/uestyX8j8tE2Qg==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.7.tgz", + "integrity": "sha512-dX/TqACJ/M5uXDIEJlVPPwietMD6EWUeA/CV4uvhLz9EMjTgHociJ3TWqGCY/70phhIBLbhLcHUVBL/q65ynfQ==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-mask": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.4.tgz", - "integrity": "sha512-U0SrOwBNKkMYTNPTz5CXeJdZ4c5easFlq2B9Txy0kPsav2OraTv8cZjpMxrWUejo/AQGVUDbaGtXMm9pE13/6w==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.7.tgz", + "integrity": "sha512-rfKHKJLAtJG7qbB4zYAMcQ9ue3CIFRuAJ3xX0lzCxC0fGvCVuXlcxiAEauBxqaTWqiKMnahqpR3/Ah679K2FKQ==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-normalize": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.4.tgz", - "integrity": "sha512-XJiPBJGCHWmIzUdmL4mWP1Ev5LMp77oMmPXdgQGDty1cxfyo3CbkTjZSsnwF/XLlrQ1yfLW+8JB+ihGKcVEOxA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.7.tgz", + "integrity": "sha512-t8x2jjKDmvUAZB4Wbeagr4D0BvoVCIWquy94mpglvSZ8ujKLt0aQBl3CBEIbXFAoVqNif+G36NtxPHNsjxIXOg==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-print": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.4.tgz", - "integrity": "sha512-mayiPhg6c7KYjvq3fYOW9ohhXD1eWdEiseV9dAWqTOEbDbohT8S6eTGhVIiVa2sVySLcpNEKZSk07c5EhJAMcw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.7.tgz", + "integrity": "sha512-kx0+cPeinki1IFg9cJy7LC4uVuOEOa8TIrcERioB6PVgJ7EDzCAfatTKULZ+t4uSs2K/lQF97wPYlbiyxs/Hzg==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "load-bmfont": "^1.4.1" } }, "@jimp/plugin-resize": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.4.tgz", - "integrity": "sha512-2wMdpPNGf6Zo2lfJg1QHHQ+ds5baQH75IcFpdjw717dcEISpn1jPG//iClXOGh16OJsRQlwHESaZTgEo/5Dw/g==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.7.tgz", + "integrity": "sha512-pg7i0JIYt7x7ag+CoD/yG70Xvwm1sKRfcFjQh954yestiin14uppPgXchAmTBmctecBjLNdsVlqSXbPvU4Jvxw==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-rotate": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.4.tgz", - "integrity": "sha512-g08LBsPENbeA6NVoeq0iuDgAL89+N+aZrvYVKYkiJZIM7vUvueJyAIq4+bjDl4r54OR8XBFX0GsrKsqrULh1eA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.7.tgz", + "integrity": "sha512-Uh3Gb18IY8uXWk6E1bzMopum2GP+xwohbnMIDE0MSWmLaz7LXrfnvgXFba1uRGgn73CJz8UDS4fC1KIJMuxQZA==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-scale": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.4.tgz", - "integrity": "sha512-cJiLQtTcNk6/+j05R23TFGXy+smDV0BdlmzJVDb+7Ye9qcmWpkdjVSioQQqZr0QScIYKhhRCY/lFTepBx67yzw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.7.tgz", + "integrity": "sha512-3uHUrk5Rl6MCxuoJtHTSeJjSHIxHWqOOgmD2caKIvyxds0Zmofu/Fva+N4V/m80E4q4G2RXNsUplFpFGhUM7hw==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-shadow": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.4.tgz", - "integrity": "sha512-a5hdpzGBzBo91DNiKaGvs8iJbs2bYQmDRm/BrCh4NET+h5l5AwXNu/Ak0bWRhN16YQ55XYNGHer2jOwBPrf2WQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.7.tgz", + "integrity": "sha512-NKEq5VR8U/d0OKf0hxFtrrbMCuNv7by31V+Kwgxb1oTP+j+zZEaww+m3YgEwIwRe7E8/yeDSHa5bJ+CmuyFZjw==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugin-threshold": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.4.tgz", - "integrity": "sha512-jTT/+p2zb2NESzd7O0bVRowiQszoaHeBf2OgP7lFde10fHd+fn78m5brUmSmlGAdlMRwm8S8ZcxTj5ZjdQns5w==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.7.tgz", + "integrity": "sha512-BH4aLwfmnqjRVhdzMIqUns4ycZ6QoHHFR6Qz+X2iSpH5a33xFA4DRbd3Ehtrs4Gk7XiCjWkUyM6wjmH7l/1hNQ==", "requires": { - "@jimp/utils": "^0.22.4" + "@jimp/utils": "^0.22.7" } }, "@jimp/plugins": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.4.tgz", - "integrity": "sha512-yAxcA4UR3Bs7j73I7wt4ty52vm5MzPmr+8DYk8jrS/ng2Z2iuXzbcTe4mf9eEqXYVah3rTIggo4dPjW75DRZtA==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.7.tgz", + "integrity": "sha512-AJmzTG/sa+CDpvle/UE89hjHR85gnRGSwLuQqPbhlY6GFCmC3uqHRJz9O5I8A4zdi9+e8LsBphuTlKV7RbuXOw==", "requires": { - "@jimp/plugin-blit": "^0.22.4", - "@jimp/plugin-blur": "^0.22.4", - "@jimp/plugin-circle": "^0.22.4", - "@jimp/plugin-color": "^0.22.4", - "@jimp/plugin-contain": "^0.22.4", - "@jimp/plugin-cover": "^0.22.4", - "@jimp/plugin-crop": "^0.22.4", - "@jimp/plugin-displace": "^0.22.4", - "@jimp/plugin-dither": "^0.22.4", - "@jimp/plugin-fisheye": "^0.22.4", - "@jimp/plugin-flip": "^0.22.4", - "@jimp/plugin-gaussian": "^0.22.4", - "@jimp/plugin-invert": "^0.22.4", - "@jimp/plugin-mask": "^0.22.4", - "@jimp/plugin-normalize": "^0.22.4", - "@jimp/plugin-print": "^0.22.4", - "@jimp/plugin-resize": "^0.22.4", - "@jimp/plugin-rotate": "^0.22.4", - "@jimp/plugin-scale": "^0.22.4", - "@jimp/plugin-shadow": "^0.22.4", - "@jimp/plugin-threshold": "^0.22.4", + "@jimp/plugin-blit": "^0.22.7", + "@jimp/plugin-blur": "^0.22.7", + "@jimp/plugin-circle": "^0.22.7", + "@jimp/plugin-color": "^0.22.7", + "@jimp/plugin-contain": "^0.22.7", + "@jimp/plugin-cover": "^0.22.7", + "@jimp/plugin-crop": "^0.22.7", + "@jimp/plugin-displace": "^0.22.7", + "@jimp/plugin-dither": "^0.22.7", + "@jimp/plugin-fisheye": "^0.22.7", + "@jimp/plugin-flip": "^0.22.7", + "@jimp/plugin-gaussian": "^0.22.7", + "@jimp/plugin-invert": "^0.22.7", + "@jimp/plugin-mask": "^0.22.7", + "@jimp/plugin-normalize": "^0.22.7", + "@jimp/plugin-print": "^0.22.7", + "@jimp/plugin-resize": "^0.22.7", + "@jimp/plugin-rotate": "^0.22.7", + "@jimp/plugin-scale": "^0.22.7", + "@jimp/plugin-shadow": "^0.22.7", + "@jimp/plugin-threshold": "^0.22.7", "timm": "^1.6.1" } }, "@jimp/png": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.4.tgz", - "integrity": "sha512-kDovx9dTyV/TSR40HQHdRyVgNNb7Cny4/0PPEa+xeR7snuDC3dV5hu9s/QJwY0RMGiAkiuKDpiaBuSZuz8dwRQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.7.tgz", + "integrity": "sha512-LxD3O9FKEwVv+j+HcUV7ez72Miy+823EjhtFZbBYXNp9qjHtHFBpgcSJBftUOCei8OlmmVgULYn9XjyfPsDgGw==", "requires": { - "@jimp/utils": "^0.22.4", + "@jimp/utils": "^0.22.7", "pngjs": "^6.0.0" } }, "@jimp/tiff": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.4.tgz", - "integrity": "sha512-RStUATRnb+unYzzuGxU+SPZALqh5NxYdcS6UGTBvhCMlijopGiY/iL01wstIOst0ypKIjwbcSVj7mAHn6B7Qbw==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.7.tgz", + "integrity": "sha512-/oE8kLumzBfU1Z6h4TrDXYCGQNc4CjbZQvPssjImEqNLr5vbefpIpoy1fVMpsyuHZHsGovsBhBHxTJaRLO4+Og==", "requires": { "utif2": "^4.0.1" } }, "@jimp/types": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.4.tgz", - "integrity": "sha512-v3hm8LGc3we6P6ML0ticiLX7wtdvywrKthYxqVrJVIu3vRL0Z4q3ngFjwzqDmaIF8wC0neq98s/t7ODWfeIiRQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.7.tgz", + "integrity": "sha512-1T8BxwDh5HJvBh3tt6HUd8r7ir5Ge3JWATXC8O3Y9QYwOaERjA2+FVhGSjtoo5xCeJvLRjSzEtfZ8heowMBL4w==", "requires": { - "@jimp/bmp": "^0.22.4", - "@jimp/gif": "^0.22.4", - "@jimp/jpeg": "^0.22.4", - "@jimp/png": "^0.22.4", - "@jimp/tiff": "^0.22.4", + "@jimp/bmp": "^0.22.7", + "@jimp/gif": "^0.22.7", + "@jimp/jpeg": "^0.22.7", + "@jimp/png": "^0.22.7", + "@jimp/tiff": "^0.22.7", "timm": "^1.6.1" } }, "@jimp/utils": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.4.tgz", - "integrity": "sha512-EPaBMNg4NvVXnMpSFJEsdCQqdSVU2ACreAL+Ipkq19C/FkDEj9Q10t6Mjx8zOe/AAjBQj1vTALS/DykcHOn4bQ==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.7.tgz", + "integrity": "sha512-4ax4IOWLIERx4yz9y3fNXKvQaPOY23yJF5h4sizxVkQUObkZHWE0kL0TVHodBt3rS8ksdbCL8Jkz4GeNP/Katg==", "requires": { "regenerator-runtime": "^0.13.3" } @@ -12084,9 +12084,9 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "axios": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz", - "integrity": "sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -15475,13 +15475,13 @@ } }, "jimp": { - "version": "0.22.4", - "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.4.tgz", - "integrity": "sha512-reGESbcYp38VlGtdAe8qrmbjLLEYXMrQWc2XXb7+czulKfCCidUHEpNfrS3hx5XXMWrAmoYKkxPTqCvll6Q6ug==", + "version": "0.22.7", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.7.tgz", + "integrity": "sha512-TJCTJ4ZcFUw6W8XZnR6ajdEu8vSyPi3AuoChs+zLHalXnhAPZgwkzwcXnxey4LNjh1p9dfIUkg8YSQ+q8pBW0A==", "requires": { - "@jimp/custom": "^0.22.4", - "@jimp/plugins": "^0.22.4", - "@jimp/types": "^0.22.4", + "@jimp/custom": "^0.22.7", + "@jimp/plugins": "^0.22.7", + "@jimp/types": "^0.22.7", "regenerator-runtime": "^0.13.3" } }, @@ -15524,12 +15524,12 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdoc": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.1.tgz", - "integrity": "sha512-UjvSrLYb270Mq25RN4AGGg2uqKRV90nCqkGsI4gD3RIR1lgMN8nWxK/am8Rsj33tWyprzZdA+0q1qY07m0Ar7w==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", + "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", "dev": true, "requires": { - "@babel/parser": "^7.9.4", + "@babel/parser": "^7.20.15", "@jsdoc/salty": "^0.2.1", "@types/markdown-it": "^12.2.3", "bluebird": "^3.7.2", @@ -17140,9 +17140,9 @@ }, "dependencies": { "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", + "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", diff --git a/package.json b/package.json index 05baeaf2f..1e3111c81 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@excalidraw/excalidraw": "0.14.2", "archiver": "5.3.1", "async-mutex": "0.4.0", - "axios": "1.3.3", + "axios": "1.3.4", "better-sqlite3": "7.4.5", "chokidar": "3.5.3", "cls-hooked": "4.2.2", @@ -64,7 +64,7 @@ "ini": "3.0.1", "is-animated": "2.0.2", "is-svg": "4.3.2", - "jimp": "0.22.4", + "jimp": "0.22.7", "joplin-turndown-plugin-gfm": "1.0.12", "jsdom": "21.1.0", "mime-types": "2.1.35", @@ -101,7 +101,7 @@ "electron-rebuild": "3.2.9", "esm": "3.2.25", "jasmine": "4.5.0", - "jsdoc": "4.0.1", + "jsdoc": "4.0.2", "lorem-ipsum": "2.0.8", "rcedit": "3.0.1", "webpack": "5.75.0", 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 6ef73b28d..d0698601f 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'); @@ -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) */ @@ -1462,6 +1476,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/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/note_detail.js b/src/public/app/widgets/note_detail.js index aaf2c568d..433a20a71 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 = `
').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/routes/api/notes.js b/src/routes/api/notes.js index 2083a9858..be69c5aa5 100644 --- a/src/routes/api/notes.js +++ b/src/routes/api/notes.js @@ -54,10 +54,10 @@ function createNote(req) { } function updateNoteData(req) { - const {content} = req.body; + const {content, ancillaries} = req.body; const {noteId} = req.params; - return noteService.updateNoteData(noteId, content); + return noteService.updateNoteData(noteId, content, ancillaries); } function deleteNote(req) { @@ -127,6 +127,49 @@ function setNoteTypeMime(req) { note.save(); } +function getNoteAncillaries(req) { + const includeContent = req.query.includeContent === 'true'; + const {noteId} = req.params; + + const note = becca.getNote(noteId); + + if (!note) { + throw new NotFoundError(`Note '${noteId}' doesn't exist.`); + } + + const noteAncillaries = note.getNoteAncillaries(); + + return noteAncillaries.map(ancillary => { + const pojo = ancillary.getPojo(); + + if (includeContent && utils.isStringNote(null, ancillary.mime)) { + pojo.content = ancillary.getContent()?.toString(); + pojo.contentLength = pojo.content.length; + + const MAX_ANCILLARY_LENGTH = 1_000_000; + + if (pojo.content.length > MAX_ANCILLARY_LENGTH) { + pojo.content = pojo.content.substring(0, MAX_ANCILLARY_LENGTH); + } + } + + return pojo; + }); +} + +function saveNoteAncillary(req) { + const {noteId, name} = req.params; + const {mime, content} = req.body; + + const note = becca.getNote(noteId); + + if (!note) { + throw new NotFoundError(`Note '${noteId}' doesn't exist.`); + } + + note.saveNoteAncillary(name, mime, content); +} + function getRelationMap(req) { const {relationMapNoteId, noteIds} = req.body; @@ -340,5 +383,7 @@ module.exports = { eraseDeletedNotesNow, getDeleteNotesPreview, uploadModifiedFile, - forceSaveNoteRevision + forceSaveNoteRevision, + getNoteAncillaries, + saveNoteAncillary }; diff --git a/src/routes/api/sync.js b/src/routes/api/sync.js index e2947f096..3600aa743 100644 --- a/src/routes/api/sync.js +++ b/src/routes/api/sync.js @@ -114,6 +114,14 @@ function forceNoteSync(req) { entityChangesService.moveEntityChangeToTop('note_revision_contents', noteRevisionId); } + for (const noteAncillaryId of sql.getColumn("SELECT noteAncillaryId FROM note_ancillaries WHERE noteId = ?", [noteId])) { + sql.execute(`UPDATE note_ancillaries SET utcDateModified = ? WHERE noteAncillaryId = ?`, [now, noteAncillaryId]); + entityChangesService.moveEntityChangeToTop('note_ancillaries', noteAncillaryId); + + sql.execute(`UPDATE note_ancillary_contents SET utcDateModified = ? WHERE noteAncillaryId = ?`, [now, noteAncillaryId]); + entityChangesService.moveEntityChangeToTop('note_ancillary_contents', noteAncillaryId); + } + log.info(`Forcing note sync for ${noteId}`); // not awaiting for the job to finish (will probably take a long time) diff --git a/src/routes/routes.js b/src/routes/routes.js index cdca32975..b6b5d4e39 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -126,6 +126,8 @@ function register(app) { apiRoute(PUT, '/api/notes/:noteId/sort-children', notesApiRoute.sortChildNotes); apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectNote); apiRoute(PUT, '/api/notes/:noteId/type', notesApiRoute.setNoteTypeMime); + apiRoute(GET, '/api/notes/:noteId/ancillaries', notesApiRoute.getNoteAncillaries); + apiRoute(PUT, '/api/notes/:noteId/ancillaries/:name', notesApiRoute.saveNoteAncillary); apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions); apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions); apiRoute(GET, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.getNoteRevision); diff --git a/src/services/app_info.js b/src/services/app_info.js index 3f5f02f3b..5b7582d61 100644 --- a/src/services/app_info.js +++ b/src/services/app_info.js @@ -4,8 +4,8 @@ const build = require('./build'); const packageJson = require('../../package'); const {TRILIUM_DATA_DIR} = require('./data_dir'); -const APP_DB_VERSION = 213; -const SYNC_VERSION = 29; +const APP_DB_VERSION = 214; +const SYNC_VERSION = 30; const CLIPPER_PROTOCOL_VERSION = "1.0"; module.exports = { diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 3fecf607c..6bb6e066d 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -213,6 +213,25 @@ class ConsistencyChecks { logError(`Relation '${attributeId}' references missing note '${noteId}'`) } }); + + this.findAndFixIssues(` + SELECT noteAncillaryId, note_ancillaries.noteId AS noteId + FROM note_ancillaries + LEFT JOIN notes USING (noteId) + WHERE notes.noteId IS NULL + AND note_ancillaries.isDeleted = 0`, + ({noteAncillaryId, noteId}) => { + if (this.autoFix) { + const noteAncillary = becca.getNoteAncillary(noteAncillaryId); + noteAncillary.markAsDeleted(); + + this.reloadNeeded = false; + + logFix(`Note ancillary '${noteAncillaryId}' has been deleted since it references missing note '${noteId}'`); + } else { + logError(`Note ancillary '${noteAncillaryId}' references missing note '${noteId}'`); + } + }); } findExistencyIssues() { @@ -320,6 +339,26 @@ class ConsistencyChecks { logError(`Duplicate branches for note '${noteId}' and parent '${parentNoteId}'`); } }); + + this.findAndFixIssues(` + SELECT noteAncillaryId, + note_ancillaries.noteId AS noteId + FROM note_ancillaries + JOIN notes USING (noteId) + WHERE notes.isDeleted = 1 + AND note_ancillaries.isDeleted = 0`, + ({noteAncillaryId, noteId}) => { + if (this.autoFix) { + const noteAncillary = becca.getNoteAncillary(noteAncillaryId); + noteAncillary.markAsDeleted(); + + this.reloadNeeded = false; + + logFix(`Note ancillary '${noteAncillaryId}' has been deleted since associated note '${noteId}' is deleted.`); + } else { + logError(`Note ancillary '${noteAncillaryId}' is not deleted even though associated note '${noteId}' is deleted.`) + } + }); } findLogicIssues() { @@ -620,6 +659,8 @@ class ConsistencyChecks { this.runEntityChangeChecks("note_contents", "noteId"); this.runEntityChangeChecks("note_revisions", "noteRevisionId"); this.runEntityChangeChecks("note_revision_contents", "noteRevisionId"); + this.runEntityChangeChecks("note_ancillaries", "noteAncillaryId"); + this.runEntityChangeChecks("note_ancillary_contents", "noteAncillaryId"); this.runEntityChangeChecks("branches", "branchId"); this.runEntityChangeChecks("attributes", "attributeId"); this.runEntityChangeChecks("etapi_tokens", "etapiTokenId"); @@ -715,7 +756,7 @@ class ConsistencyChecks { return `${tableName}: ${count}`; } - const tables = [ "notes", "note_revisions", "branches", "attributes", "etapi_tokens" ]; + const tables = [ "notes", "note_revisions", "note_ancillaries", "branches", "attributes", "etapi_tokens" ]; log.info(`Table counts: ${tables.map(tableName => getTableRowCount(tableName)).join(", ")}`); } diff --git a/src/services/entity_changes.js b/src/services/entity_changes.js index 6f9d5034d..2c3991d81 100644 --- a/src/services/entity_changes.js +++ b/src/services/entity_changes.js @@ -151,6 +151,8 @@ function fillAllEntityChanges() { fillEntityChanges("branches", "branchId"); fillEntityChanges("note_revisions", "noteRevisionId"); fillEntityChanges("note_revision_contents", "noteRevisionId"); + fillEntityChanges("note_ancillaries", "noteAncillaryId"); + fillEntityChanges("note_ancillary_contents", "noteAncillaryId"); fillEntityChanges("attributes", "attributeId"); fillEntityChanges("etapi_tokens", "etapiTokenId"); fillEntityChanges("options", "name", 'isSynced = 1'); diff --git a/src/services/export/zip.js b/src/services/export/zip.js index c58afca9f..8196c9e84 100644 --- a/src/services/export/zip.js +++ b/src/services/export/zip.js @@ -170,6 +170,24 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) meta.dataFileName = getDataFileName(note.type, note.mime, baseFileName, existingFileNames); } + const ancillaries = note.getNoteAncillaries(); + + if (ancillaries.length > 0) { + meta.ancillaries = ancillaries + .filter(ancillary => ["canvasSvg", "mermaidSvg"].includes(ancillary.name)) + .map(ancillary => ({ + + name: ancillary.name, + mime: ancillary.mime, + dataFileName: getDataFileName( + null, + ancillary.mime, + baseFileName + "_" + ancillary.name, + existingFileNames + ) + })); + } + if (childBranches.length > 0) { meta.dirFileName = getUniqueFilename(existingFileNames, baseFileName); meta.children = []; @@ -319,6 +337,16 @@ ${markdownContent}`; taskContext.increaseProgressCount(); + for (const ancillaryMeta of noteMeta.ancillaries || []) { + const noteAncillary = note.getNoteAncillaryByName(ancillaryMeta.name); + const content = noteAncillary.getContent(); + + archive.append(content, { + name: filePathPrefix + ancillaryMeta.dataFileName, + date: dateUtils.parseDateTime(note.utcDateModified) + }); + } + if (noteMeta.children && noteMeta.children.length > 0) { const directoryPath = filePathPrefix + noteMeta.dirFileName; diff --git a/src/services/import/zip.js b/src/services/import/zip.js index abe3b58a9..64df89e28 100644 --- a/src/services/import/zip.js +++ b/src/services/import/zip.js @@ -14,6 +14,7 @@ const treeService = require("../tree"); const yauzl = require("yauzl"); const htmlSanitizer = require('../html_sanitizer'); const becca = require("../../becca/becca"); +const BNoteAncillary = require("../../becca/entities/bnote_ancillary"); /** * @param {TaskContext} taskContext @@ -64,6 +65,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { }; let parent; + let ancillaryMeta = false; for (const segment of pathSegments) { if (!cursor || !cursor.children || cursor.children.length === 0) { @@ -72,11 +74,28 @@ async function importZip(taskContext, fileBuffer, importRootNote) { parent = cursor; cursor = parent.children.find(file => file.dataFileName === segment || file.dirFileName === segment); + + if (!cursor) { + for (const file of parent.children) { + for (const ancillary of file.ancillaries || []) { + if (ancillary.dataFileName === segment) { + cursor = file; + ancillaryMeta = ancillary; + break; + } + } + + if (cursor) { + break; + } + } + } } return { parentNoteMeta: parent, - noteMeta: cursor + noteMeta: cursor, + ancillaryMeta }; } @@ -351,7 +370,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { } function saveNote(filePath, content) { - const {parentNoteMeta, noteMeta} = getMeta(filePath); + const {parentNoteMeta, noteMeta, ancillaryMeta} = getMeta(filePath); if (noteMeta?.noImport) { return; @@ -359,6 +378,17 @@ async function importZip(taskContext, fileBuffer, importRootNote) { const noteId = getNoteId(noteMeta, filePath); + if (ancillaryMeta) { + const noteAncillary = new BNoteAncillary({ + noteId, + name: ancillaryMeta.name, + mime: ancillaryMeta.mime + }); + + noteAncillary.setContent(content); + return; + } + const parentNoteId = getParentNoteId(filePath, parentNoteMeta); if (!parentNoteId) { diff --git a/src/services/note_ancillaries.js b/src/services/note_ancillaries.js new file mode 100644 index 000000000..9336b14bb --- /dev/null +++ b/src/services/note_ancillaries.js @@ -0,0 +1,37 @@ +const protectedSession = require("./protected_session"); +const log = require("./log"); + +/** + * @param {BNote} note + */ +function protectNoteAncillaries(note) { + for (const noteAncillary of note.getNoteAncillaries()) { + if (note.isProtected !== noteAncillary.isProtected) { + if (!protectedSession.isProtectedSessionAvailable()) { + log.error("Protected session is not available to fix note ancillaries."); + + return; + } + + try { + const content = noteAncillary.getContent(); + + noteAncillary.isProtected = note.isProtected; + + // this will force de/encryption + noteAncillary.setContent(content); + + noteAncillary.save(); + } + catch (e) { + log.error(`Could not un/protect note ancillary ID = ${noteAncillary.noteAncillaryId}`); + + throw e; + } + } + } +} + +module.exports = { + protectNoteAncillaries +} diff --git a/src/services/sync.js b/src/services/sync.js index 80adc235f..243266cf6 100644 --- a/src/services/sync.js +++ b/src/services/sync.js @@ -321,7 +321,7 @@ function getEntityChangeRow(entityName, entityId) { throw new Error(`Entity ${entityName} ${entityId} not found.`); } - if (['note_contents', 'note_revision_contents'].includes(entityName) && entity.content !== null) { + if (['note_contents', 'note_revision_contents', 'note_ancillary_contents'].includes(entityName) && entity.content !== null) { if (typeof entity.content === 'string') { entity.content = Buffer.from(entity.content, 'UTF-8'); } diff --git a/src/services/sync_update.js b/src/services/sync_update.js index d650fdb0b..50fb29a0e 100644 --- a/src/services/sync_update.js +++ b/src/services/sync_update.js @@ -64,7 +64,7 @@ function updateNormalEntity(remoteEntityChange, remoteEntityRow, instanceId) { || localEntityChange.utcDateChanged < remoteEntityChange.utcDateChanged || localEntityChange.hash !== remoteEntityChange.hash // sync error, we should still update ) { - if (['note_contents', 'note_revision_contents'].includes(remoteEntityChange.entityName)) { + if (['note_contents', 'note_revision_contents', 'note_ancillary_contents'].includes(remoteEntityChange.entityName)) { remoteEntityRow.content = handleContent(remoteEntityRow.content); } @@ -115,7 +115,9 @@ function eraseEntity(entityChange, instanceId) { "branches", "attributes", "note_revisions", - "note_revision_contents" + "note_revision_contents", + "note_ancillaries", + "note_ancillary_contents" ]; if (!entityNames.includes(entityName)) { |
---|