From 71d548b9d6ff47bfa2eb0cdd628d9f702b22d323 Mon Sep 17 00:00:00 2001 From: Christian Beutel <> Date: Wed, 10 Apr 2024 14:40:04 +0200 Subject: [PATCH] adds grid lines to print map --- web/package-lock.json | 789 ++++++++++++++++++ web/package.json | 1 + web/src/lib/components/logo/logo_text.svelte | 127 ++- .../trail/map_with_elevation.svelte | 9 +- web/src/lib/i18n/locales/de.json | 6 + web/src/lib/i18n/locales/en.json | 5 +- web/src/lib/i18n/locales/fr.json | 6 + web/src/lib/i18n/locales/hu.json | 6 + web/src/lib/i18n/locales/nl.json | 6 + web/src/lib/i18n/locales/pl.json | 6 + web/src/lib/i18n/locales/pt.json | 6 + web/src/lib/i18n/locales/zh.json | 6 + web/src/lib/util/leaflet_util.ts | 7 +- .../lib/vendor/leaflet-elevation/src/utils.js | 2 +- .../leaflet-auto-graticule.css | 11 + .../leaflet-auto-graticule.ts | 233 ++++++ .../lib/vendor/leaflet-image/leaflet-image.js | 29 +- .../routes/map/trail/[id]/print/+page.svelte | 68 +- 18 files changed, 1254 insertions(+), 69 deletions(-) create mode 100644 web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.css create mode 100644 web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.ts diff --git a/web/package-lock.json b/web/package-lock.json index d76a50d0..5db32f78 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -21,6 +21,7 @@ "leaflet.awesome-markers": "^2.0.5", "meilisearch": "^0.37.0", "nouislider": "^15.7.1", + "pdfkit": "^0.15.0", "photoswipe": "^5.4.3", "pocketbase": "^0.21.0", "qrcode-with-logos": "^1.0.5", @@ -1006,6 +1007,14 @@ "vite": "^5.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz", + "integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@threlte/core": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@threlte/core/-/core-7.1.0.tgz", @@ -1291,6 +1300,21 @@ "dequal": "^2.0.3" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -1342,6 +1366,20 @@ "postcss": "^8.1.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axobject-query": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz", @@ -1355,6 +1393,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/bidi-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", @@ -1394,6 +1451,14 @@ "node": ">=8" } }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, "node_modules/browserslist": { "version": "4.22.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", @@ -1455,6 +1520,24 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1647,6 +1730,14 @@ "node": ">=8" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/code-red": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", @@ -1736,6 +1827,11 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, "node_modules/crypto-random-string": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-5.0.0.tgz", @@ -1878,6 +1974,37 @@ "node": ">=6" } }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1886,6 +2013,38 @@ "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1916,6 +2075,11 @@ "resolved": "https://registry.npmjs.org/devalue/-/devalue-4.3.2.tgz", "integrity": "sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==" }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1976,6 +2140,44 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es5-ext": { "version": "0.10.64", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", @@ -2204,6 +2406,30 @@ "node": ">=8" } }, + "node_modules/fontkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz", + "integrity": "sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==", + "dependencies": { + "@swc/helpers": "^0.3.13", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "deep-equal": "^2.0.5", + "dfa": "^1.2.0", + "restructure": "^2.0.1", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.3.1", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -2272,6 +2498,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2289,6 +2523,24 @@ "node": "*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -2343,12 +2595,78 @@ "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -2454,6 +2772,19 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/intl-messageformat": { "version": "10.5.11", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.11.tgz", @@ -2465,6 +2796,47 @@ "tslib": "^2.4.0" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2477,6 +2849,21 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-builtin-module": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", @@ -2491,6 +2878,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", @@ -2502,6 +2900,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2531,6 +2943,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", @@ -2545,6 +2968,20 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -2563,6 +3000,46 @@ "@types/estree": "*" } }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -2575,6 +3052,65 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2608,6 +3144,11 @@ "jiti": "bin/jiti.js" } }, + "node_modules/jpeg-exif": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/jpeg-exif/-/jpeg-exif-1.1.4.tgz", + "integrity": "sha512-a+bKEcCjtuW5WTdgeXFzswSrdqi0jk4XlEtZlx5A94wCoBpFjfFTbo/Tra5SpNCl/YFZPvcV1dJc+TAYeg6ROQ==" + }, "node_modules/jsdom": { "version": "24.0.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.0.0.tgz", @@ -2716,6 +3257,23 @@ "node": ">=10" } }, + "node_modules/linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "dependencies": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/linebreak/node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -3103,6 +3661,54 @@ "node": ">= 6" } }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3174,6 +3780,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3259,6 +3870,18 @@ "node": "*" } }, + "node_modules/pdfkit": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.15.0.tgz", + "integrity": "sha512-Z0dx0sEPKLW2kbThS1SWZ0iSHlRPoFMpP+oSjNrtwRjsfGivwE+r6emyEFwQG/fx1Ri0AGUHmDcGOSMMlLLnSg==", + "dependencies": { + "crypto-js": "^4.2.0", + "fontkit": "^1.8.1", + "jpeg-exif": "^1.1.4", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, "node_modules/periscopic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", @@ -3352,6 +3975,11 @@ "node": ">=16" } }, + "node_modules/png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, "node_modules/pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", @@ -3365,6 +3993,14 @@ "resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.21.0.tgz", "integrity": "sha512-WGA5qxW9jzwOTx0i3FNhkKBlT2F5EvC8qZDYv14SB3BeOZVAqs6wMTj7vAXD52V0Fg8zF4XPHJCAJK04fw1rqg==" }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.33", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", @@ -3619,6 +4255,23 @@ "node": ">=8.10.0" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3670,6 +4323,11 @@ "node": ">=4" } }, + "node_modules/restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3800,6 +4458,36 @@ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3821,6 +4509,23 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -3887,6 +4592,17 @@ "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", "dev": true }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -4357,6 +5073,11 @@ "globrex": "^0.1.2" } }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, "node_modules/tinybench": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", @@ -4513,6 +5234,24 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "devOptional": true }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, "node_modules/universalify": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", @@ -4798,11 +5537,61 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/why-is-node-running": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", diff --git a/web/package.json b/web/package.json index 62d13783..cfe8b282 100644 --- a/web/package.json +++ b/web/package.json @@ -46,6 +46,7 @@ "leaflet.awesome-markers": "^2.0.5", "meilisearch": "^0.37.0", "nouislider": "^15.7.1", + "pdfkit": "^0.15.0", "photoswipe": "^5.4.3", "pocketbase": "^0.21.0", "qrcode-with-logos": "^1.0.5", diff --git a/web/src/lib/components/logo/logo_text.svelte b/web/src/lib/components/logo/logo_text.svelte index b98dfe07..7a57d1ce 100644 --- a/web/src/lib/components/logo/logo_text.svelte +++ b/web/src/lib/components/logo/logo_text.svelte @@ -1,25 +1,102 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/src/lib/components/trail/map_with_elevation.svelte b/web/src/lib/components/trail/map_with_elevation.svelte index f6d7d588..7f8c972e 100644 --- a/web/src/lib/components/trail/map_with_elevation.svelte +++ b/web/src/lib/components/trail/map_with_elevation.svelte @@ -25,6 +25,7 @@ await import("leaflet.awesome-markers"); //@ts-ignore await import("$lib/vendor/leaflet-elevation/src/index.js"); + const AutoGraticule = (await import("$lib/vendor/leaflet-graticule/leaflet-auto-graticule")).default; map = L.map("map", { preferCanvas: true }).setView( [trail.lat ?? 0, trail.lon ?? 0], @@ -35,7 +36,7 @@ map!.on("zoomend", function () { dispatch("zoomend", map); }); - + L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { attribution: "© OpenStreetMap contributors", }).addTo(map); @@ -92,6 +93,7 @@ iconColor: "white", }), }, + graticule: false }; const elevation_options = Object.assign( @@ -106,6 +108,11 @@ marker.addTo(map!); markers.push(marker); } + + if(elevation_options.graticule) { + new AutoGraticule().addTo(map!); + } + }); diff --git a/web/src/lib/i18n/locales/de.json b/web/src/lib/i18n/locales/de.json index 597a36d9..c8490d61 100644 --- a/web/src/lib/i18n/locales/de.json +++ b/web/src/lib/i18n/locales/de.json @@ -83,6 +83,11 @@ "metric": "Metrisch", "moderate": "Mittel", "must-be-at-least-n-characters-long": "Muss mindestens {n} Zeichen lang sein", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "Name", "near": "Nahe", @@ -99,6 +104,7 @@ "pick-a-trail": "Route auswählen", "polish": "Polnisch", "portuguese": "Portugiesisch", + "print": "", "profile": "Profil", "public": "Öffentlich", "radius": "Radius", diff --git a/web/src/lib/i18n/locales/en.json b/web/src/lib/i18n/locales/en.json index 1a1721cb..138c9bfa 100644 --- a/web/src/lib/i18n/locales/en.json +++ b/web/src/lib/i18n/locales/en.json @@ -83,12 +83,12 @@ "metric": "Metric", "moderate": "Moderate", "must-be-at-least-n-characters-long": "Must be at least {n} characters long", - "n-years-ago": "{n} years ago", - "n-months-ago": "{n} months ago", "n-days-ago": "{n} days ago", "n-hours-ago": "{n} hours ago", "n-minutes-ago": "{n} minutes ago", + "n-months-ago": "{n} months ago", "n-seconds-ago": "{n} seconds ago", + "n-years-ago": "{n} years ago", "name": "Name", "near": "Near", "new-list": "New List", @@ -104,6 +104,7 @@ "pick-a-trail": "Pick a trail", "polish": "Polish", "portuguese": "Portuguese", + "print": "Print", "profile": "Profile", "public": "Public", "radius": "Radius", diff --git a/web/src/lib/i18n/locales/fr.json b/web/src/lib/i18n/locales/fr.json index ebb95288..0c0c6020 100644 --- a/web/src/lib/i18n/locales/fr.json +++ b/web/src/lib/i18n/locales/fr.json @@ -83,6 +83,11 @@ "metric": "Métrique", "moderate": "Modérer", "must-be-at-least-n-characters-long": "Doit être composé d'au moins {n} caractères", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "Nom", "near": "Proche", @@ -99,6 +104,7 @@ "pick-a-trail": "Choisir un itinéraire", "polish": "polonais", "portuguese": "Portugais", + "print": "", "profile": "Profile", "public": "Publique", "radius": "Rayon", diff --git a/web/src/lib/i18n/locales/hu.json b/web/src/lib/i18n/locales/hu.json index 65bac44f..c6fd9af0 100644 --- a/web/src/lib/i18n/locales/hu.json +++ b/web/src/lib/i18n/locales/hu.json @@ -83,6 +83,11 @@ "metric": "Metrikus", "moderate": "Mérsékelt", "must-be-at-least-n-characters-long": "Legalább {n} karakter hosszúnak kell lennie", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "Név", "near": "Közelben", @@ -99,6 +104,7 @@ "pick-a-trail": "Válasszon útvonalat", "polish": "Lengyel", "portuguese": "Portugál", + "print": "", "profile": "Profil", "public": "Publikus", "radius": "Átmérő", diff --git a/web/src/lib/i18n/locales/nl.json b/web/src/lib/i18n/locales/nl.json index 3ad2774a..448802a9 100644 --- a/web/src/lib/i18n/locales/nl.json +++ b/web/src/lib/i18n/locales/nl.json @@ -83,6 +83,11 @@ "metric": "Metrisch", "moderate": "Gemiddeld", "must-be-at-least-n-characters-long": "Minimaal {n} tekens", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "Naam", "near": "Nabij", @@ -99,6 +104,7 @@ "pick-a-trail": "Kies een wandelroute", "polish": "Pools", "portuguese": "Portugees", + "print": "", "profile": "Profiel", "public": "Openbaar", "radius": "Straal", diff --git a/web/src/lib/i18n/locales/pl.json b/web/src/lib/i18n/locales/pl.json index a51c8f23..f650289a 100644 --- a/web/src/lib/i18n/locales/pl.json +++ b/web/src/lib/i18n/locales/pl.json @@ -83,6 +83,11 @@ "metric": "Metryczne", "moderate": "Średnia", "must-be-at-least-n-characters-long": "Długość musi wynosić przynajmniej {n} znaków", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "Nazwa", "near": "Blisko", @@ -99,6 +104,7 @@ "pick-a-trail": "Wybierz ścieżkę", "polish": "Polski", "portuguese": "Portugalski", + "print": "", "profile": "Profil", "public": "Publiczny", "radius": "Promień", diff --git a/web/src/lib/i18n/locales/pt.json b/web/src/lib/i18n/locales/pt.json index 6bf44290..bbdbad82 100644 --- a/web/src/lib/i18n/locales/pt.json +++ b/web/src/lib/i18n/locales/pt.json @@ -83,6 +83,11 @@ "metric": "Métrica", "moderate": "Moderado", "must-be-at-least-n-characters-long": "Deve ter pelo menos {n} caracteres", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "Nome", "near": "Próximo", @@ -99,6 +104,7 @@ "pick-a-trail": "Escolha uma trilha", "polish": "Polonês", "portuguese": "Português", + "print": "", "profile": "Perfil", "public": "Público", "radius": "Raio", diff --git a/web/src/lib/i18n/locales/zh.json b/web/src/lib/i18n/locales/zh.json index f95422f7..882912e6 100644 --- a/web/src/lib/i18n/locales/zh.json +++ b/web/src/lib/i18n/locales/zh.json @@ -83,6 +83,11 @@ "metric": "公制", "moderate": "中等", "must-be-at-least-n-characters-long": "长度至少 {n} 字符", + "n-days-ago": "", + "n-hours-ago": "", + "n-minutes-ago": "", + "n-months-ago": "", + "n-seconds-ago": "", "n-years-ago": "", "name": "名称", "near": "附近", @@ -99,6 +104,7 @@ "pick-a-trail": "选择一个路线", "polish": "波兰语", "portuguese": "葡萄牙语", + "print": "", "profile": "个人资料", "public": "公开", "radius": "半径", diff --git a/web/src/lib/util/leaflet_util.ts b/web/src/lib/util/leaflet_util.ts index a687b5d8..fbcaa22e 100644 --- a/web/src/lib/util/leaflet_util.ts +++ b/web/src/lib/util/leaflet_util.ts @@ -12,7 +12,10 @@ export function createMarkerFromWaypoint(L: any, waypoint: Waypoint, onDragEnd?: const marker = L.marker([waypoint.lat, waypoint.lon], { title: waypoint.name, icon: fontAwesomeIcon, - draggable: onDragEnd != null + draggable: onDragEnd != null, + meta: { + waypointName: waypoint.name + } }) .bindPopup( "" + @@ -25,7 +28,7 @@ export function createMarkerFromWaypoint(L: any, waypoint: Waypoint, onDragEnd?: if (onDragEnd) { marker.on("dragend", onDragEnd); } - + return marker; } diff --git a/web/src/lib/vendor/leaflet-elevation/src/utils.js b/web/src/lib/vendor/leaflet-elevation/src/utils.js index 5aaad7df..a322eedd 100644 --- a/web/src/lib/vendor/leaflet-elevation/src/utils.js +++ b/web/src/lib/vendor/leaflet-elevation/src/utils.js @@ -9,7 +9,7 @@ export const Colors = { 'steelblue': { area: '#4682B4' }, 'red' : { area: '#F00' }, 'lime' : { area: '#9CC222', line: '#566B13' }, - 'gray': { area: '#000000', line: '#242734', alpha: 0.00001, stroke: '#000000' } + 'gray': { area: '#000000', line: '#3366CC', alpha: 0.00001, stroke: '#000000' } }; const SEC = 1000; diff --git a/web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.css b/web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.css new file mode 100644 index 00000000..377462e8 --- /dev/null +++ b/web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.css @@ -0,0 +1,11 @@ +.leaflet-grid-label .gridlabel-vert { + margin-left: 8px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} + +.leaflet-grid-label .gridlabel-vert, +.leaflet-grid-label .gridlabel-horiz { + padding-left:2px; + text-shadow: -2px 0 #FFFFFF, 0 2px #FFFFFF, 2px 0 #FFFFFF, 0 -2px #FFFFFF; +} \ No newline at end of file diff --git a/web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.ts b/web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.ts new file mode 100644 index 00000000..f12f75c8 --- /dev/null +++ b/web/src/lib/vendor/leaflet-graticule/leaflet-auto-graticule.ts @@ -0,0 +1,233 @@ +import { LatLngBounds, type LatLngExpression, type LayerOptions, type LeafletEventHandlerFnMap, type PolylineOptions, Map, LayerGroup, Util, Polyline, LatLng, marker, divIcon, latLngBounds } from 'leaflet'; +import './leaflet-auto-graticule.css'; + +export interface AutoGraticuleOptions extends LayerOptions { + redraw: keyof LeafletEventHandlerFnMap, + + /** Minimum distance between two lines in pixels */ + minDistance: number +} + +export default class AutoGraticule extends LayerGroup { + + options: AutoGraticuleOptions = { + redraw: 'moveend', + minDistance: 100 // Minimum distance between two lines in pixels + }; + + lineStyle: PolylineOptions = { + stroke: true, + color: '#333', + opacity: 0.6, + weight: 1, + interactive: false + }; + + _bounds!: LatLngBounds; + + + constructor(options?: Partial) { + super(); + Util.setOptions(this, options); + } + + + onAdd(map: Map) { + this._map = map; + + this.redraw(); + this._map.on('viewreset ' + this.options.redraw, this.redraw, this); + + this.eachLayer(map.addLayer, map); + + return this; + } + + onRemove(map: Map) { + map.off('viewreset ' + this.options.redraw, this.redraw, this); + this.eachLayer(this.removeLayer, this); + return this; + } + + redraw() { + this._bounds = this._map.getBounds().pad(0.5); + + this.clearLayers(); + + this.constructLines(); + + return this; + } + + constructLines() { + const bounds = this._map.getBounds(); + const zoom = this._map.getZoom(); + + // Fix drawing of lines outside of bounds + this._bounds = AutoGraticule.bboxIntersect(bounds, [[-85, -180], [85, 180]]); + + // Fix drawing of labels outside of bounds + const getBoundsBkp = this._map.getBounds; + try { + this._map.getBounds = function () { + return AutoGraticule.bboxIntersect(getBoundsBkp.apply(this), [[-85, -180], [85, 180]]) + }; + + // Longitude: Draw vartical lines with a fixed distance between each other + const center = this._map.project(bounds.getCenter(), zoom); + const divisor = AutoGraticule.getGridDivisor(this._map.unproject(center.add([this.options.minDistance / 2, 0]), zoom).lng - this._map.unproject(center.subtract([this.options.minDistance / 2, 0]), zoom).lng, false); + const west = Math.max(bounds.getWest(), -180); + const east = Math.min(bounds.getEast(), 180); + for (let lng = AutoGraticule.fixFloatingPoint(Math.ceil(west / divisor) * divisor); lng <= east; lng += divisor) { + this.addLayer(this.buildXLine(lng)); + this.addLayer(this.buildLabel('gridlabel-horiz', AutoGraticule.fixFloatingPoint(lng))); + } + + // Latitude: Draw horizontal lines with a variable distance between each other (as in Mercator projection, the distance + // between latitudes gets bigger towards the poles). Calculate a divisor that all latitude line coordinates must be + // dividable by, but then only draw those coordinates that keep the minimum distance to their neighbour lines. + // Draw lines north of the equator separately from lines south of the equator (to keep the grid symmetical in + // relation to the equator). + if (bounds.getNorth() > 0) { + let lat = Math.max(0, bounds.getSouth()); + let first = true; + while (lat < bounds.getNorth() && lat < 85) { + const point = this._map.project([lat, bounds.getCenter().lng], zoom); + const point2LatLng = this._map.unproject(point.subtract([0, this.options.minDistance]), zoom); + + const divisor = AutoGraticule.getGridDivisor(point2LatLng.lat - lat, true); + lat = AutoGraticule.fixFloatingPoint(first ? Math.ceil(lat / divisor) * divisor : Math.ceil(point2LatLng.lat / divisor) * divisor); + + first = false; + + this.addLayer(this.buildYLine(lat)); + this.addLayer(this.buildLabel('gridlabel-vert', lat)); + } + } + if (bounds.getSouth() < 0) { + let lat = Math.min(0, bounds.getNorth()); + let first = true; + while (lat > bounds.getSouth() && lat > -85) { + const point = this._map.project([lat, bounds.getCenter().lng], zoom); + const point2LatLng = this._map.unproject(point.add([0, this.options.minDistance]), zoom); + + const divisor = AutoGraticule.getGridDivisor(AutoGraticule.fixFloatingPoint(lat - point2LatLng.lat), true); + lat = AutoGraticule.fixFloatingPoint(first ? Math.floor(lat / divisor) * divisor : Math.floor(point2LatLng.lat / divisor) * divisor); + + first = false; + + this.addLayer(this.buildYLine(lat)); + this.addLayer(this.buildLabel('gridlabel-vert', lat)); + } + } + } finally { + this._map.getBounds = getBoundsBkp; + } + } + + buildXLine(x: number): Polyline { + const bottomLL = new LatLng(this._bounds.getSouth(), x); + const topLL = new LatLng(this._bounds.getNorth(), x); + + return new Polyline([bottomLL, topLL], this.lineStyle); + } + + buildYLine(y: number): L.Polyline { + const leftLL = new LatLng(y, this._bounds.getWest()); + const rightLL = new LatLng(y, this._bounds.getEast()); + + return new Polyline([leftLL, rightLL], this.lineStyle); + } + + buildLabel(axis: 'gridlabel-horiz' | 'gridlabel-vert', val: number) { + const bounds = this._map.getBounds().pad(-0.003); + let latLng: LatLng; + if (axis == 'gridlabel-horiz') { + latLng = new LatLng(bounds.getNorth(), val); + } else { + latLng = new LatLng(val, bounds.getWest()); + } + + return marker(latLng, { + interactive: false, + icon: divIcon({ + iconSize: [0, 0], + className: 'leaflet-grid-label', + html: '
' + val + ' °
' + }) + }); + } + + /** + * Rounds the given number to a fixed number of decimals in order to avoid floating point inaccuracies + * (for example to make 0.1 + 0.2 = 0.3 instead of 0.30000000000000004). + */ + static fixFloatingPoint(number: number): number { + return AutoGraticule.round(number, 12); + } + + /** + * Rounds the given number to the given number of decimals. + */ + static round(number: number, digits: number) { + const fac = Math.pow(10, digits); + return Math.round(number * fac) / fac; + } + + /** + * Given the distance between two coordinates, floors this distance to 90, 60, 45, 30 or + * 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01, ... + * This will define the distance between two grid lines. + * @param variableDistance This should be true when the distance between the grid lines will be variable, that is for the latitude + * lines (because in Meractor projection the distance between two latitutes gets larger towards the poles, but the distance + * between two longitudes is constant throughout the globe). + * For constant distance lines (longitude), a line should be shown for every coordinate dividable by the result of this + * function. For example, if the result is 45, a line should be shown for longitudes -180, -135, -90, -45, 0, 45, 90, 135, 180. + * For variable distance lines (latitude), a line should be shown for coordinates dividable by a result of this function, but + * not for every single coordinate but only those that have a minimum distance towards their neighbour coordinate line. For + * variable distance lines, the maximum number returned by this function is 5, meaning at low zoom levels, all latitude lines + * are dividable by 5 (but not every latitude dividable by 5 will get a line). + */ + static getGridDivisor(number: number, variableDistance: boolean) { + if (number <= 0 || !isFinite(number)) + throw new Error("Invalid number " + number); + else { + if (variableDistance && number >= 5) + return 5; + if (number <= 10) { + let fac = 1; + while (number > 1) { fac *= 10; number /= 10; } + while (number <= 0.1) { fac /= 10; number *= 10; } + + // Dist is now some number between 0.1 and 1, so we can round it conveniently and then multiply it again by fac to get back to the original dist + + if (number == 0.1) + return AutoGraticule.fixFloatingPoint(0.1 * fac); + else if (number <= 0.2) + return AutoGraticule.fixFloatingPoint(0.2 * fac); + else if (number <= 0.5) + return AutoGraticule.fixFloatingPoint(0.5 * fac); + else + return fac; + } else if (number <= 30) + return 30; + else if (number <= 45) + return 45; + else if (number <= 60) + return 60; + else + return 90; + } + } + // Backwards compatibility + static niceRound = AutoGraticule.getGridDivisor; + + static bboxIntersect(bbox1: LatLngBounds | LatLngExpression[], bbox2: LatLngBounds | LatLngExpression[]) { + const bounds1 = bbox1 instanceof LatLngBounds ? bbox1 : latLngBounds(bbox1); + const bounds2 = bbox2 instanceof LatLngBounds ? bbox2 : latLngBounds(bbox2); + return latLngBounds([ + [Math.max(bounds1.getSouth(), bounds2.getSouth()), Math.max(bounds1.getWest(), bounds2.getWest())], + [Math.min(bounds1.getNorth(), bounds2.getNorth()), Math.min(bounds1.getEast(), bounds2.getEast())] + ]); + } +} \ No newline at end of file diff --git a/web/src/lib/vendor/leaflet-image/leaflet-image.js b/web/src/lib/vendor/leaflet-image/leaflet-image.js index e3cbbfd8..3364ca9e 100644 --- a/web/src/lib/vendor/leaflet-image/leaflet-image.js +++ b/web/src/lib/vendor/leaflet-image/leaflet-image.js @@ -197,12 +197,11 @@ export default function leafletImage(map, callback) { minPoint = new L.Point(pixelBounds.min.x, pixelBounds.min.y), pixelPoint = map.project(marker.getLatLng()), url = "/vendor/leaflet-image/marker.png", - icon = getComputedStyle(marker._icon.children[0], ':before').getPropertyValue('content').substring(1, 2) ?? "\uf111", im = new Image(), options = marker.options.icon.options, size = options.iconSize, pos = pixelPoint.subtract(minPoint), - anchor = L.point(options.iconAnchor || size && size.divideBy(2, true)); + anchor = L.point(options.iconAnchor || size && { x: size[0], y: size[1] }); if (size instanceof L.Point) size = [size.x, size.y]; @@ -214,10 +213,28 @@ export default function leafletImage(map, callback) { im.crossOrigin = ''; im.onload = function () { - ctx.drawImage(this, x, y, size[0], size[1]); - ctx.font = '600 14px "Font Awesome 6 Free"'; - ctx.fillStyle = "#ffffff"; - ctx.fillText(icon, x + 10.2, y + 24); + if (marker._icon.classList.contains("leaflet-grid-label")) { + const label = marker._icon.children[0].textContent; + ctx.font = '600 8px "Font Awesome 6 Free"'; + ctx.fillStyle = "#000"; + ctx.fillText(label, x + 4, y + 12); + } else { + const waypointName = marker.options.meta?.waypointName; + const icon = getComputedStyle(marker._icon.children[0], ':before').getPropertyValue('content').substring(1, 2) ?? "\uf111"; + ctx.drawImage(this, x, y, size[0], size[1]); + ctx.font = '600 14px "Font Awesome 6 Free"'; + ctx.fillStyle = "#ffffff"; + ctx.fillText(icon, x + 10.2, y + 24); + if (waypointName) { + ctx.fillStyle = "#313131" + ctx.roundRect(x - 8, y - 18, waypointName.length * 7, 20, 5) + ctx.fill(); + ctx.font = '600 12px "IBMPlexSans"'; + ctx.fillStyle = "#ffffff"; + ctx.fillText(waypointName, x, y - 4); + } + } + callback(null, { canvas: canvas }); diff --git a/web/src/routes/map/trail/[id]/print/+page.svelte b/web/src/routes/map/trail/[id]/print/+page.svelte index 2df02add..65ac4e86 100644 --- a/web/src/routes/map/trail/[id]/print/+page.svelte +++ b/web/src/routes/map/trail/[id]/print/+page.svelte @@ -2,8 +2,15 @@ import { page } from "$app/stores"; import Button from "$lib/components/base/button.svelte"; import Select from "$lib/components/base/select.svelte"; + import LogoText from "$lib/components/logo/logo_text.svelte"; import MapWithElevation from "$lib/components/trail/map_with_elevation.svelte"; import { trail } from "$lib/stores/trail_store"; + import { currentUser } from "$lib/stores/user_store"; + import { + formatDistance, + formatElevation, + formatTimeHHMM, + } from "$lib/util/format_util"; import { calculatePixelPerMeter, calculateScaleFactor, @@ -16,14 +23,7 @@ import "leaflet/dist/leaflet.css"; import QrCodeWithLogo from "qrcode-with-logos"; import { onMount, tick } from "svelte"; - import { currentUser } from "$lib/stores/user_store"; - import { - formatDistance, - formatElevation, - formatTimeHHMM, - } from "$lib/util/format_util"; - import LogoTextLight from "$lib/components/logo/logo_text_light.svelte"; - import LogoText from "$lib/components/logo/logo_text.svelte"; + import { _ } from "svelte-i18n"; let map: Map; @@ -164,9 +164,13 @@ } -
+ + {$_("print")} | wanderer + + +