diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..472150eeb --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/test.ts \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 000000000..ff3f3e8f9 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,27 @@ +/* eslint-env node */ +module.exports = { + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:svelte/recommended", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + extraFileExtensions: [".svelte"], + }, + overrides: [ + { + files: ["*.svelte"], + parser: "svelte-eslint-parser", + parserOptions: { + parser: "@typescript-eslint/parser", + }, + }, + ], + plugins: ["@typescript-eslint"], + root: true, + env: { + browser: true, + node: true, + }, +} diff --git a/.gitignore b/.gitignore index 41f172fe8..a9dcf16ad 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ index_*.ts .~lock.* *.doctest.ts service-worker.js +.env .vscode/* !.vscode/settings.json diff --git a/.nvmrc b/.nvmrc index 132d0eed6..06e751596 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -nodejs 16.9.1 \ No newline at end of file +16.9.1 diff --git a/.vscode/extensions.json b/.vscode/extensions.json index f2dca9d05..8a636f99e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,10 +1,11 @@ { - "recommendations": [ - "esbenp.prettier-vscode", - "eamodio.gitlens", - "github.vscode-pull-request-github", - "svelte.svelte-vscode", - "bradlc.vscode-tailwindcss", - "editorconfig.editorconfig" - ] + "recommendations": [ + "esbenp.prettier-vscode", + "eamodio.gitlens", + "github.vscode-pull-request-github", + "svelte.svelte-vscode", + "bradlc.vscode-tailwindcss", + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint" + ] } diff --git a/assets/layers/artwork/artwork.json b/assets/layers/artwork/artwork.json index 2561cff78..a14715d00 100644 --- a/assets/layers/artwork/artwork.json +++ b/assets/layers/artwork/artwork.json @@ -629,23 +629,30 @@ "he": "האם יש אתר אינטרנט עם מידע נוסף על היצירה הזו?" }, "render": { - "en": "More information on this website", - "nl": "Meer informatie op deze website", - "fr": "Plus d'info sûr ce site web", - "de": "Weitere Informationen auf dieser Webseite", - "id": "Info lanjut tersedia di laman web ini", - "it": "Ulteriori informazioni su questo sito web", - "ru": "Больше информации на этом сайте", - "ja": "Webサイトに詳細情報がある", - "zh_Hant": "這個網站有更多資訊", - "nb_NO": "Mer info er å finne på denne nettsiden", - "pt": "Mais informações neste site", - "hu": "További információ ezen a weboldalon", - "pl": "Więcej informacji na tej stronie", - "es": "Más información en este sitio web", - "da": "Yderligere oplysninger på dette websted", - "cs": "Více informací na této webové stránce", - "ca": "Més informació a aquesta pàgina web" + "special": { + "type": "link", + "href": "{website}", + "text": { + "en": "More information on this website", + "nl": "Meer informatie op deze website", + "fr": "Plus d'info sûr ce site web", + "de": "Weitere Informationen auf dieser Webseite", + "id": "Info lanjut tersedia di laman web ini", + "it": "Ulteriori informazioni su questo sito web", + "ru": "Больше информации на этом сайте", + "ja": "Webサイトに詳細情報がある", + "zh_Hant": "這個網站有更多資訊", + "nb_NO": "Mer info er å finne på denne nettsiden", + "pt": "Mais informações neste site", + "hu": "További információ ezen a weboldalon", + "pl": "Więcej informacji na tej stronie", + "es": "Más información en este sitio web", + "da": "Yderligere oplysninger på dette websted", + "cs": "Více informací na této webové stránce", + "ca": "Més informació a aquesta pàgina web" + } + } + }, "freeform": { "key": "website", diff --git a/assets/layers/atm/atm.json b/assets/layers/atm/atm.json index 881a1499a..04e74522d 100644 --- a/assets/layers/atm/atm.json +++ b/assets/layers/atm/atm.json @@ -290,27 +290,8 @@ }, { "or": [ - "_country=", - "_country=at", - "_country=be", - "_country=cy", - "_country=de", - "_country=ee", - "_country=es", - "_country=fi", - "_country=fr", - "_country=gr", - "_country=hr", - "_country=ie", - "_country=it", - "_country=lt", - "_country=lu", - "_country=lv", - "_country=mt", - "_country=nl", - "_country=pt", - "_country=si", - "_country=sk" + "_currency=", + "_currency~.*EUR.*" ] } ] @@ -329,7 +310,7 @@ "mappings": [ { "if": "cash_out:notes:denominations=5 EUR", - "icon": "./assets/layers/questions/5euro.svg", + "icon": "./assets/layers/questions/denominations/eur/5euro.svg", "then": { "en": "5 euro notes can be withdrawn", "nl": "Je kunt biljetten van 5 euro afhalen", @@ -341,7 +322,7 @@ }, { "if": "cash_out:notes:denominations=10 EUR", - "icon": "./assets/layers/questions/10euro.svg", + "icon": "./assets/layers/questions/denominations/eur/10euro.svg", "then": { "en": "10 euro notes can be withdrawn", "nl": "Je kunt biljetten van 10 euro afhalen", @@ -353,7 +334,7 @@ }, { "if": "cash_out:notes:denominations=20 EUR", - "icon": "./assets/layers/questions/20euro.svg", + "icon": "./assets/layers/questions/denominations/eur/20euro.svg", "then": { "en": "20 euro notes can be withdrawn", "nl": "Je kunt biljetten van 20 euro afhalen", @@ -365,7 +346,7 @@ }, { "if": "cash_out:notes:denominations=50 EUR", - "icon": "./assets/layers/questions/50euro.svg", + "icon": "./assets/layers/questions/denominations/eur/50euro.svg", "then": { "en": "50 euro notes can be withdrawn", "nl": "Je kunt biljetten van 50 euro afhalen", @@ -377,7 +358,7 @@ }, { "if": "cash_out:notes:denominations=100 EUR", - "icon": "./assets/layers/questions/100euro.svg", + "icon": "./assets/layers/questions/denominations/eur/100euro.svg", "then": { "en": "100 euro notes can be withdrawn", "nl": "Je kunt biljetten van 100 euro afhalen", @@ -389,7 +370,7 @@ }, { "if": "cash_out:notes:denominations=200 EUR", - "icon": "./assets/layers/questions/200euro.svg", + "icon": "./assets/layers/questions/denominations/eur/200euro.svg", "then": { "en": "200 euro notes can be withdrawn", "nl": "Je kunt biljetten van 200 euro afhalen", @@ -401,7 +382,7 @@ }, { "if": "cash_out:notes:denominations=500 EUR", - "icon": "./assets/layers/questions/500euro.svg", + "icon": "./assets/layers/questions/denominations/eur/500euro.svg", "then": { "en": "500 euro notes can be withdrawn", "nl": "Je kunt biljetten van 500 euro afhalen", @@ -523,4 +504,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/assets/layers/climbing/climbing.json b/assets/layers/climbing/climbing.json index 5f6a4546b..6be535d0d 100644 --- a/assets/layers/climbing/climbing.json +++ b/assets/layers/climbing/climbing.json @@ -32,7 +32,7 @@ "club=" ] }, - "render": "{url}", + "render": "{url}", "freeform": { "key": "url", "type": "url" diff --git a/assets/layers/elevator/elevator.json b/assets/layers/elevator/elevator.json index fb54abe24..fb453c3bd 100644 --- a/assets/layers/elevator/elevator.json +++ b/assets/layers/elevator/elevator.json @@ -151,8 +151,23 @@ } }, "induction-loop", + + {"id": "tactile_writing_available", + "question": {"en": "Has this elevator tactile writing?"}, + + "mappings":[ + {"if":"tactile_writing:braille=yes", + "then": {"en": "This elevator has tactile writing in Braille"} + }, + {"if":"tactile_writing:braille=no", + "then": {"en": "This elevator does not have tactile writing"} + } + ] + }, + { "id": "tactile_writing_language", + "condition": "tactile_writing:braille=yes", "render": { "special": { "type": "language_chooser", @@ -175,8 +190,22 @@ } } }, + {"id": "speech_output_available", + "question": {"en": "Has this elevator speech output?"}, + "questionHint": {"en": "E.g. it announces the current floor"}, + "mappings":[ + {"if":"speech_output=yes", + "then": {"en": "This elevator has speech output"} + }, + {"if":"speech_output=no", + "then": {"en": "This elevator does not have speech output"} + } + ] + }, + { "id": "speech_output", + "condition": "speech_output=yes", "render": { "special": { "type": "language_chooser", @@ -247,7 +276,8 @@ "defaultInput": "cm", "applicableUnits": [ { - "canonicalDenomination": "m", + "canonicalDenomination": "m" + , "alternativeDenomination": [ "meter" ], diff --git a/assets/layers/elongated_coin/elongated_coin.json b/assets/layers/elongated_coin/elongated_coin.json index 1f3b8921b..903493f4e 100644 --- a/assets/layers/elongated_coin/elongated_coin.json +++ b/assets/layers/elongated_coin/elongated_coin.json @@ -84,7 +84,50 @@ } ] }, - "payment-options-split", + { + "id": "fee", + "question": { + "en": "Does it cost money to press a penny?" + }, + "mappings": [ + { + "if": "fee=", + "then": { + "en": "It costs money to press a penny." + } + }, + { + "if": "fee=yes", + "then": { + "en": "It costs money to press a penny." + } + }, + { + "if": "fee=no", + "then": { + "en": "It is free to press a penny." + }, + "addExtraTags": [ + "payment:qr_code=", + "payment:coins=", + "payment:notes=", + "payment:debit_cards=", + "payment:credit_cards=" + ] + } + ] + }, + { + "builtin": "payment-options-split", + "override": { + "condition": { + "or": [ + "fee=yes", + "fee=" + ] + } + } + }, { "id": "coin", "question": { @@ -109,6 +152,12 @@ "en": "This penny press uses a 2 cent coin for pressing.", "de": "Die Münzpresse benötigt eine 2 Cent Münze um zu Pressen.", "es": "Esta prensa de centavo utiliza una moneda de 2 centavos para presionar." + }, + "hideInAnswer": { + "and": [ + "_currency!~.*EUR.*", + "_currency!~.*USD.*" + ] } }, { @@ -117,6 +166,12 @@ "en": "This penny press uses a 5 cent coin for pressing.", "de": "Die Münzpresse benötigt eine 5 Cent Münze um zu Pressen.", "es": "Esta prensa de centavo utiliza una moneda de 5 centavos para presionar." + }, + "hideInAnswer": { + "and": [ + "_currency!~.*EUR.*", + "_currency!~.*USD.*" + ] } }, { @@ -125,6 +180,12 @@ "en": "This penny press uses a 10 cent coin for pressing.", "de": "Die Münzpresse benötigt eine 10 Cent Münze um zu Pressen.", "es": "Esta prensa de centavo utiliza una moneda de 10 centavos para presionar." + }, + "hideInAnswer": { + "and": [ + "_currency!~.*EUR.*", + "_currency!~.*USD.*" + ] } }, { @@ -144,6 +205,20 @@ "es": "Esta prensa de centavo utiliza una moneda de 50 centavos para presionar." }, "hideInAnswer": "_currency!~.*USD.*" + }, + { + "if": "coin:type=10centimes", + "then": { + "en": "This penny press uses a 10 centimes coin for pressing." + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "coin:type=20centimes", + "then": { + "en": "This penny press uses a 20 centimes coin for pressing." + }, + "hideInAnswer": "_currency!~.*CHF.*" } ], "render": { @@ -155,6 +230,12 @@ "website", { "id": "charge", + "condition": { + "or": [ + "fee=yes", + "fee=" + ] + }, "question": { "en": "How much does it cost to press a penny?", "de": "Wieviel kostet es eine Münze zu Pressen?", @@ -187,6 +268,20 @@ "es": "Cuesta 2 euros para presionar un centavo." }, "hideInAnswer": "_currency!~.*EUR.*" + }, + { + "if": "charge=2 CHF", + "then": { + "en": "It costs 2 Swiss francs to press a penny." + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "charge=1 CHF", + "then": { + "en": "It costs 1 Swiss franc to press a penny." + }, + "hideInAnswer": "_currency!~.*CHF.*" } ], "render": { @@ -264,4 +359,4 @@ "accepts_debit_cards", "accepts_credit_cards" ] -} +} \ No newline at end of file diff --git a/assets/layers/ghost_bike/ghost_bike.json b/assets/layers/ghost_bike/ghost_bike.json index f9b8c1ab7..71ec9261f 100644 --- a/assets/layers/ghost_bike/ghost_bike.json +++ b/assets/layers/ghost_bike/ghost_bike.json @@ -186,14 +186,20 @@ "ca": "En quina pàgina web es pot trobar més informació sobre la bicicleta blanca o l'accident?" }, "render": { - "en": "More info available", - "nl": "Meer informatie", - "de": "Mehr Informationen", - "it": "Sono disponibili ulteriori informazioni", - "ru": "Доступна более подробная информация", - "fr": "Plus d'informations sont disponibles", - "id": "Informasi lanjut tersedia", - "ca": "Més informació disponible" + "special": { + "type": "link", + "href": "{source}", + "text": { + "en": "More info available", + "nl": "Meer informatie", + "de": "Mehr Informationen", + "it": "Sono disponibili ulteriori informazioni", + "ru": "Доступна более подробная информация", + "fr": "Plus d'informations sont disponibles", + "id": "Informasi lanjut tersedia", + "ca": "Més informació disponible" + } + } }, "freeform": { "type": "url", diff --git a/assets/layers/icons/icons.json b/assets/layers/icons/icons.json index c5633b74a..f3b781152 100644 --- a/assets/layers/icons/icons.json +++ b/assets/layers/icons/icons.json @@ -12,7 +12,7 @@ "labels": [ "defaults" ], - "render": "Wikipedia", + "render": "Wikipedia", "condition": { "or": [ "wikipedia~*", @@ -23,7 +23,7 @@ { "#": "ignore-image-in-then", "if": "wikipedia=", - "then": "WD" + "then": "WD" } ] }, @@ -106,7 +106,7 @@ "labels": [ "defaults" ], - "render": "website", + "render": "website", "condition": "website~*" }, { @@ -140,7 +140,7 @@ "labels": [ "defaults" ], - "render": "on osm", + "render": "on osm", "mappings": [ { "if": "id~.*/-.*", @@ -149,7 +149,7 @@ { "#": "ignore-image-in-then", "if": "_backend~*", - "then": "" + "then": "" } ], "condition": "id~(node|way|relation)/[0-9]*" diff --git a/assets/layers/nature_reserve/nature_reserve.json b/assets/layers/nature_reserve/nature_reserve.json index f8c555c55..7e9ee0669 100644 --- a/assets/layers/nature_reserve/nature_reserve.json +++ b/assets/layers/nature_reserve/nature_reserve.json @@ -360,14 +360,7 @@ "ca": "A quina adreça de correu electrònic es pot enviar amb preguntes i problemes amb aquest parc natural?" }, "render": { - "nl": "{email}", - "en": "{email}", - "ca": "{email}", - "de": "{email}", - "fr": "{email}", - "it": "{email}", - "ru": "{email}", - "id": "{email}" + "*": "{email}" }, "freeform": { "key": "email", @@ -393,7 +386,7 @@ "ca": "A quin número de telèfon es pot trucar amb preguntes i problemes amb aquest parc natural?" }, "render": { - "*": "{phone}" + "*": "{phone}" }, "freeform": { "key": "phone", diff --git a/assets/layers/public_bookcase/public_bookcase.json b/assets/layers/public_bookcase/public_bookcase.json index 5ab231642..835a99e0a 100644 --- a/assets/layers/public_bookcase/public_bookcase.json +++ b/assets/layers/public_bookcase/public_bookcase.json @@ -439,13 +439,19 @@ }, { "render": { - "en": "More info on the website", - "nl": "Meer info op de website", - "de": "Weitere Informationen auf der Webseite", - "fr": "Plus d'infos sur le site web", - "ru": "Более подробная информация на сайте", - "it": "Maggiori informazioni sul sito web", - "hu": "További információ ezen a weboldalon" + "special": { + "type": "link", + "href": "{website}", + "text": { + "en": "More info on the website", + "nl": "Meer info op de website", + "de": "Weitere Informationen auf der Webseite", + "fr": "Plus d'infos sur le site web", + "ru": "Более подробная информация на сайте", + "it": "Maggiori informazioni sul sito web", + "hu": "További információ ezen a weboldalon" + } + } }, "question": { "en": "Is there a website with more information about this public bookcase?", diff --git a/assets/layers/questions/denominations/chf/1000chf.svg b/assets/layers/questions/denominations/chf/1000chf.svg new file mode 100644 index 000000000..620e2802a --- /dev/null +++ b/assets/layers/questions/denominations/chf/1000chf.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/layers/questions/denominations/chf/1000chf.svg.license b/assets/layers/questions/denominations/chf/1000chf.svg.license new file mode 100644 index 000000000..75299f884 --- /dev/null +++ b/assets/layers/questions/denominations/chf/1000chf.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Robin van der Linde +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/100chf.svg b/assets/layers/questions/denominations/chf/100chf.svg new file mode 100644 index 000000000..04148d015 --- /dev/null +++ b/assets/layers/questions/denominations/chf/100chf.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/layers/questions/denominations/chf/100chf.svg.license b/assets/layers/questions/denominations/chf/100chf.svg.license new file mode 100644 index 000000000..75299f884 --- /dev/null +++ b/assets/layers/questions/denominations/chf/100chf.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Robin van der Linde +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/10chf.svg b/assets/layers/questions/denominations/chf/10chf.svg new file mode 100644 index 000000000..fe020f3eb --- /dev/null +++ b/assets/layers/questions/denominations/chf/10chf.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/layers/questions/denominations/chf/10chf.svg.license b/assets/layers/questions/denominations/chf/10chf.svg.license new file mode 100644 index 000000000..75299f884 --- /dev/null +++ b/assets/layers/questions/denominations/chf/10chf.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Robin van der Linde +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/10rp-2019-800px.png b/assets/layers/questions/denominations/chf/10rp-2019-800px.png new file mode 100644 index 000000000..31b93b638 Binary files /dev/null and b/assets/layers/questions/denominations/chf/10rp-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/10rp-2019-800px.png.license b/assets/layers/questions/denominations/chf/10rp-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/10rp-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/1fr-2019-800px.png b/assets/layers/questions/denominations/chf/1fr-2019-800px.png new file mode 100644 index 000000000..d9d33e5bf Binary files /dev/null and b/assets/layers/questions/denominations/chf/1fr-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/1fr-2019-800px.png.license b/assets/layers/questions/denominations/chf/1fr-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/1fr-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/200chf.svg b/assets/layers/questions/denominations/chf/200chf.svg new file mode 100644 index 000000000..2f40ca8b3 --- /dev/null +++ b/assets/layers/questions/denominations/chf/200chf.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/layers/questions/denominations/chf/200chf.svg.license b/assets/layers/questions/denominations/chf/200chf.svg.license new file mode 100644 index 000000000..75299f884 --- /dev/null +++ b/assets/layers/questions/denominations/chf/200chf.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Robin van der Linde +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/20chf.svg b/assets/layers/questions/denominations/chf/20chf.svg new file mode 100644 index 000000000..9ee919393 --- /dev/null +++ b/assets/layers/questions/denominations/chf/20chf.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/layers/questions/denominations/chf/20chf.svg.license b/assets/layers/questions/denominations/chf/20chf.svg.license new file mode 100644 index 000000000..75299f884 --- /dev/null +++ b/assets/layers/questions/denominations/chf/20chf.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Robin van der Linde +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/20rp-2019-800px.png b/assets/layers/questions/denominations/chf/20rp-2019-800px.png new file mode 100644 index 000000000..20317c011 Binary files /dev/null and b/assets/layers/questions/denominations/chf/20rp-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/20rp-2019-800px.png.license b/assets/layers/questions/denominations/chf/20rp-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/20rp-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/2fr-2019-800px.png b/assets/layers/questions/denominations/chf/2fr-2019-800px.png new file mode 100644 index 000000000..728c5deba Binary files /dev/null and b/assets/layers/questions/denominations/chf/2fr-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/2fr-2019-800px.png.license b/assets/layers/questions/denominations/chf/2fr-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/2fr-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/50chf.svg b/assets/layers/questions/denominations/chf/50chf.svg new file mode 100644 index 000000000..24d62bbeb --- /dev/null +++ b/assets/layers/questions/denominations/chf/50chf.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/layers/questions/denominations/chf/50chf.svg.license b/assets/layers/questions/denominations/chf/50chf.svg.license new file mode 100644 index 000000000..75299f884 --- /dev/null +++ b/assets/layers/questions/denominations/chf/50chf.svg.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Robin van der Linde +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/50rp-2019-800px.png b/assets/layers/questions/denominations/chf/50rp-2019-800px.png new file mode 100644 index 000000000..f1cd3f7aa Binary files /dev/null and b/assets/layers/questions/denominations/chf/50rp-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/50rp-2019-800px.png.license b/assets/layers/questions/denominations/chf/50rp-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/50rp-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/5fr-2019-800px.png b/assets/layers/questions/denominations/chf/5fr-2019-800px.png new file mode 100644 index 000000000..1b52e2273 Binary files /dev/null and b/assets/layers/questions/denominations/chf/5fr-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/5fr-2019-800px.png.license b/assets/layers/questions/denominations/chf/5fr-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/5fr-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/5rp-2019-800px.png b/assets/layers/questions/denominations/chf/5rp-2019-800px.png new file mode 100644 index 000000000..915926a68 Binary files /dev/null and b/assets/layers/questions/denominations/chf/5rp-2019-800px.png differ diff --git a/assets/layers/questions/denominations/chf/5rp-2019-800px.png.license b/assets/layers/questions/denominations/chf/5rp-2019-800px.png.license new file mode 100644 index 000000000..17bb1c167 --- /dev/null +++ b/assets/layers/questions/denominations/chf/5rp-2019-800px.png.license @@ -0,0 +1,2 @@ +SPDX-FileCopyrightText: Swissmint +SPDX-License-Identifier: CC0-1.0 \ No newline at end of file diff --git a/assets/layers/questions/denominations/chf/license_info.json b/assets/layers/questions/denominations/chf/license_info.json new file mode 100644 index 000000000..c3119f7fb --- /dev/null +++ b/assets/layers/questions/denominations/chf/license_info.json @@ -0,0 +1,120 @@ +[ + { + "path": "1000chf.svg", + "license": "CC0-1.0", + "authors": [ + "Robin van der Linde" + ], + "sources": [] + }, + { + "path": "100chf.svg", + "license": "CC0-1.0", + "authors": [ + "Robin van der Linde" + ], + "sources": [] + }, + { + "path": "10chf.svg", + "license": "CC0-1.0", + "authors": [ + "Robin van der Linde" + ], + "sources": [] + }, + { + "path": "10rp-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + }, + { + "path": "1fr-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + }, + { + "path": "200chf.svg", + "license": "CC0-1.0", + "authors": [ + "Robin van der Linde" + ], + "sources": [] + }, + { + "path": "20chf.svg", + "license": "CC0-1.0", + "authors": [ + "Robin van der Linde" + ], + "sources": [] + }, + { + "path": "20rp-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + }, + { + "path": "2fr-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + }, + { + "path": "50chf.svg", + "license": "CC0-1.0", + "authors": [ + "Robin van der Linde" + ], + "sources": [] + }, + { + "path": "50rp-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + }, + { + "path": "5fr-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + }, + { + "path": "5rp-2019-800px.png", + "license": "CC0-1.0", + "authors": [ + "Swissmint" + ], + "sources": [ + "https://www.swissmint.ch/swissmint/de/home/dokumentation/bildgalerie/umlaufmuenzen-bildgalerie.html" + ] + } +] \ No newline at end of file diff --git a/assets/layers/questions/100euro.svg b/assets/layers/questions/denominations/eur/100euro.svg similarity index 100% rename from assets/layers/questions/100euro.svg rename to assets/layers/questions/denominations/eur/100euro.svg diff --git a/assets/layers/questions/100euro.svg.license b/assets/layers/questions/denominations/eur/100euro.svg.license similarity index 100% rename from assets/layers/questions/100euro.svg.license rename to assets/layers/questions/denominations/eur/100euro.svg.license diff --git a/assets/layers/questions/10cent.svg b/assets/layers/questions/denominations/eur/10cent.svg similarity index 100% rename from assets/layers/questions/10cent.svg rename to assets/layers/questions/denominations/eur/10cent.svg diff --git a/assets/layers/questions/10cent.svg.license b/assets/layers/questions/denominations/eur/10cent.svg.license similarity index 100% rename from assets/layers/questions/10cent.svg.license rename to assets/layers/questions/denominations/eur/10cent.svg.license diff --git a/assets/layers/questions/10euro.svg b/assets/layers/questions/denominations/eur/10euro.svg similarity index 100% rename from assets/layers/questions/10euro.svg rename to assets/layers/questions/denominations/eur/10euro.svg diff --git a/assets/layers/questions/10euro.svg.license b/assets/layers/questions/denominations/eur/10euro.svg.license similarity index 100% rename from assets/layers/questions/10euro.svg.license rename to assets/layers/questions/denominations/eur/10euro.svg.license diff --git a/assets/layers/questions/1cent.svg b/assets/layers/questions/denominations/eur/1cent.svg similarity index 100% rename from assets/layers/questions/1cent.svg rename to assets/layers/questions/denominations/eur/1cent.svg diff --git a/assets/layers/questions/1cent.svg.license b/assets/layers/questions/denominations/eur/1cent.svg.license similarity index 100% rename from assets/layers/questions/1cent.svg.license rename to assets/layers/questions/denominations/eur/1cent.svg.license diff --git a/assets/layers/questions/1euro.svg b/assets/layers/questions/denominations/eur/1euro.svg similarity index 100% rename from assets/layers/questions/1euro.svg rename to assets/layers/questions/denominations/eur/1euro.svg diff --git a/assets/layers/questions/1euro.svg.license b/assets/layers/questions/denominations/eur/1euro.svg.license similarity index 100% rename from assets/layers/questions/1euro.svg.license rename to assets/layers/questions/denominations/eur/1euro.svg.license diff --git a/assets/layers/questions/200euro.svg b/assets/layers/questions/denominations/eur/200euro.svg similarity index 100% rename from assets/layers/questions/200euro.svg rename to assets/layers/questions/denominations/eur/200euro.svg diff --git a/assets/layers/questions/200euro.svg.license b/assets/layers/questions/denominations/eur/200euro.svg.license similarity index 100% rename from assets/layers/questions/200euro.svg.license rename to assets/layers/questions/denominations/eur/200euro.svg.license diff --git a/assets/layers/questions/20cent.svg b/assets/layers/questions/denominations/eur/20cent.svg similarity index 100% rename from assets/layers/questions/20cent.svg rename to assets/layers/questions/denominations/eur/20cent.svg diff --git a/assets/layers/questions/20cent.svg.license b/assets/layers/questions/denominations/eur/20cent.svg.license similarity index 100% rename from assets/layers/questions/20cent.svg.license rename to assets/layers/questions/denominations/eur/20cent.svg.license diff --git a/assets/layers/questions/20euro.svg b/assets/layers/questions/denominations/eur/20euro.svg similarity index 100% rename from assets/layers/questions/20euro.svg rename to assets/layers/questions/denominations/eur/20euro.svg diff --git a/assets/layers/questions/20euro.svg.license b/assets/layers/questions/denominations/eur/20euro.svg.license similarity index 100% rename from assets/layers/questions/20euro.svg.license rename to assets/layers/questions/denominations/eur/20euro.svg.license diff --git a/assets/layers/questions/2cent.svg b/assets/layers/questions/denominations/eur/2cent.svg similarity index 100% rename from assets/layers/questions/2cent.svg rename to assets/layers/questions/denominations/eur/2cent.svg diff --git a/assets/layers/questions/2cent.svg.license b/assets/layers/questions/denominations/eur/2cent.svg.license similarity index 100% rename from assets/layers/questions/2cent.svg.license rename to assets/layers/questions/denominations/eur/2cent.svg.license diff --git a/assets/layers/questions/2euro.svg b/assets/layers/questions/denominations/eur/2euro.svg similarity index 100% rename from assets/layers/questions/2euro.svg rename to assets/layers/questions/denominations/eur/2euro.svg diff --git a/assets/layers/questions/2euro.svg.license b/assets/layers/questions/denominations/eur/2euro.svg.license similarity index 100% rename from assets/layers/questions/2euro.svg.license rename to assets/layers/questions/denominations/eur/2euro.svg.license diff --git a/assets/layers/questions/500euro.svg b/assets/layers/questions/denominations/eur/500euro.svg similarity index 100% rename from assets/layers/questions/500euro.svg rename to assets/layers/questions/denominations/eur/500euro.svg diff --git a/assets/layers/questions/500euro.svg.license b/assets/layers/questions/denominations/eur/500euro.svg.license similarity index 100% rename from assets/layers/questions/500euro.svg.license rename to assets/layers/questions/denominations/eur/500euro.svg.license diff --git a/assets/layers/questions/50cent.svg b/assets/layers/questions/denominations/eur/50cent.svg similarity index 100% rename from assets/layers/questions/50cent.svg rename to assets/layers/questions/denominations/eur/50cent.svg diff --git a/assets/layers/questions/50cent.svg.license b/assets/layers/questions/denominations/eur/50cent.svg.license similarity index 100% rename from assets/layers/questions/50cent.svg.license rename to assets/layers/questions/denominations/eur/50cent.svg.license diff --git a/assets/layers/questions/50euro.svg b/assets/layers/questions/denominations/eur/50euro.svg similarity index 100% rename from assets/layers/questions/50euro.svg rename to assets/layers/questions/denominations/eur/50euro.svg diff --git a/assets/layers/questions/50euro.svg.license b/assets/layers/questions/denominations/eur/50euro.svg.license similarity index 100% rename from assets/layers/questions/50euro.svg.license rename to assets/layers/questions/denominations/eur/50euro.svg.license diff --git a/assets/layers/questions/5cent.svg b/assets/layers/questions/denominations/eur/5cent.svg similarity index 100% rename from assets/layers/questions/5cent.svg rename to assets/layers/questions/denominations/eur/5cent.svg diff --git a/assets/layers/questions/5cent.svg.license b/assets/layers/questions/denominations/eur/5cent.svg.license similarity index 100% rename from assets/layers/questions/5cent.svg.license rename to assets/layers/questions/denominations/eur/5cent.svg.license diff --git a/assets/layers/questions/5euro.svg b/assets/layers/questions/denominations/eur/5euro.svg similarity index 100% rename from assets/layers/questions/5euro.svg rename to assets/layers/questions/denominations/eur/5euro.svg diff --git a/assets/layers/questions/5euro.svg.license b/assets/layers/questions/denominations/eur/5euro.svg.license similarity index 100% rename from assets/layers/questions/5euro.svg.license rename to assets/layers/questions/denominations/eur/5euro.svg.license diff --git a/assets/layers/questions/denominations/eur/license_info.json b/assets/layers/questions/denominations/eur/license_info.json new file mode 100644 index 000000000..257617556 --- /dev/null +++ b/assets/layers/questions/denominations/eur/license_info.json @@ -0,0 +1,167 @@ +[ + { + "path": "100euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311346/worksheet-100-euro-coloured" + ] + }, + { + "path": "10cent.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311337/worksheet-10-cent-coloured" + ] + }, + { + "path": "10euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311343/worksheet-10-euro-coloured" + ] + }, + { + "path": "1cent.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311334/worksheet-1-cent-coloured" + ] + }, + { + "path": "1euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311340/worksheet-1-euro-coloured" + ] + }, + { + "path": "200euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311347/worksheet-200-euro-coloured" + ] + }, + { + "path": "20cent.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311338/worksheet-20-cent-coloured" + ] + }, + { + "path": "20euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311344/worksheet-20-euro-coloured" + ] + }, + { + "path": "2cent.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311335/worksheet-2-cent-coloured" + ] + }, + { + "path": "2euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311341/worksheet-2-euro-coloured" + ] + }, + { + "path": "500euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311348/worksheet-500-euro-coloured" + ] + }, + { + "path": "50cent.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311339/worksheet-50-cent-coloured" + ] + }, + { + "path": "50euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311345/worksheet-50-euro-coloured" + ] + }, + { + "path": "5cent.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311336/worksheet-5-cent-coloured" + ] + }, + { + "path": "5euro.svg", + "license": "CC0-1.0", + "authors": [ + "OpenClipart", + "frankes" + ], + "sources": [ + "https://openclipart.org/detail/311342/worksheet-5-euro-coloured" + ] + } +] \ No newline at end of file diff --git a/assets/layers/questions/license_info.json b/assets/layers/questions/license_info.json index cbc306b77..65a360bb6 100644 --- a/assets/layers/questions/license_info.json +++ b/assets/layers/questions/license_info.json @@ -1,169 +1,4 @@ [ - { - "path": "100euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311346/worksheet-100-euro-coloured" - ] - }, - { - "path": "10cent.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311337/worksheet-10-cent-coloured" - ] - }, - { - "path": "10euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311343/worksheet-10-euro-coloured" - ] - }, - { - "path": "1cent.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311334/worksheet-1-cent-coloured" - ] - }, - { - "path": "1euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311340/worksheet-1-euro-coloured" - ] - }, - { - "path": "200euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311347/worksheet-200-euro-coloured" - ] - }, - { - "path": "20cent.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311338/worksheet-20-cent-coloured" - ] - }, - { - "path": "20euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311344/worksheet-20-euro-coloured" - ] - }, - { - "path": "2cent.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311335/worksheet-2-cent-coloured" - ] - }, - { - "path": "2euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311341/worksheet-2-euro-coloured" - ] - }, - { - "path": "500euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311348/worksheet-500-euro-coloured" - ] - }, - { - "path": "50cent.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311339/worksheet-50-cent-coloured" - ] - }, - { - "path": "50euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311345/worksheet-50-euro-coloured" - ] - }, - { - "path": "5cent.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311336/worksheet-5-cent-coloured" - ] - }, - { - "path": "5euro.svg", - "license": "CC0-1.0", - "authors": [ - "OpenClipart", - "frankes" - ], - "sources": [ - "https://openclipart.org/detail/311342/worksheet-5-euro-coloured" - ] - }, { "path": "audio_induction_loop.svg", "license": "CC-BY-4.0", diff --git a/assets/layers/questions/questions.json b/assets/layers/questions/questions.json index 7dfd898d4..2edf689d7 100644 --- a/assets/layers/questions/questions.json +++ b/assets/layers/questions/questions.json @@ -15,7 +15,7 @@ "id": "images", "description": "This block shows the known images which are linked with the `image`-keys, but also via `mapillary` and `wikidata` and shows the button to upload new images", "render": { - "*": "{image_carousel()}{image_upload()}" + "*": "{image_carousel()}{image_upload()}{nearby_images()}" } }, { @@ -209,7 +209,7 @@ { "id": "osmlink", "render": { - "*": "" + "*": "" }, "mappings": [ { @@ -221,7 +221,7 @@ { "id": "email", "render": { - "*": "{email}" + "*": "{email}" }, "icon": "./assets/svg/envelope.svg", "labels": [ @@ -256,7 +256,7 @@ { "if": "contact:email~*", "icon": "./assets/svg/envelope.svg", - "then": "{contact:email}", + "then": "{contact:email}", "hideInAnswer": true } ], @@ -1127,7 +1127,8 @@ }, { "or": [ - "_currency=EUR" + "_currency~.*EUR.*", + "_currency~.*CHF.*" ] } ] @@ -1147,7 +1148,7 @@ "mappings": [ { "if": "payment:coins:denominations=0.01 EUR", - "icon": "./assets/layers/questions/1cent.svg", + "icon": "./assets/layers/questions/denominations/eur/1cent.svg", "then": { "en": "1 cent coins are accepted", "de": "1-Cent-Münzen werden akzeptiert", @@ -1164,7 +1165,7 @@ }, { "if": "payment:coins:denominations=0.02 EUR", - "icon": "./assets/layers/questions/2cent.svg", + "icon": "./assets/layers/questions/denominations/eur/2cent.svg", "then": { "en": "2 cent coins are accepted", "de": "2-Cent-Münzen werden akzeptiert", @@ -1181,7 +1182,7 @@ }, { "if": "payment:coins:denominations=0.05 EUR", - "icon": "./assets/layers/questions/5cent.svg", + "icon": "./assets/layers/questions/denominations/eur/5cent.svg", "then": { "en": "5 cent coins are accepted", "de": "5-Cent-Münzen werden akzeptiert", @@ -1198,7 +1199,7 @@ }, { "if": "payment:coins:denominations=0.10 EUR", - "icon": "./assets/layers/questions/10cent.svg", + "icon": "./assets/layers/questions/denominations/eur/10cent.svg", "then": { "en": "10 cent coins are accepted", "de": "10-Cent-Münzen werden akzeptiert", @@ -1215,7 +1216,7 @@ }, { "if": "payment:coins:denominations=0.20 EUR", - "icon": "./assets/layers/questions/20cent.svg", + "icon": "./assets/layers/questions/denominations/eur/20cent.svg", "then": { "en": "20 cent coins are accepted", "de": "20-Cent-Münzen werden akzeptiert", @@ -1232,7 +1233,7 @@ }, { "if": "payment:coins:denominations=0.50 EUR", - "icon": "./assets/layers/questions/50cent.svg", + "icon": "./assets/layers/questions/denominations/eur/50cent.svg", "then": { "en": "50 cent coins are accepted", "de": "50-Cent-Münzen werden akzeptiert", @@ -1249,7 +1250,7 @@ }, { "if": "payment:coins:denominations=1 EUR", - "icon": "./assets/layers/questions/1euro.svg", + "icon": "./assets/layers/questions/denominations/eur/1euro.svg", "then": { "en": "1 euro coins are accepted", "de": "1-Euro-Münzen werden akzeptiert", @@ -1265,7 +1266,7 @@ }, { "if": "payment:coins:denominations=2 EUR", - "icon": "./assets/layers/questions/2euro.svg", + "icon": "./assets/layers/questions/denominations/eur/2euro.svg", "then": { "en": "2 euro coins are accepted", "de": "2-Euro-Münzen werden akzeptiert", @@ -1278,6 +1279,69 @@ "cs": "Jsou přijímány mince v hodnotě 2 euro" }, "hideInAnswer": "_currency!~.*EUR.*" + }, + { + "if": "payment:coins:denominations=0.05 CHF", + "icon": "./assets/layers/questions/denominations/chf/5rp-2019-800px.png", + "then": { + "en": "5 centimes coins are accepted", + "nl": "Munten van 5 rappen worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:coins:denominations=0.10 CHF", + "icon": "./assets/layers/questions/denominations/chf/10rp-2019-800px.png", + "then": { + "en": "10 centimes coins are accepted", + "nl": "Munten van 10 rappen worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:coins:denominations=0.20 CHF", + "icon": "./assets/layers/questions/denominations/chf/20rp-2019-800px.png", + "then": { + "en": "20 centimes coins are accepted", + "nl": "Munten van 20 rappen worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:coins:denominations=0.50 CHF", + "icon": "./assets/layers/questions/denominations/chf/50rp-2019-800px.png", + "then": { + "en": "½ franc coins are accepted", + "nl": "Munten van ½ frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:coins:denominations=1 CHF", + "icon": "./assets/layers/questions/denominations/chf/1fr-2019-800px.png", + "then": { + "en": "1 franc coins are accepted", + "nl": "Munten van 1 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:coins:denominations=2 CHF", + "icon": "./assets/layers/questions/denominations/chf/2fr-2019-800px.png", + "then": { + "en": "2 francs coins are accepted", + "nl": "Munten van 2 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:coins:denominations=5 CHF", + "icon": "./assets/layers/questions/denominations/chf/5fr-2019-800px.png", + "then": { + "en": "5 francs coins are accepted", + "nl": "Munten van 5 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" } ] }, @@ -1293,7 +1357,8 @@ }, { "or": [ - "_currency=EUR" + "_currency~.*EUR.*", + "_currency~.*CHF.*" ] } ] @@ -1312,7 +1377,7 @@ "mappings": [ { "if": "payment:notes:denominations=5 EUR", - "icon": "./assets/layers/questions/5euro.svg", + "icon": "./assets/layers/questions/denominations/eur/5euro.svg", "then": { "en": "5 euro notes are accepted", "nl": "Biljetten van 5 euro worden geaccepteerd", @@ -1327,7 +1392,7 @@ }, { "if": "payment:notes:denominations=10 EUR", - "icon": "./assets/layers/questions/10euro.svg", + "icon": "./assets/layers/questions/denominations/eur/10euro.svg", "then": { "en": "10 euro notes are accepted", "nl": "Biljetten van 10 euro worden geaccepteerd", @@ -1342,7 +1407,7 @@ }, { "if": "payment:notes:denominations=20 EUR", - "icon": "./assets/layers/questions/20euro.svg", + "icon": "./assets/layers/questions/denominations/eur/20euro.svg", "then": { "en": "20 euro notes are accepted", "nl": "Biljetten van 20 euro worden geaccepteerd", @@ -1357,7 +1422,7 @@ }, { "if": "payment:notes:denominations=50 EUR", - "icon": "./assets/layers/questions/50euro.svg", + "icon": "./assets/layers/questions/denominations/eur/50euro.svg", "then": { "en": "50 euro notes are accepted", "nl": "Biljetten van 50 euro worden geaccepteerd", @@ -1372,7 +1437,7 @@ }, { "if": "payment:notes:denominations=100 EUR", - "icon": "./assets/layers/questions/100euro.svg", + "icon": "./assets/layers/questions/denominations/eur/100euro.svg", "then": { "en": "100 euro notes are accepted", "nl": "Biljetten van 100 euro worden geaccepteerd", @@ -1387,7 +1452,7 @@ }, { "if": "payment:notes:denominations=200 EUR", - "icon": "./assets/layers/questions/200euro.svg", + "icon": "./assets/layers/questions/denominations/eur/200euro.svg", "then": { "en": "200 euro notes are accepted", "nl": "Biljetten van 200 euro worden geaccepteerd", @@ -1402,7 +1467,7 @@ }, { "if": "payment:notes:denominations=500 EUR", - "icon": "./assets/layers/questions/500euro.svg", + "icon": "./assets/layers/questions/denominations/eur/500euro.svg", "then": { "en": "500 euro notes are accepted", "nl": "Biljetten van 500 euro worden geaccepteerd", @@ -1414,6 +1479,60 @@ "fr": "Les billets de 500 euros sont acceptés" }, "hideInAnswer": "_currency!~.*EUR.*" + }, + { + "if": "payment:notes:denominations=10 CHF", + "icon": "./assets/layers/questions/denominations/chf/10chf.svg", + "then": { + "en": "10 francs notes are accepted", + "nl": "Biljetten van 10 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:notes:denominations=20 CHF", + "icon": "./assets/layers/questions/denominations/chf/20chf.svg", + "then": { + "en": "20 francs notes are accepted", + "nl": "Biljetten van 20 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:notes:denominations=50 CHF", + "icon": "./assets/layers/questions/denominations/chf/50chf.svg", + "then": { + "en": "50 francs notes are accepted", + "nl": "Biljetten van 50 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:notes:denominations=100 CHF", + "icon": "./assets/layers/questions/denominations/chf/100chf.svg", + "then": { + "en": "100 francs notes are accepted", + "nl": "Biljetten van 100 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:notes:denominations=200 CHF", + "icon": "./assets/layers/questions/denominations/chf/200chf.svg", + "then": { + "en": "200 francs notes are accepted", + "nl": "Biljetten van 200 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" + }, + { + "if": "payment:notes:denominations=1000 CHF", + "icon": "./assets/layers/questions/denominations/chf/1000chf.svg", + "then": { + "en": "1000 francs notes are accepted", + "nl": "Biljetten van 1000 frank worden geaccepteerd" + }, + "hideInAnswer": "_currency!~.*CHF.*" } ] }, diff --git a/assets/layers/sport_pitch/sport_pitch.json b/assets/layers/sport_pitch/sport_pitch.json index 8ad88f522..900547099 100644 --- a/assets/layers/sport_pitch/sport_pitch.json +++ b/assets/layers/sport_pitch/sport_pitch.json @@ -491,7 +491,7 @@ "key": "email", "type": "email" }, - "render": "{email}", + "render": "{email}", "id": "sport_pitch-email" }, { diff --git a/assets/layers/usersettings/usersettings.json b/assets/layers/usersettings/usersettings.json index 49db41c52..cd7445107 100644 --- a/assets/layers/usersettings/usersettings.json +++ b/assets/layers/usersettings/usersettings.json @@ -407,7 +407,7 @@ "special": { "type": "multi", "key": "_translation_links", - "tagrendering": "Translate entries of {id}" + "tagrendering": "Translate entries of {id}" } } }, @@ -417,20 +417,20 @@ { "if": "_mastodon_link~*", "then": { - "en": "A link to your Mastodon-profile has been been found: {_mastodon_link}", - "de": "Es wurde ein Link zu deinem Mastodon-Profil gefunden: {_mastodon_link}", - "nl": "Een link naar je Mastodon-profiel werd gevonden: {_mastodon_link}", - "fr": "Un lien vers votre profil Mastodon a été trouvé : {_mastodon_link}", - "ca": "S'ha trobat un enllaç al vostre perfil de Mastodon: {_mastodon_link}" + "en": "A link to your Mastodon-profile has been been found: {_mastodon_link}", + "de": "Es wurde ein Link zu deinem Mastodon-Profil gefunden: {_mastodon_link}", + "nl": "Een link naar je Mastodon-profiel werd gevonden: {_mastodon_link}", + "fr": "Un lien vers votre profil Mastodon a été trouvé : {_mastodon_link}", + "ca": "S'ha trobat un enllaç al vostre perfil de Mastodon: {_mastodon_link}" }, "icon": "mastodon" }, { "if": "_mastodon_candidate~*", "then": { - "en": "We found a link to what looks to be a mastodon account, but it is unverified. Edit your profile description and place the following there: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", - "de": "Wir haben einen Link gefunden, der aussieht wie ein Mastodon-Konto, aber nicht verifiziert ist. Bearbeiten Sie Ihre Profilbeschreibung und fügen Sie dort Folgendes ein: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", - "nl": "Je profielbeschrijving bevat een link die vermoedelijk naar je Mastodon gaat, maar deze link is niet verifieerdbaar voor Mastodon.Pas je profielbeschrijving aan en plaats er de volgende code: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" + "en": "We found a link to what looks to be a mastodon account, but it is unverified. Edit your profile description and place the following there: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", + "de": "Wir haben einen Link gefunden, der aussieht wie ein Mastodon-Konto, aber nicht verifiziert ist. Bearbeiten Sie Ihre Profilbeschreibung und fügen Sie dort Folgendes ein: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>", + "nl": "Je profielbeschrijving bevat een link die vermoedelijk naar je Mastodon gaat, maar deze link is niet verifieerdbaar voor Mastodon.Pas je profielbeschrijving aan en plaats er de volgende code: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" }, "icon": "invalid" } diff --git a/assets/themes/climbing/climbing.json b/assets/themes/climbing/climbing.json index 25549a313..7e1072246 100644 --- a/assets/themes/climbing/climbing.json +++ b/assets/themes/climbing/climbing.json @@ -460,7 +460,8 @@ } ] } - } + }, + "drinking_water", "toilet" ], "credits": "Christian Neumann " } diff --git a/land.html b/land.html index cd155ea56..a9fd46b34 100644 --- a/land.html +++ b/land.html @@ -2,9 +2,6 @@ MapComplete Auth - + diff --git a/langs/ca.json b/langs/ca.json index fa2280cd2..772d01878 100644 --- a/langs/ca.json +++ b/langs/ca.json @@ -405,20 +405,6 @@ "doDelete": "Esborrar imatge", "dontDelete": "Cancel·lar", "isDeleted": "Esborrada", - "nearbyPictures": { - "allFiltered": "No hi ha cap imatge que coincideixi amb el vostre filtre", - "browseNearby": "Cerca imatges properes…", - "confirm": "La imatge seleccionada mostra {title()}", - "hasMatchingPicture": "Una imatge coincideix amb l'objecte? Seleccioneu-lo a continuació", - "loadMore": "Carrega més imatges", - "loading": "Carregant imatges properes…", - "noImageSelected": "Seleccioneu una imatge per enllaçar-la a l'objecte", - "nothingFound": "No s'han trobat imatges properes…", - "onlyTowards": "Mostra només les imatges fetes cap a aquest objecte", - "removeFilters": "Feu clic aquí per eliminar els filtres", - "title": "Imatges properes", - "withinRadius": "Mostra només les imatges que s'han fet a {radius} metres d'aquest objecte" - }, "pleaseLogin": "Entrar per pujar una foto", "respectPrivacy": "Respecta la privacitat. No fotografiïs gent o matrícules. No facis servir imatges de Google Maps, Google Streetview o altres fonts amb copyright.", "toBig": "La teva imatge és massa gran ara que medeix {actual_size}. Usa imatges de com a molt {max_size}", diff --git a/langs/cs.json b/langs/cs.json index 4ae073795..e5229e6b9 100644 --- a/langs/cs.json +++ b/langs/cs.json @@ -357,20 +357,6 @@ "doDelete": "Odebrat obrázek", "dontDelete": "Zrušit", "isDeleted": "Smazáno", - "nearbyPictures": { - "allFiltered": "Filtru neodpovídají žádné obrázky", - "browseNearby": "Procházet obrázky z okolí…", - "confirm": "Na vybraném obrázku je vidět {title()}", - "hasMatchingPicture": "Odpovídá obrázek objektu? Vyberte jej níže", - "loadMore": "Načíst další obrázky", - "loading": "Načítání obrázků z okolí…", - "noImageSelected": "Výběrem obrázku jej propojíte s objektem", - "nothingFound": "V okolí nebyly nalezeny žádné obrázky…", - "onlyTowards": "Zobrazit pouze fotky pořízené směrem k tomuto objektu", - "removeFilters": "Kliknutím sem odstraníte filtry", - "title": "Obrázky v okolí", - "withinRadius": "Zobrazit pouze fotky pořízené v okruhu {radius} metrů kolem tohoto objektu" - }, "pleaseLogin": "Pro přidání fotky se prosím přihlaste", "respectPrivacy": "Nefotografujte osoby ani poznávací značky. Nevkládejte Mapy Google, Google Streetview ani jiné zdroje chráněné autorskými právy.", "toBig": "Váš obrázek je příliš velký, protože má velikost {actual_size}. Používejte prosím obrázky o maximální velikosti {max_size}", diff --git a/langs/da.json b/langs/da.json index 9b5bf0f24..bca653a48 100644 --- a/langs/da.json +++ b/langs/da.json @@ -257,20 +257,6 @@ "doDelete": "Fjern billede", "dontDelete": "Afbryd", "isDeleted": "Slettet", - "nearbyPictures": { - "allFiltered": "Ingen billeder matchede dit filter", - "browseNearby": "Gennemse billeder i nærheden…", - "confirm": "Det valgte billede viser {title()}", - "hasMatchingPicture": "Passer et billede til objektet? Vælg det nedenfor", - "loadMore": "Indlæs flere billeder", - "loading": "Indlæser billeder i nærheden…", - "noImageSelected": "Vælg et billede for at linke det til objektet", - "nothingFound": "Ingen billeder i nærheden fundet…", - "onlyTowards": "Vis kun billeder, der er taget mod dette objekt", - "removeFilters": "Klik her for at fjerne filtrene", - "title": "Nærliggende billeder", - "withinRadius": "Vis kun billeder, der er taget inden for {radius} meter fra dette objekt" - }, "pleaseLogin": "Log venligst ind for at tilføje et billede", "respectPrivacy": "Tag ikke billeder af mennesker eller nummerplader. Upload ikke Google Maps, Google Streetview, eller fra andre ophavsresbeskyttede kilder.", "toBig": "Dit billede er for stort da det er {actual_size}. Brug venligst billeder, der er højst {max_size}", diff --git a/langs/de.json b/langs/de.json index 4df47808f..f4b2280f8 100644 --- a/langs/de.json +++ b/langs/de.json @@ -405,20 +405,6 @@ "doDelete": "Bild entfernen", "dontDelete": "Abbrechen", "isDeleted": "Gelöscht", - "nearbyPictures": { - "allFiltered": "Keine Bilder passen zu Ihrem Filter", - "browseNearby": "Bilder in der Nähe suchen…", - "confirm": "Das ausgewählte Bild zeigt {title()}", - "hasMatchingPicture": "Passt ein Bild zum Objekt? Wählen Sie es unten aus", - "loadMore": "Weitere Bilder laden", - "loading": "Bilder in der Nähe laden…", - "noImageSelected": "Wählen Sie ein Bild aus, um es mit dem Objekt zu verknüpfen", - "nothingFound": "Keine Bilder in der Nähe gefunden…", - "onlyTowards": "Nur Bilder anzeigen, die in Richtung dieses Objekts aufgenommen wurden", - "removeFilters": "Hier klicken, um die Filter zu entfernen", - "title": "Bilder in der Nähe", - "withinRadius": "Nur Bilder anzeigen, die im Umkreis von {radius} Metern um dieses Objekt aufgenommen wurden" - }, "pleaseLogin": "Bitte anmelden, um ein Bild hinzuzufügen", "respectPrivacy": "Bitte respektieren Sie die Privatsphäre. Fotografieren Sie weder Personen noch Nummernschilder. Benutzen Sie keine urheberrechtlich geschützten Quellen wie z.B. Google Maps oder Google Streetview.", "toBig": "Ihr Bild ist mit {actual_size} zu groß. Die maximale Bildgröße ist {max_size}", diff --git a/langs/en.json b/langs/en.json index 7544255c6..cc9974402 100644 --- a/langs/en.json +++ b/langs/en.json @@ -405,19 +405,10 @@ "doDelete": "Remove image", "dontDelete": "Cancel", "isDeleted": "Deleted", - "nearbyPictures": { - "allFiltered": "No images matched your filter", - "browseNearby": "Browse nearby images…", - "confirm": "The selected image shows {title()}", - "hasMatchingPicture": "Does a picture match the object? Select it below", - "loadMore": "Load more images", - "loading": "Loading nearby images…", - "noImageSelected": "Select an image to link it to the object", - "nothingFound": "No nearby images found…", - "onlyTowards": "Only show pictures which are taken towards this object", - "removeFilters": "Click here to remove the filters", - "title": "Nearby pictures", - "withinRadius": "Only show pictures which are taken within {radius} meter of this object" + "nearby": { + "link": "This picture shows the object", + "seeNearby": "Browse and link nearby pictures", + "title": "Nearby streetview imagery" }, "pleaseLogin": "Please log in to add a picture", "respectPrivacy": "Do not photograph people nor license plates. Do not upload Google Maps, Google Streetview or other copyrighted sources.", diff --git a/langs/eo.json b/langs/eo.json index 67d6e9b08..8b6069896 100644 --- a/langs/eo.json +++ b/langs/eo.json @@ -94,7 +94,6 @@ "image": { "addPicture": "Aldoni bildon", "dontDelete": "Nuligi", - "nearbyPictures": {}, "pleaseLogin": "Bonvolu saluti por aldoni bildon", "uploadingMultiple": "Alŝutante {count} bildojn…", "uploadingPicture": "Alŝutante vian bildon…" diff --git a/langs/es.json b/langs/es.json index ab6e52313..815880080 100644 --- a/langs/es.json +++ b/langs/es.json @@ -310,20 +310,6 @@ "doDelete": "Borrar imagen", "dontDelete": "Cancelar", "isDeleted": "Borrada", - "nearbyPictures": { - "allFiltered": "Ninguna imagen coincide con tu filtro", - "browseNearby": "Buscar imágenes cercanas…", - "confirm": "La imagen seleccionada muestra {title()}", - "hasMatchingPicture": "¿Esta imagen coincide con el objeto? Selecciónalo debajo", - "loadMore": "Cargar más imágenes", - "loading": "Cargando imágenes cercanas…", - "noImageSelected": "Selecciona una imagen para enlazarla al objeto", - "nothingFound": "No se encontraron imágenes cercanas…", - "onlyTowards": "Solo mostrar imágenes que fueron sacadas hacia este objeto", - "removeFilters": "Haz clic aquí para eliminar los filtros", - "title": "Imágenes cercanas", - "withinRadius": "Solo mostrar imágenes que fueran sacadas dentro de un radio de {radius} metros para este objeto" - }, "pleaseLogin": "Acceda para cargar una imagen", "respectPrivacy": "No fotografíe personas ni matrículas. No cargue datos de Google Maps, Google StreetView u otras fuentes protegidas por derechos de autor.", "toBig": "Tu imagen es demasiado grande, ya que pesa {actual_size}. Por favor utiliza imágenes de como máximo {max_size}", diff --git a/langs/fi.json b/langs/fi.json index 4185427de..d0dfdabb2 100644 --- a/langs/fi.json +++ b/langs/fi.json @@ -69,8 +69,7 @@ "addPicture": "Lisää kuva", "doDelete": "Poista kuva", "dontDelete": "Peruuta", - "isDeleted": "Poistettu", - "nearbyPictures": {} + "isDeleted": "Poistettu" }, "importInspector": {}, "importLayer": {}, diff --git a/langs/fil.json b/langs/fil.json index 0705f9d56..a5cdcda2a 100644 --- a/langs/fil.json +++ b/langs/fil.json @@ -79,9 +79,7 @@ "previewbox": {} } }, - "image": { - "nearbyPictures": {} - }, + "image": {}, "importInspector": {}, "importLayer": {}, "index": {}, diff --git a/langs/fr.json b/langs/fr.json index 4e3637481..19c56011b 100644 --- a/langs/fr.json +++ b/langs/fr.json @@ -336,19 +336,6 @@ "doDelete": "Supprimer l'image", "dontDelete": "Annuler", "isDeleted": "Supprimé", - "nearbyPictures": { - "allFiltered": "Aucune image ne correspond à votre filtre", - "browseNearby": "Parcourir les images à proximité…", - "confirm": "L'image sélectionnée représente {title()}", - "hasMatchingPicture": "Est-ce qu'une image correspond à cet objet ? Sélectionnez ci-dessous", - "loadMore": "Charger plus d'images", - "loading": "Chargement des images alentours…", - "noImageSelected": "Sélectionnez une image à lier à l'objet", - "nothingFound": "Aucune image trouvée à proximité…", - "removeFilters": "Cliquez ici pour retirer les filtres", - "title": "Images à proximité", - "withinRadius": "N'afficher que les images prises dans un rayon de {radius} mètres autour de cet objet" - }, "pleaseLogin": "Connectez-vous pour téléverser une photo", "respectPrivacy": "Ne photographiez ni les personnes ni les plaques d'immatriculation. Ne téléversez rien issu de Google Maps, Google Streetview ou d'autre sources soumises à des droits d'auteurs.", "toBig": "Votre image est trop large car elle est de {actual_size}. Veuillez utiliser des images d'au maximum {max_size}", diff --git a/langs/gl.json b/langs/gl.json index ed4dc6c29..23648730b 100644 --- a/langs/gl.json +++ b/langs/gl.json @@ -138,7 +138,6 @@ "doDelete": "Eliminar imaxe", "dontDelete": "Cancelar", "isDeleted": "Eliminada", - "nearbyPictures": {}, "pleaseLogin": "Inicia a sesión para subir unha imaxe", "respectPrivacy": "Respecta a privacidade. Non fotografes xente ou matrículas", "uploadDone": "A túa imaxe foi engadida. Grazas por axudar.", diff --git a/langs/hu.json b/langs/hu.json index fe39a38f8..de4faf548 100644 --- a/langs/hu.json +++ b/langs/hu.json @@ -242,7 +242,6 @@ "doDelete": "Kép eltávolítása", "dontDelete": "Mégse", "isDeleted": "Törölve", - "nearbyPictures": {}, "pleaseLogin": "Kép hozzáadásához be kell jelentkezni", "respectPrivacy": "Ne készíts fényképet emberekről és rendszámtáblákról. Ne tölts fel képet a Google Mapsről, a Google Streetview-ról (utcaképről) és egyéb szerzői jog által védett forrásokból.", "toBig": "A kép túl nagy ({actual_size}). Kérjük, legfeljebb {max_size} méretű képeket használj", diff --git a/langs/it.json b/langs/it.json index a1bf685bc..1506a86b5 100644 --- a/langs/it.json +++ b/langs/it.json @@ -258,20 +258,6 @@ "doDelete": "Rimuovi immagine", "dontDelete": "Annulla", "isDeleted": "Cancellata", - "nearbyPictures": { - "allFiltered": "Nessuna immagine corrisponde al tuo filtro", - "browseNearby": "Carica immagini nei dintorni…", - "confirm": "L'immagine selezionata mostra {title()}", - "hasMatchingPicture": "C'è un'immagine che corrisponde all'oggetto? Selezionalo sotto", - "loadMore": "Carica più immagini", - "loading": "Caricamento di immagini nei dintorni…", - "noImageSelected": "Seleziona un'immagine per collegarla all'oggetto", - "nothingFound": "Nessuna immagine trovata nei dintorni…", - "onlyTowards": "Mostra solo le immagini scattate verso quest'oggetto", - "removeFilters": "Clicca qui per rimuovere i filtri", - "title": "Immagini nei dintorni", - "withinRadius": "Mostra solo immagini che son scattate entro {radius} metri da questo oggetto" - }, "pleaseLogin": "Accedi per caricare una foto", "respectPrivacy": "Non fotografare persone o targhe dei veicoli. Non caricare da Google Maps, Google Streetview o da altre fonti coperte da copyright.", "toBig": "La tua immagine è troppo grande in quanto è di {actual_size}. Cerca di usare immagini non più grandi di {max_size}", diff --git a/langs/ja.json b/langs/ja.json index 6418961d5..afcfdd6ad 100644 --- a/langs/ja.json +++ b/langs/ja.json @@ -138,7 +138,6 @@ "doDelete": "イメージの削除", "dontDelete": "[キャンセル]", "isDeleted": "削除済み", - "nearbyPictures": {}, "pleaseLogin": "写真を追加するにはログインしてください", "respectPrivacy": "人やナンバープレートを撮影しないでください。Googleマップ、Google Streetview、その他著作権で保護された情報源をアップロードしないでください。", "uploadDone": "あなたの写真が追加されました。ご協力ありがとうございます!", diff --git a/langs/layers/ca.json b/langs/layers/ca.json index a612bbe4b..7d894c090 100644 --- a/langs/layers/ca.json +++ b/langs/layers/ca.json @@ -351,7 +351,11 @@ }, "artwork-website": { "question": "Hi ha un lloc web amb més informació sobre aquesta obra d'art?", - "render": "Més informació a aquesta pàgina web" + "render": { + "special": { + "text": "Més informació a aquesta pàgina web" + } + } }, "artwork_subject": { "question": "Què representa aquesta obra d'art?", @@ -3671,7 +3675,11 @@ }, "ghost_bike-source": { "question": "En quina pàgina web es pot trobar més informació sobre la bicicleta blanca o l'accident?", - "render": "Més informació disponible" + "render": { + "special": { + "text": "Més informació disponible" + } + } } }, "title": { @@ -4108,8 +4116,7 @@ }, "Email": { "question": "A quina adreça de correu electrònic es pot enviar amb preguntes i problemes amb aquest parc natural?", - "questionHint": "Respecteu la privadesa: només ompliu una adreça de correu electrònic personal si es publica àmpliament", - "render": "{email}" + "questionHint": "Respecteu la privadesa: només ompliu una adreça de correu electrònic personal si es publica àmpliament" }, "Name tag": { "render": "Aquesta àrea s'anomena {name}" @@ -6456,7 +6463,7 @@ "verified-mastodon": { "mappings": { "0": { - "then": "S'ha trobat un enllaç al vostre perfil de Mastodon: {_mastodon_link}" + "then": "S'ha trobat un enllaç al vostre perfil de Mastodon: {_mastodon_link}" } } } diff --git a/langs/layers/cs.json b/langs/layers/cs.json index 521179bca..4c2da9751 100644 --- a/langs/layers/cs.json +++ b/langs/layers/cs.json @@ -351,7 +351,11 @@ }, "artwork-website": { "question": "Existuje webová stránka s dalšími informacemi o tomto uměleckém díle?", - "render": "Více informací na této webové stránce" + "render": { + "special": { + "text": "Více informací na této webové stránce" + } + } }, "artwork_subject": { "question": "Co zobrazuje toto umělecké dílo?", diff --git a/langs/layers/da.json b/langs/layers/da.json index 20e0d008f..7e5f7982c 100644 --- a/langs/layers/da.json +++ b/langs/layers/da.json @@ -130,7 +130,11 @@ }, "artwork-website": { "question": "Er der et websted med mere information om dette kunstværk?", - "render": "Yderligere oplysninger på dette websted" + "render": { + "special": { + "text": "Yderligere oplysninger på dette websted" + } + } } }, "title": { diff --git a/langs/layers/de.json b/langs/layers/de.json index 793e3762d..b4224d6c7 100644 --- a/langs/layers/de.json +++ b/langs/layers/de.json @@ -351,7 +351,11 @@ }, "artwork-website": { "question": "Auf welcher Webseite gibt es weitere Informationen zum Kunstwerk?", - "render": "Weitere Informationen auf dieser Webseite" + "render": { + "special": { + "text": "Weitere Informationen auf dieser Webseite" + } + } }, "artwork_subject": { "question": "Was zeigt dieses Kunstwerk?", @@ -5171,7 +5175,11 @@ }, "ghost_bike-source": { "question": "Auf welcher Webseite kann man mehr Informationen über das Geisterrad oder den Unfall finden?", - "render": "Mehr Informationen" + "render": { + "special": { + "text": "Mehr Informationen" + } + } }, "ghost_bike-start_date": { "question": "Wann wurde dieses Geisterrad aufgestellt?", @@ -6087,8 +6095,7 @@ }, "Email": { "question": "An welche Email-Adresse kann man sich bei Fragen und Problemen zu diesem Gebiet wenden?", - "questionHint": "Respektieren Sie die Privatsphäre. Geben Sie nur dann eine persönliche Email-Adresse an, wenn diese allgemein bekannt ist", - "render": "{email}" + "questionHint": "Respektieren Sie die Privatsphäre. Geben Sie nur dann eine persönliche Email-Adresse an, wenn diese allgemein bekannt ist" }, "Name tag": { "mappings": { @@ -7135,7 +7142,11 @@ }, "public_bookcase-website": { "question": "Auf welcher Webseite findet man Informationen zu diesem Bücherschrank?", - "render": "Weitere Informationen auf der Webseite" + "render": { + "special": { + "text": "Weitere Informationen auf der Webseite" + } + } } }, "title": { @@ -9678,10 +9689,10 @@ "verified-mastodon": { "mappings": { "0": { - "then": "Es wurde ein Link zu deinem Mastodon-Profil gefunden: {_mastodon_link}" + "then": "Es wurde ein Link zu deinem Mastodon-Profil gefunden: {_mastodon_link}" }, "1": { - "then": "Wir haben einen Link gefunden, der aussieht wie ein Mastodon-Konto, aber nicht verifiziert ist. Bearbeiten Sie Ihre Profilbeschreibung und fügen Sie dort Folgendes ein: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" + "then": "Wir haben einen Link gefunden, der aussieht wie ein Mastodon-Konto, aber nicht verifiziert ist. Bearbeiten Sie Ihre Profilbeschreibung und fügen Sie dort Folgendes ein: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" } } } diff --git a/langs/layers/en.json b/langs/layers/en.json index e0170c310..1125f5522 100644 --- a/langs/layers/en.json +++ b/langs/layers/en.json @@ -351,7 +351,11 @@ }, "artwork-website": { "question": "Is there a website with more information about this artwork?", - "render": "More information on this website" + "render": { + "special": { + "text": "More information on this website" + } + } }, "artwork_subject": { "question": "What does this artwork depict?", @@ -5171,7 +5175,11 @@ }, "ghost_bike-source": { "question": "On what webpage can one find more info about the ghost bike or the accident?", - "render": "More info available" + "render": { + "special": { + "text": "More info available" + } + } }, "ghost_bike-start_date": { "question": "When was this Ghost bike installed?", @@ -6087,8 +6095,7 @@ }, "Email": { "question": "What email adress can one send to with questions and problems with this nature reserve?", - "questionHint": "Respect privacy - only fill out a personal email address if this is widely published", - "render": "{email}" + "questionHint": "Respect privacy - only fill out a personal email address if this is widely published" }, "Name tag": { "mappings": { @@ -7135,7 +7142,11 @@ }, "public_bookcase-website": { "question": "Is there a website with more information about this public bookcase?", - "render": "More info on the website" + "render": { + "special": { + "text": "More info on the website" + } + } } }, "title": { @@ -9678,10 +9689,10 @@ "verified-mastodon": { "mappings": { "0": { - "then": "A link to your Mastodon-profile has been been found: {_mastodon_link}" + "then": "A link to your Mastodon-profile has been been found: {_mastodon_link}" }, "1": { - "then": "We found a link to what looks to be a mastodon account, but it is unverified. Edit your profile description and place the following there: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" + "then": "We found a link to what looks to be a mastodon account, but it is unverified. Edit your profile description and place the following there: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" } } } diff --git a/langs/layers/es.json b/langs/layers/es.json index 31857c562..cef9969e8 100644 --- a/langs/layers/es.json +++ b/langs/layers/es.json @@ -351,7 +351,11 @@ }, "artwork-website": { "question": "¿Hay un sitio web con más información sobre esta obra de arte?", - "render": "Más información en este sitio web" + "render": { + "special": { + "text": "Más información en este sitio web" + } + } }, "artwork_subject": { "question": "¿Qué representa esta obra de arte?", diff --git a/langs/layers/fr.json b/langs/layers/fr.json index 14f41d88b..21915cd19 100644 --- a/langs/layers/fr.json +++ b/langs/layers/fr.json @@ -339,7 +339,11 @@ }, "artwork-website": { "question": "Existe-t-il un site web où trouver plus d'informations sur cette œuvre d'art ?", - "render": "Plus d'info sûr ce site web" + "render": { + "special": { + "text": "Plus d'info sûr ce site web" + } + } }, "artwork_subject": { "question": "Que représente cette oeuvre d'art ?", @@ -3727,7 +3731,11 @@ }, "ghost_bike-source": { "question": "Sur quelle page web peut-on trouver plus d'informations sur le Vélo fantôme ou l'accident ?", - "render": "Plus d'informations sont disponibles" + "render": { + "special": { + "text": "Plus d'informations sont disponibles" + } + } }, "ghost_bike-start_date": { "question": "Quand ce vélo fantôme a-t-il été installée ?", @@ -4093,8 +4101,7 @@ }, "Email": { "question": "À quelle adresse courriel peut-on envoyer des questions et des problèmes concernant cette réserve naturelle ? ", - "questionHint": "Respecter la vie privée – renseignez une adresse électronique personnelle seulement si celle-ci est largement publiée", - "render": "{email}" + "questionHint": "Respecter la vie privée – renseignez une adresse électronique personnelle seulement si celle-ci est largement publiée" }, "Surface area": { "render": "Superficie : {_surface:ha} ha" @@ -4656,7 +4663,11 @@ }, "public_bookcase-website": { "question": "Y a-t-il un site web avec plus d'informations sur cette microbibliothèque ?", - "render": "Plus d'infos sur le site web" + "render": { + "special": { + "text": "Plus d'infos sur le site web" + } + } } }, "title": { @@ -6513,7 +6524,7 @@ "verified-mastodon": { "mappings": { "0": { - "then": "Un lien vers votre profil Mastodon a été trouvé : {_mastodon_link}" + "then": "Un lien vers votre profil Mastodon a été trouvé : {_mastodon_link}" } } } diff --git a/langs/layers/hu.json b/langs/layers/hu.json index 033b17ec5..44c9e796c 100644 --- a/langs/layers/hu.json +++ b/langs/layers/hu.json @@ -130,7 +130,11 @@ }, "artwork-website": { "question": "Van-e olyan honlap, amely további információkat tartalmaz erről a műalkotásról?", - "render": "További információ ezen a weboldalon" + "render": { + "special": { + "text": "További információ ezen a weboldalon" + } + } } }, "title": { @@ -752,7 +756,11 @@ }, "public_bookcase-website": { "question": "Van-e olyan weboldal, ahol további információ található erről a nyilvános könyvespolcról?", - "render": "További információ ezen a weboldalon" + "render": { + "special": { + "text": "További információ ezen a weboldalon" + } + } } }, "title": { diff --git a/langs/layers/id.json b/langs/layers/id.json index 950dc3170..ff82e7cdd 100644 --- a/langs/layers/id.json +++ b/langs/layers/id.json @@ -81,7 +81,11 @@ }, "artwork-website": { "question": "Adakah situs web mengenai informasi lebih lanjut tentang karya seni ini?", - "render": "Info lanjut tersedia di laman web ini" + "render": { + "special": { + "text": "Info lanjut tersedia di laman web ini" + } + } } }, "title": { @@ -341,7 +345,11 @@ "render": "{inscription}" }, "ghost_bike-source": { - "render": "Informasi lanjut tersedia" + "render": { + "special": { + "text": "Informasi lanjut tersedia" + } + } } } }, @@ -365,13 +373,6 @@ } } }, - "nature_reserve": { - "tagRenderings": { - "Email": { - "render": "{email}" - } - } - }, "playground": { "tagRenderings": { "playground-email": { diff --git a/langs/layers/it.json b/langs/layers/it.json index f4bdc4550..1b6502f5e 100644 --- a/langs/layers/it.json +++ b/langs/layers/it.json @@ -105,7 +105,11 @@ }, "artwork-website": { "question": "Esiste un sito web con maggiori informazioni su quest’opera?", - "render": "Ulteriori informazioni su questo sito web" + "render": { + "special": { + "text": "Ulteriori informazioni su questo sito web" + } + } } }, "title": { @@ -1345,7 +1349,11 @@ }, "ghost_bike-source": { "question": "In quale pagina web si possono trovare informazioni sulla bici fantasma o l’incidente?", - "render": "Sono disponibili ulteriori informazioni" + "render": { + "special": { + "text": "Sono disponibili ulteriori informazioni" + } + } }, "ghost_bike-start_date": { "question": "Quando è stata installata questa bici fantasma?", @@ -1510,8 +1518,7 @@ }, "Email": { "question": "Qual è l’indirizzo email a cui scrivere per fare domande o segnalare problemi su questa riserva naturale?", - "questionHint": "Rispetta la privacy (compila l’indirizzo email personale solo se è stato reso pubblico)", - "render": "{email}" + "questionHint": "Rispetta la privacy (compila l’indirizzo email personale solo se è stato reso pubblico)" }, "Surface area": { "render": "Area: {_surface:ha} ha" @@ -1760,7 +1767,11 @@ }, "public_bookcase-website": { "question": "C'è un sito web con maggiori informazioni su questa microbiblioteca?", - "render": "Maggiori informazioni sul sito web" + "render": { + "special": { + "text": "Maggiori informazioni sul sito web" + } + } } }, "title": { diff --git a/langs/layers/ja.json b/langs/layers/ja.json index 71997d053..eb2c414f2 100644 --- a/langs/layers/ja.json +++ b/langs/layers/ja.json @@ -105,7 +105,11 @@ }, "artwork-website": { "question": "この作品についての詳しい情報はどのウェブサイトにありますか?", - "render": "Webサイトに詳細情報がある" + "render": { + "special": { + "text": "Webサイトに詳細情報がある" + } + } } }, "title": { diff --git a/langs/layers/nb_NO.json b/langs/layers/nb_NO.json index cb139d8ec..d073d3e7e 100644 --- a/langs/layers/nb_NO.json +++ b/langs/layers/nb_NO.json @@ -101,7 +101,11 @@ }, "artwork-website": { "question": "Finnes det en nettside med mer info om dette kunstverket?", - "render": "Mer info er å finne på denne nettsiden" + "render": { + "special": { + "text": "Mer info er å finne på denne nettsiden" + } + } }, "artwork_subject": { "render": "Dette kunstverket viser {wikidata_label(subject:wikidata)}{wikipedia(subject:wikidata)}" diff --git a/langs/layers/nl.json b/langs/layers/nl.json index 87d066050..4fa39eed5 100644 --- a/langs/layers/nl.json +++ b/langs/layers/nl.json @@ -247,7 +247,11 @@ }, "artwork-website": { "question": "Is er een website met meer informatie over dit kunstwerk?", - "render": "Meer informatie op deze website" + "render": { + "special": { + "text": "Meer informatie op deze website" + } + } }, "artwork_subject": { "question": "Wat beeldt dit kunstwerk af?", @@ -4851,7 +4855,11 @@ }, "ghost_bike-source": { "question": "Op welke website kan men meer informatie vinden over de Witte fiets of over het ongeval?", - "render": "Meer informatie" + "render": { + "special": { + "text": "Meer informatie" + } + } }, "ghost_bike-start_date": { "question": "Wanneer werd deze witte fiets geplaatst?", @@ -5678,8 +5686,7 @@ }, "Email": { "question": "Waar kan men naartoe emailen voor vragen en meldingen van dit natuurgebied?", - "questionHint": "Respecteer privacy - geef enkel persoonlijke emailadressen als deze elders zijn gepubliceerd", - "render": "{email}" + "questionHint": "Respecteer privacy - geef enkel persoonlijke emailadressen als deze elders zijn gepubliceerd" }, "Name tag": { "mappings": { @@ -6667,7 +6674,11 @@ }, "public_bookcase-website": { "question": "Is er een website over dit boekenruilkastje?", - "render": "Meer info op de website" + "render": { + "special": { + "text": "Meer info op de website" + } + } } }, "title": { @@ -8940,10 +8951,10 @@ "verified-mastodon": { "mappings": { "0": { - "then": "Een link naar je Mastodon-profiel werd gevonden: {_mastodon_link}" + "then": "Een link naar je Mastodon-profiel werd gevonden: {_mastodon_link}" }, "1": { - "then": "Je profielbeschrijving bevat een link die vermoedelijk naar je Mastodon gaat, maar deze link is niet verifieerdbaar voor Mastodon.Pas je profielbeschrijving aan en plaats er de volgende code: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" + "then": "Je profielbeschrijving bevat een link die vermoedelijk naar je Mastodon gaat, maar deze link is niet verifieerdbaar voor Mastodon.Pas je profielbeschrijving aan en plaats er de volgende code: <a href=\"{_mastodon_candidate}\" rel=\"me\">Mastodon</a>" } } } diff --git a/langs/layers/pl.json b/langs/layers/pl.json index dc6c5f820..d75b361bf 100644 --- a/langs/layers/pl.json +++ b/langs/layers/pl.json @@ -1,2661 +1,2665 @@ { - "address": { - "description": "Adresy", - "name": "Znane adresy w OSM", - "tagRenderings": { - "fixme": { - "question": "Co wymaga naprawy? Proszę wytłumaczyć" - }, - "housenumber": { - "mappings": { - "0": { - "then": "Ten budynek nie ma numeru" - } - }, - "question": "Jaki jest numer tego domu?", - "render": "Numer tego domu to {addr:housenumber}" - }, - "street": { - "question": "Na jakiej ulicy znajduje się ten adres?", - "render": "Ten adres znajduje się na ulicy {addr:street}" - } + "address": { + "description": "Adresy", + "name": "Znane adresy w OSM", + "tagRenderings": { + "fixme": { + "question": "Co wymaga naprawy? Proszę wytłumaczyć" + }, + "housenumber": { + "mappings": { + "0": { + "then": "Ten budynek nie ma numeru" + } }, - "title": { - "render": "Znany adres" - } + "question": "Jaki jest numer tego domu?", + "render": "Numer tego domu to {addr:housenumber}" + }, + "street": { + "question": "Na jakiej ulicy znajduje się ten adres?", + "render": "Ten adres znajduje się na ulicy {addr:street}" + } }, - "advertising": { - "presets": { - "0": { - "description": "Duża struktura reklamowa na dworze, zwykle znajdująca się w obszarach z dużym ruchem, np. w pobliżu ruchliwych dróg", - "title": "bilbord" - }, - "3": { - "description": "Mały bilbord dla reklam lokalnych, przeznaczony głównie dla pieszych", - "title": "tablica" - }, - "4": { - "title": "kolumna" - }, - "5": { - "title": "flaga" - }, - "6": { - "title": "ekran" - }, - "7": { - "title": "ekran zamontowany na ścianie" - }, - "10": { - "title": "znak" - }, - "11": { - "title": "rzeźba" - }, - "12": { - "title": "mural ścienny" - } - }, - "tagRenderings": { - "Sides": { - "mappings": { - "0": { - "then": "Ten obiekt ma reklamy po jednej stronie" - }, - "1": { - "then": "Ten obiekt ma reklamy po dwóch stronach" - } - }, - "question": "Z ilu stron można oglądać reklamy?" - }, - "animated": { - "mappings": { - "0": { - "then": "Statyczne, zawsze pokazuje tą samą wiadomość" - }, - "1": { - "then": "Ten obiekt ma wbudowany cyfrowy wyświetlacz do pokazywania cen lub innych informacji" - } - }, - "question": "Czy ta reklama przechodzi przez wiele różnych wiadomości?" - }, - "message_type": { - "mappings": { - "0": { - "then": "Wiadomość komercyjna" - }, - "1": { - "then": "Informacja lokalna" - }, - "2": { - "then": "Informacje dotyczące bezpieczeństwa" - }, - "3": { - "then": "Reklamy wyborcze" - }, - "4": { - "then": "Informacje dotyczące teatru, koncertów, …" - }, - "5": { - "then": "Wiadomość od organizacji non-profit" - }, - "6": { - "then": "Żeby wyrazić swoją opinię" - }, - "7": { - "then": "Przekaz religijny" - }, - "9": { - "then": "Mapa" - } - }, - "question": "Jaki rodzaj wiadomości jest pokazany?" - }, - "operator": { - "question": "Kto obsługuje ten obiekt?", - "render": "Obsługiwane przez {operator}" - }, - "ref": { - "question": "Jaki jest numer referencyjny?", - "render": "Numer referencyjny to {ref}" - }, - "type": { - "mappings": { - "0": { - "then": "To jest bilbord" - }, - "1": { - "then": "To jest tablica" - }, - "2": { - "then": "To jest kolumna" - }, - "3": { - "then": "To jest flaga" - }, - "5": { - "then": "To jest ekran" - }, - "6": { - "then": "To jest rzeźba" - }, - "7": { - "then": "To jest znak" - }, - "10": { - "then": "To jest mural ścienny" - } - }, - "question": "Jakiego rodzaju jest to obiekt reklamowy?", - "render": "To jest {advertising}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Bilbord" - }, - "1": { - "then": "Tablica" - }, - "3": { - "then": "Kolumna" - }, - "4": { - "then": "Flaga" - }, - "5": { - "then": "Ekran" - }, - "6": { - "then": "Rzeźba" - }, - "7": { - "then": "Znak" - }, - "10": { - "then": "Mural ścienny" - } - } - } + "title": { + "render": "Znany adres" + } + }, + "advertising": { + "presets": { + "0": { + "description": "Duża struktura reklamowa na dworze, zwykle znajdująca się w obszarach z dużym ruchem, np. w pobliżu ruchliwych dróg", + "title": "bilbord" + }, + "3": { + "description": "Mały bilbord dla reklam lokalnych, przeznaczony głównie dla pieszych", + "title": "tablica" + }, + "4": { + "title": "kolumna" + }, + "5": { + "title": "flaga" + }, + "6": { + "title": "ekran" + }, + "7": { + "title": "ekran zamontowany na ścianie" + }, + "10": { + "title": "znak" + }, + "11": { + "title": "rzeźba" + }, + "12": { + "title": "mural ścienny" + } }, - "artwork": { - "name": "Dzieła sztuki", - "presets": { + "tagRenderings": { + "Sides": { + "mappings": { + "0": { + "then": "Ten obiekt ma reklamy po jednej stronie" + }, + "1": { + "then": "Ten obiekt ma reklamy po dwóch stronach" + } + }, + "question": "Z ilu stron można oglądać reklamy?" + }, + "animated": { + "mappings": { + "0": { + "then": "Statyczne, zawsze pokazuje tą samą wiadomość" + }, + "1": { + "then": "Ten obiekt ma wbudowany cyfrowy wyświetlacz do pokazywania cen lub innych informacji" + } + }, + "question": "Czy ta reklama przechodzi przez wiele różnych wiadomości?" + }, + "message_type": { + "mappings": { + "0": { + "then": "Wiadomość komercyjna" + }, + "1": { + "then": "Informacja lokalna" + }, + "2": { + "then": "Informacje dotyczące bezpieczeństwa" + }, + "3": { + "then": "Reklamy wyborcze" + }, + "4": { + "then": "Informacje dotyczące teatru, koncertów, …" + }, + "5": { + "then": "Wiadomość od organizacji non-profit" + }, + "6": { + "then": "Żeby wyrazić swoją opinię" + }, + "7": { + "then": "Przekaz religijny" + }, + "9": { + "then": "Mapa" + } + }, + "question": "Jaki rodzaj wiadomości jest pokazany?" + }, + "operator": { + "question": "Kto obsługuje ten obiekt?", + "render": "Obsługiwane przez {operator}" + }, + "ref": { + "question": "Jaki jest numer referencyjny?", + "render": "Numer referencyjny to {ref}" + }, + "type": { + "mappings": { + "0": { + "then": "To jest bilbord" + }, + "1": { + "then": "To jest tablica" + }, + "2": { + "then": "To jest kolumna" + }, + "3": { + "then": "To jest flaga" + }, + "5": { + "then": "To jest ekran" + }, + "6": { + "then": "To jest rzeźba" + }, + "7": { + "then": "To jest znak" + }, + "10": { + "then": "To jest mural ścienny" + } + }, + "question": "Jakiego rodzaju jest to obiekt reklamowy?", + "render": "To jest {advertising}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Bilbord" + }, + "1": { + "then": "Tablica" + }, + "3": { + "then": "Kolumna" + }, + "4": { + "then": "Flaga" + }, + "5": { + "then": "Ekran" + }, + "6": { + "then": "Rzeźba" + }, + "7": { + "then": "Znak" + }, + "10": { + "then": "Mural ścienny" + } + } + } + }, + "artwork": { + "name": "Dzieła sztuki", + "presets": { + "0": { + "title": "Dzieło sztuki" + }, + "1": { + "title": "Dzieło sztuki na ścianie" + } + }, + "tagRenderings": { + "artwork-artist-wikidata": { + "question": "Kto stworzył to dzieło sztuki?", + "render": "To dzieło sztuki zostało zrobione przez {wikidata_label(artist:wikidata):font-weight:bold}
{wikipedia(artist:wikidata)}" + }, + "artwork-artist_name": { + "question": "Który artysta to stworzył?", + "render": "Stworzone przez {artist_name}" + }, + "artwork-artwork_type": { + "mappings": { + "0": { + "then": "Architektura" + }, + "1": { + "then": "Mural" + }, + "2": { + "then": "Obraz" + }, + "3": { + "then": "Rzeźba" + }, + "4": { + "then": "Posąg" + }, + "5": { + "then": "Popiersie" + }, + "6": { + "then": "Skała" + }, + "7": { + "then": "Instalacja artystyczna" + }, + "8": { + "then": "Graffiti" + }, + "9": { + "then": "Płaskorzeźba" + }, + "10": { + "then": "Azulejo (hiszpańskie płytka dekoracyjna)" + }, + "11": { + "then": "Płyta ceramiczna (fliza)" + } + }, + "question": "Jakiego rodzaju jest to dzieło sztuki?", + "render": "Jest to {artwork_type}" + }, + "artwork-website": { + "question": "Gdzie znajdę więcej informacji na temat tego dzieła sztuki?", + "render": { + "special": { + "text": "Więcej informacji na tej stronie" + } + }, + "artwork_subject": { + "question": "Co przedstawia to dzieło sztuki?", + "render": "To dzieło sztuki przedstawia {wikidata_label(subject:wikidata)}{wikipedia(subject:wikidata)}" + }, + "doubles_as_bench": { + "mappings": { "0": { - "title": "Dzieło sztuki" + "then": "To dzieło sztuki pełni również funkcję ławki" }, "1": { - "title": "Dzieło sztuki na ścianie" + "then": "To dzieło sztuki nie pełni funkcji ławki" + }, + "2": { + "then": "To dzieło sztuki nie pełni funkcji ławki" } - }, - "tagRenderings": { - "artwork-artist-wikidata": { - "question": "Kto stworzył to dzieło sztuki?", - "render": "To dzieło sztuki zostało zrobione przez {wikidata_label(artist:wikidata):font-weight:bold}
{wikipedia(artist:wikidata)}" - }, - "artwork-artist_name": { - "question": "Który artysta to stworzył?", - "render": "Stworzone przez {artist_name}" - }, - "artwork-artwork_type": { - "mappings": { - "0": { - "then": "Architektura" - }, - "1": { - "then": "Mural" - }, - "2": { - "then": "Obraz" - }, - "3": { - "then": "Rzeźba" - }, - "4": { - "then": "Posąg" - }, - "5": { - "then": "Popiersie" - }, - "6": { - "then": "Skała" - }, - "7": { - "then": "Instalacja artystyczna" - }, - "8": { - "then": "Graffiti" - }, - "9": { - "then": "Płaskorzeźba" - }, - "10": { - "then": "Azulejo (hiszpańskie płytka dekoracyjna)" - }, - "11": { - "then": "Płyta ceramiczna (fliza)" - } - }, - "question": "Jakiego rodzaju jest to dzieło sztuki?", - "render": "Jest to {artwork_type}" - }, - "artwork-website": { - "question": "Gdzie znajdę więcej informacji na temat tego dzieła sztuki?", - "render": "Więcej informacji na tej stronie" - }, - "artwork_subject": { - "question": "Co przedstawia to dzieło sztuki?", - "render": "To dzieło sztuki przedstawia {wikidata_label(subject:wikidata)}{wikipedia(subject:wikidata)}" - }, - "doubles_as_bench": { - "mappings": { - "0": { - "then": "To dzieło sztuki pełni również funkcję ławki" - }, - "1": { - "then": "To dzieło sztuki nie pełni funkcji ławki" - }, - "2": { - "then": "To dzieło sztuki nie pełni funkcji ławki" - } - }, - "question": "Czy to dzieło sztuki pełni funkcję ławki?" - } - }, - "title": { - "mappings": { - "0": { - "then": "Dzieło sztuki {name}" - } - }, - "render": "Dzieło sztuki" + }, + "question": "Czy to dzieło sztuki pełni funkcję ławki?" } + }, + "title": { + "mappings": { + "0": { + "then": "Dzieło sztuki {name}" + } + }, + "render": "Dzieło sztuki" + } }, "atm": { - "description": "Bankomaty do wypłacania pieniędzy", - "name": "Bankomaty", - "presets": { - "0": { - "title": "bankomat" - } - }, - "tagRenderings": { - "cash_in": { - "mappings": { - "0": { - "then": "Prawdopodobnie ten bankomat nie pozwala wpłacać pieniędzy" - }, - "1": { - "then": "Ten bankomat pozwala wpłacać pieniądze" - }, - "2": { - "then": "Ten bankomat nie pozwala wpłacać pieniędzy" - } - }, - "question": "Czy ten bankomat pozwala wpłacać pieniądze?" - }, - "cash_out": { - "mappings": { - "0": { - "then": "Z tego bankomatu można wypłacić pieniądze" - } - } - }, - "cash_out-denominations-notes": { - "question": "Jakie banknoty można tutaj wypłacić?" - }, - "name": { - "render": "Nazwa tego bankomatu to {name}" - }, - "operator": { - "question": "Jaka firma obsługuje ten bankomat?", - "render": "Ten bankomat jest obsługiwany przez {operator}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Bankomat {brand}" - } - }, - "render": "Bankomat" + "description": "Bankomaty do wypłacania pieniędzy", + "name": "Bankomaty", + "presets": { + "0": { + "title": "bankomat" } + }, + "tagRenderings": { + "cash_in": { + "mappings": { + "0": { + "then": "Prawdopodobnie ten bankomat nie pozwala wpłacać pieniędzy" + }, + "1": { + "then": "Ten bankomat pozwala wpłacać pieniądze" + }, + "2": { + "then": "Ten bankomat nie pozwala wpłacać pieniędzy" + } + }, + "question": "Czy ten bankomat pozwala wpłacać pieniądze?" + }, + "cash_out": { + "mappings": { + "0": { + "then": "Z tego bankomatu można wypłacić pieniądze" + } + } + }, + "cash_out-denominations-notes": { + "question": "Jakie banknoty można tutaj wypłacić?" + }, + "name": { + "render": "Nazwa tego bankomatu to {name}" + }, + "operator": { + "question": "Jaka firma obsługuje ten bankomat?", + "render": "Ten bankomat jest obsługiwany przez {operator}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Bankomat {brand}" + } + }, + "render": "Bankomat" + } }, "bank": { - "description": "Instytucja finansowa pozwalająca wpłacić pieniądze", - "filter": { - "1": { - "options": { - "0": { - "question": "Za pomocą bankomatu" - } - } - } - }, - "name": "Banki", - "tagRenderings": { - "has_atm": { - "mappings": { - "0": { - "then": "Ten bank ma bankomat" - }, - "1": { - "then": "Ten bank nie ma bankomatu" - } - }, - "question": "Czy ten bank ma bankomat?" + "description": "Instytucja finansowa pozwalająca wpłacić pieniądze", + "filter": { + "1": { + "options": { + "0": { + "question": "Za pomocą bankomatu" } + } } + }, + "name": "Banki", + "tagRenderings": { + "has_atm": { + "mappings": { + "0": { + "then": "Ten bank ma bankomat" + }, + "1": { + "then": "Ten bank nie ma bankomatu" + } + }, + "question": "Czy ten bank ma bankomat?" + } + } }, "barrier": { - "name": "Barierki" + "name": "Barierki" }, "bench": { - "filter": { - "1": { - "options": { - "0": { - "question": "Z oraz bez oparcia" - }, - "1": { - "question": "Ma oparcie" - }, - "2": { - "question": "Nie ma oparcia" - } - } - } - }, - "name": "Ławki", - "presets": { + "filter": { + "1": { + "options": { "0": { - "title": "Ławka" - } - }, - "tagRenderings": { - "bench-artwork": { - "mappings": { - "0": { - "then": "Ta ławka ma wbudowane dzieło sztuki" - }, - "1": { - "then": "Ta ławka nie ma wbudowanego dzieła sztuki" - } - }, - "question": "Czy ta ławka ma wbudowane dzieło sztuki?", - "questionHint": "Np. jest na niej coś namalowane, ma rzeźbę lub inną nietrywialną pracę" - }, - "bench-backrest": { - "mappings": { - "0": { - "then": "Ta ławka jest dwustronna ze wspólnym oparciem" - }, - "1": { - "then": "Oparcie: Tak" - }, - "2": { - "then": "Oparcie: Nie" - } - }, - "question": "Czy ta ławka ma oparcie?" - }, - "bench-colour": { - "mappings": { - "0": { - "then": "Kolor: brązowy" - }, - "1": { - "then": "Kolor: zielony" - }, - "2": { - "then": "Kolor: szary" - }, - "3": { - "then": "Kolor: biały" - }, - "4": { - "then": "Kolor: czerwony" - }, - "5": { - "then": "Kolor: czarny" - }, - "6": { - "then": "Kolor: niebieski" - }, - "7": { - "then": "Kolor: żółty" - } - }, - "question": "Jaki kolor ma ta ławka?", - "render": "Kolor: {colour}" - }, - "bench-direction": { - "question": "W jakim kierunku patrzysz siedząc na ławce?", - "render": "Siedząc na ławce, patrzy się w kierunku {direction}°." - }, - "bench-material": { - "mappings": { - "0": { - "then": "Materiał: drewno" - }, - "1": { - "then": "Materiał: metal" - }, - "2": { - "then": "Materiał: kamień" - }, - "3": { - "then": "Materiał: beton" - }, - "4": { - "then": "Materiał: plastik" - }, - "5": { - "then": "Materiał: stal" - } - }, - "question": "Z czego wykonana jest ławka (siedzisko)?", - "render": "Materiał: {material}" - }, - "bench-memorial": { - "mappings": { - "0": { - "then": "Ta ławka jest pomnikiem upamiętniającym kogoś lub coś" - }, - "1": { - "then": "Ta ławka nie jest pomnikiem upamiętniającym kogoś lub coś" - } - }, - "question": "Czy ta ławka służy jako pomnik upamiętniający kogoś lub coś?" - }, - "bench-seats": { - "question": "Ile siedzeń ma ta ławka?", - "render": "{seats} siedzeń" - }, - "bench-survey:date": { - "question": "Kiedy ostatnio badano tę ławkę?", - "render": "Ławka ta była ostatnio badana w dniu {survey:date}" - } - }, - "title": { - "render": "Ławka" - } - }, - "bench_at_pt": { - "deletion": { - "extraDeleteReasons": { - "0": { - "explanation": "Ten przystanek autobusowy nie jest już używany" - } - }, - "nonDeleteMappings": { - "0": { - "then": "Ten przystanek autobusowy nie ma ławki (nigdy jej nie było lub została usunięta)" - } - } - }, - "description": "Warstwa pokazująca wszystkie przystanki transportu publicznego, które mają ławki", - "name": "Ławki na przystankach komunikacji miejskiej", - "tagRenderings": { - "bench_at_pt-name": { - "render": "{name}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Ławka na przystanku komunikacji miejskiej" - } - }, - "render": "Ławka" - } - }, - "bicycle_library": { - "description": "Obiekt, w którym rowery można wypożyczyć na dłuższy okres" - }, - "bicycle_rental": { - "tagRenderings": { - "rental_types": { - "rewrite": { - "into": { - "0": { - "1": "rowery miejskie" - }, - "1": { - "1": "rowery elektryczne" - }, - "2": { - "1": "rowery dla dzieci" - }, - "3": { - "1": "rowery BMX" - }, - "4": { - "1": "rowery górskie" - }, - "6": { - "1": "tandem" - } - } - } - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "Wypożyczalnia rowerów" - } - }, - "bike_parking": { - "name": "Parking dla rowerów", - "presets": { - "0": { - "title": "Parking dla rowerów" - } - }, - "tagRenderings": { - "Access": { - "mappings": { - "0": { - "then": "Dostępne publicznie" - } - }, - "question": "Kto może używać tego parkingu dla rowerów?", - "render": "{access}" - }, - "Bicycle parking type": { - "question": "Jaki jest typ tego parkingu dla rowerów?", - "render": "Jest to parking rowerowy typu: {bicycle_parking}" - }, - "Capacity": { - "render": "Miejsce na {capacity} rowerów" - }, - "Underground?": { - "mappings": { - "2": { - "then": "Parking na dachu" - } - }, - "question": "Jaka jest względna lokalizacja tego parkingu rowerowego?" - } - }, - "title": { - "render": "Parking dla rowerów" - } - }, - "bike_repair_station": { - "presets": { - "0": { - "description": "Urządzenie do pompowania opon w stałym miejscu w przestrzeni publicznej.", - "title": "pompka do roweru" + "question": "Z oraz bez oparcia" }, "1": { - "title": "stacja naprawy rowerów i pompka" - } - }, - "tagRenderings": { - "Operational status": { - "mappings": { - "0": { - "then": "Pompka rowerowa jest zepsuta" - }, - "1": { - "then": "Pompka rowerowa jest sprawna" - } - }, - "question": "Czy pompka rowerowa jest nadal sprawna?" - }, - "access": { - "mappings": { - "1": { - "then": "Dostępne publicznie" - }, - "2": { - "then": "Tylko dla klientów" - } - } - }, - "bike_repair_station-electrical_pump": { - "mappings": { - "0": { - "then": "Pompa ręczna" - }, - "1": { - "then": "Pompka elektryczna" - } - }, - "question": "Czy jest to elektryczna pompka do roweru?" - }, - "bike_repair_station-manometer": { - "mappings": { - "0": { - "then": "Jest manometr" - }, - "1": { - "then": "Nie ma manometru" - }, - "2": { - "then": "Jest manometr, ale jest uszkodzony" - } - }, - "question": "Czy pompka posiada wskaźnik ciśnienia lub manometr?" - }, - "bike_repair_station-valves": { - "question": "Jakie zawory są obsługiwane?", - "render": "Ta pompka obsługuje następujące zawory: {valves}" - }, - "send_email_about_broken_pump": { - "render": { - "special": { - "button_text": "Zgłoś, że ta pompka rowerowa jest zepsuta", - "subject": "Zepsuta pompka rowerowa" - } - } - } - }, - "title": { - "mappings": { - "0": { - "then": "Stacja naprawy rowerów" - }, - "1": { - "then": "Stacja naprawy rowerów" - }, - "2": { - "then": "Zepsuta pompka" - }, - "3": { - "then": "Pompka do rowerów {name}" - }, - "4": { - "then": "Pompka do rowerów" - } - } - } - }, - "bike_shop": { - "tagRenderings": { - "bike_shop-access": { - "render": "Dostępne tylko dla {access}" - } - } - }, - "bike_themed_object": { - "name": "Obiekt związany z rowerami", - "title": { - "render": "Obiekt związany z rowerami" - } - }, - "birdhide": { - "name": "Miejsca do obserwacji ptaków", - "tagRenderings": { - "bird-hide-wheelchair": { - "mappings": { - "3": { - "then": "Niedostępne dla osób na wózkach" - } - } - }, - "birdhide-operator": { - "mappings": { - "0": { - "then": "Obsługiwane przez Natuurpunt" - } - }, - "render": "Obsługiwane przez {operator}" - } - } - }, - "cafe_pub": { - "name": "Kawiarnie i puby", - "presets": { - "0": { - "title": "pub" - }, - "1": { - "title": "bar" + "question": "Ma oparcie" }, "2": { - "title": "Kawiarnia" - }, - "3": { - "title": "klub nocny lub dyskoteka" + "question": "Nie ma oparcia" } - }, - "tagRenderings": { - "Classification": { - "question": "Jakiego rodzaju jest to kawiarnia?" - } - }, - "title": { - "render": "Pub" + } } - }, - "car_rental": { - "description": "Miejsca, w których można wypożyczyć samochód", - "name": "Wypożyczalnia samochodów", - "presets": { - "0": { - "description": "Miejsce, w którym można wypożyczyć samochód", - "title": "wypożyczalnia samochodów" - } - }, - "tagRenderings": { - "name": { - "freeform": { - "placeholder": "Nazwa wypożyczalni samochodów" - }, - "mappings": { - "0": { - "then": "Ta wypożyczalnia samochodów nie ma nazwy" - } - }, - "question": "Jaka jest nazwa tej wypożyczalni samochodów?", - "render": "Ta wypożyczalnia samochodów nazywa się {name}" - } - }, - "title": { - "render": "Wypożyczalnia samochodów" + }, + "name": "Ławki", + "presets": { + "0": { + "title": "Ławka" } - }, - "charging_station": { - "description": "Stacja ładowania", - "filter": { + }, + "tagRenderings": { + "bench-artwork": { + "mappings": { "0": { - "options": { - "0": { - "question": "Wszystkie rodzaje pojazdów" - }, - "1": { - "question": "Stacja ładowania dla rowerów" - }, - "2": { - "question": "Stacja ładowania dla samochodów" - } - } + "then": "Ta ławka ma wbudowane dzieło sztuki" }, "1": { - "options": { - "0": { - "question": "Tylko działające stacje ładowania" - } - } + "then": "Ta ławka nie ma wbudowanego dzieła sztuki" } + }, + "question": "Czy ta ławka ma wbudowane dzieło sztuki?", + "questionHint": "Np. jest na niej coś namalowane, ma rzeźbę lub inną nietrywialną pracę" }, - "name": "Stacje ładowania", - "presets": { - "1": { - "title": "stacja ładowania dla samochodów" - } - }, - "tagRenderings": { - "Available_charging_stations (generated)": { - "mappings": { - "13": { - "then": "Tesla Supercharger" - } - } - }, - "Network": { - "mappings": { - "1": { - "then": "Nie jest częścią większej sieci" - } - }, - "question": "Czy ta stacja ładowania jest częścią sieci?" - }, - "OH": { - "override": { - "question": "Kiedy otwiera się ta stacja ładowania?" - } - }, - "Operational status": { - "mappings": { - "0": { - "then": "Ta stacja ładowania działa" - }, - "1": { - "then": "Ta stacja ładowania jest zepsuta" - }, - "2": { - "then": "Planowana jest tutaj stacja ładowania" - }, - "3": { - "then": "Budowana jest tutaj stacja ładowania" - } - } - }, - "Operator": { - "render": "Ta stacja ładowania jest obsługiwana przez {operator}" - } - }, - "title": { - "render": "Stacja ładowania" - }, - "units": { + "bench-backrest": { + "mappings": { "0": { - "applicableUnits": { - "0": { - "human": " minut", - "humanSingular": " minuta" - }, - "1": { - "human": " godzin", - "humanSingular": " godzina" - }, - "2": { - "human": " dni", - "humanSingular": " dzień" - } - } - } - } - }, - "climbing_gym": { - "tagRenderings": { - "shoe_rental": { - "mappings": { - "2": { - "then": "Można tutaj wypożyczyć buty do wspinaczki" - }, - "3": { - "then": "Nie można wypożyczyć tutaj butów do wspinaczki" - } - }, - "question": "Czy można tutaj wypożyczyć buty do wspinaczki?" - } - } - }, - "climbing_opportunity": { - "tagRenderings": { - "climbing-opportunity-name": { - "render": "{name}" - } - } - }, - "clock": { - "presets": { - "0": { - "title": "zegar" + "then": "Ta ławka jest dwustronna ze wspólnym oparciem" }, "1": { - "description": "Publicznie widoczny zegar zamontowany na ścianie", - "title": "zegar na ścianie" - } - }, - "tagRenderings": { - "barometer": { - "mappings": { - "0": { - "then": "Ten zegar wyświetla również ciśnienie" - }, - "1": { - "then": "Ten zegar nie wyświetla ciśnienia" - }, - "2": { - "then": "Ten zegar prawdopodobnie nie wyświetla ciśnienia" - } - }, - "question": "Czy ten zegar wyświetla ciśnienie?" - }, - "date": { - "mappings": { - "0": { - "then": "Ten zegar wyświetla również datę" - }, - "1": { - "then": "Ten zegar nie wyświetla daty" - }, - "2": { - "then": "Ten zegar prawdopodobnie nie wyświetla daty" - } - }, - "question": "Czy ten zegar wyświetla datę?" - }, - "display": { - "mappings": { - "0": { - "then": "Ten zegar pokazuje czas za pomocą wskazówek" - }, - "1": { - "then": "Ten zegar wyświetla czas za pomocą cyfr" - }, - "3": { - "then": "Ten zegar wyświetla czas w niestandardowy sposób, np. używając systemu binarnego, wody lub czegoś innego" - } - }, - "question": "Jak ten zegar wyświetla czas?" - }, - "hygrometer": { - "mappings": { - "0": { - "then": "Ten zegar wyświetla również wilgotność" - }, - "1": { - "then": "Ten zegar nie wyświetla wilgotności" - }, - "2": { - "then": "Ten zegar prawdopodobnie nie wyświetla wilgotności" - } - }, - "question": "Czy ten zegar wyświetla również wilgotność?" - }, - "support": { - "mappings": { - "0": { - "then": "Ten zegar jest zamontowany na słupie" - }, - "1": { - "then": "Ten zegar jest zamontowany na ścianie" - }, - "2": { - "then": "Ten zegar jest częścią bilbordu" - }, - "3": { - "then": "Ten zegar jest na ziemi" - } - }, - "question": "W jaki sposób zamontowany jest ten zegar?" - }, - "thermometer": { - "mappings": { - "0": { - "then": "Ten zegar wyświetla również temperaturę" - }, - "1": { - "then": "Ten zegar nie wyświetla temperatury" - }, - "2": { - "then": "Ten zegar prawdopodobnie nie wyświetla temperatury" - } - }, - "question": "Czy ten zegar wyświetla również temperaturę?" - }, - "visibility": { - "mappings": { - "0": { - "then": "Ten zegar jest widoczny z około 5 metrów (mały zegar ścienny)" - }, - "1": { - "then": "Ten zegar jest widoczny z około 20 metrów (średniej wielkości zegar na bilbordzie)" - }, - "2": { - "then": "Ten zegar jest widoczny z ponad 20 metrów (np. zegar kościelny lub stacyjny)" - } - }, - "question": "Jaka jest widoczność tego zegara?" - } - }, - "title": { - "render": "Zegar" - } - }, - "crossings": { - "tagRenderings": { - "crossing-is-zebra": { - "question": "Czy to jest przejście dla pieszych typu \"zebra\"?" - } - } - }, - "cycleways_and_roads": { - "tagRenderings": { - "Maxspeed (for road)": { - "mappings": { - "0": { - "then": "Maksymalna prędkość tutaj to 20 km/h" - }, - "1": { - "then": "Maksymalna prędkość tutaj to 30 km/h" - }, - "2": { - "then": "Maksymalna prędkość tutaj to 50 km/h" - }, - "3": { - "then": "Maksymalna prędkość tutaj to 70 km/h" - }, - "4": { - "then": "Maksymalna prędkość tutaj to 90 km/h" - } - }, - "question": "Jaka jest maksymalna prędkość na tej ulicy?", - "render": "Maksymalna prędkość na tej drodze to {maxspeed} km/h" - }, - "is lit?": { - "mappings": { - "0": { - "then": "Ta ulica jest oświetlona" - }, - "1": { - "then": "Ta droga nie jest oświetlona" - }, - "2": { - "then": "Ta droga jest oświetlona w nocy" - }, - "3": { - "then": "Ta droga jest oświetlona 24/7" - } - }, - "question": "Czy ta ulica jest oświetlona?" - } - }, - "title": { - "mappings": { - "5": { - "then": "Pas rowerowy" - } - } - } - }, - "defibrillator": { - "presets": { - "0": { - "title": "defibrylator" - }, - "1": { - "title": "defibrylator na ścianie" - } - }, - "tagRenderings": { - "defibrillator-access": { - "mappings": { - "0": { - "then": "Dostępny publicznie" - }, - "1": { - "then": "Dostępny publicznie" - }, - "2": { - "then": "Dostępny tylko dla klientów" - }, - "3": { - "then": "Niedostępny publicznie (np. dostępny tylko dla personelu, właścicieli, ...)" - }, - "4": { - "then": "Niedostępny, być może tylko do profesjonalnego użytku" - } - }, - "question": "Czy ten defibrylator jest swobodnie dostępny?" - }, - "defibrillator-defibrillator": { - "mappings": { - "0": { - "then": "Nie ma informacji o rodzaju urządzenia" - }, - "1": { - "then": "To jest ręczny defibrylator dla profesjonalistów" - }, - "2": { - "then": "To jest zwykły automatyczny defibrylator" - }, - "3": { - "then": "To jest specjalny rodzaj defibrylatora: {defibrillator}" - } - }, - "question": "Czy to jest zwykły automatyczny defibrylator czy ręczny defibrylator tylko dla profesjonalistów?" - }, - "defibrillator-defibrillator:location": { - "question": "Proszę podaj opis gdzie znajduje się defibrylator (w lokalnym języku)", - "render": "Dodatkowe informacje o lokalizacji (w lokalnym języku):
{defibrillator:location}" - }, - "defibrillator-defibrillator:location:en": { - "question": "Proszę podaj opis gdzie znajduje się defibrylator (po angielsku)", - "render": "Dodatkowe informacje o lokalizacji (po angielsku):
{defibrillator:location:en}" - }, - "defibrillator-defibrillator:location:fr": { - "question": "Proszę podaj opis gdzie znajduje się defibrylator (po francusku)", - "render": "Dodatkowe informacje o lokalizacji (po francusku):
{defibrillator:location:fr}" - }, - "defibrillator-description": { - "render": "Dodatkowe informacje: {description}" - }, - "defibrillator-fixme": { - "render": "Więcej informacji dla doświadczonych użytkowników OpenStreetMap: {fixme}" - }, - "defibrillator-indoors": { - "mappings": { - "0": { - "then": "Ten defibrylator jest wewnątrz budynku" - }, - "1": { - "then": "Ten defibrylator jest na dworze" - } - }, - "question": "Czy ten defibrylator znajduje się wewnątrz budynku?" - }, - "defibrillator-level": { - "mappings": { - "0": { - "then": "Ten defibrylator jest na parterze" - }, - "1": { - "then": "Ten defibrylator jest na pierwszym piętrze" - } - }, - "question": "Na którym piętrze jest ten defibrylator?", - "render": "Ten defibrylator jest na piętrze {level}" - }, - "defibrillator-ref": { - "render": "Oficjalny numer identyfikacyjny urządzenia: {ref}" - }, - "defibrillator-survey:date": { - "mappings": { - "0": { - "then": "Sprawdzone dzisiaj!" - } - } - }, - "opening_hours_24_7": { - "override": { - "question": "W jakich godzinach dostępny jest ten defibrylator?" - } - } - }, - "title": { - "render": "Defibrylator" - } - }, - "dentist": { - "description": "Ta warstwa pokazuje gabinety dentystyczne", - "name": "Dentysta", - "tagRenderings": { - "name": { - "question": "Jaka jest nazwa tego gabinetu dentystycznego?", - "render": "Nazwa tego gabinetu dentystycznego to {name}" - } - } - }, - "doctors": { - "tagRenderings": { - "specialty": { - "mappings": { - "1": { - "then": "To jest ginekolog" - }, - "2": { - "then": "To jest psychiatra" - }, - "3": { - "then": "To jest pediatra" - } - }, - "question": "W czym specjalizuje się ten lekarz?", - "render": "Ten lekarz specjalizuje się w {healthcare:speciality}" - } - } - }, - "elevator": { - "name": "Winda", - "presets": { - "0": { - "title": "winda" - } - }, - "tagRenderings": { - "door-width": { - "question": "Jaka jest szerokość drzwi windy?", - "render": "Drzwi tej windy mają szerokość {canonical(door:width)}" - }, - "elevator-width": { - "question": "Jaka jest szerokość tej windy?", - "render": "Szerokość tej windy to {canonical(elevator:width)}" - }, - "operational_status": { - "mappings": { - "0": { - "then": "Ta winda jest zepsuta" - }, - "1": { - "then": "Ta winda jest nieczynna np. z powodu renowacji" - }, - "2": { - "then": "Ta winda działa" - }, - "3": { - "then": "Ta winda działa" - } - }, - "question": "Czy ta winda działa?" - } - }, - "title": { - "render": "Winda" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": "metr" - }, - "1": { - "human": "centymetr" - } - } - } - } - }, - "elongated_coin": { - "tagRenderings": { - "coin": { - "freeform": { - "placeholder": "Rodzaj monety (np. 10 centów)" - } - } - } - }, - "entrance": { - "tagRenderings": { - "Entrance type": { - "mappings": { - "2": { - "then": "To jest główne wejście" - }, - "4": { - "then": "To jest wejście serwisowe - zazwyczaj używane tylko przez pracowników, dostawy, …" - }, - "5": { - "then": "To jest wyjście bez możliwości wejścia" - }, - "6": { - "then": "To jest wejście, którym nie można wychodzić" - }, - "7": { - "then": "To jest wyjście ewakuacyjne" - }, - "8": { - "then": "To jest wejście do prywatnego domu" - } - }, - "question": "Jakiego rodzaju jest to wejście?" - }, - "automatic_door": { - "mappings": { - "0": { - "then": "Te drzwi są automatyczne" - }, - "1": { - "then": "Te drzwi nie są automatyczne" - }, - "2": { - "then": "Te drzwi automatycznie się otwierają, kiedy zostanie wykryty ruch" - } - } - }, - "kerb-height": { - "freeform": { - "placeholder": "Wysokość progu w drzwiach" - }, - "mappings": { - "0": { - "then": "Te drzwi nie mają progu" - } - } - } - }, - "title": { - "render": "Wejście" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": "metr" - }, - "1": { - "human": "centrymetr" - } - } - } - } - }, - "etymology": { - "tagRenderings": { - "simple etymology": { - "question": "Po czym nazwany jest ten obiekt?", - "render": "Nazwane po {name:etymology}" - }, - "wikipedia": { - "render": "Istnieje artykuł Wikipedii na temat tej ulicy:
{wikipedia():max-height:25rem}" - } - } - }, - "extinguisher": { - "description": "Warstwa mapy pokazująca gaśnice.", - "name": "Mapa gaśnic", - "presets": { - "0": { - "description": "Gaśnica to małe, przenośne urządzenie do gaszenia ognia", - "title": "gaśnica" - } - }, - "tagRenderings": { - "extinguisher-location": { - "mappings": { - "0": { - "then": "Znajduje się wewnątrz budynku." - }, - "1": { - "then": "Znajduje się na dworze." - } - }, - "question": "Gdzie się znajduje?", - "render": "Lokalizacja: {location}" - } - }, - "title": { - "render": "Gaśnice" - } - }, - "filters": { - "filter": { - "0": { - "options": { - "0": { - "question": "Otwarte teraz" - } - } - }, - "1": { - "options": { - "0": { - "question": "Przyjmuje gotówkę" - } - } + "then": "Oparcie: Tak" }, "2": { - "options": { - "0": { - "question": "Przyjmuje karty płatnicze" - } - } + "then": "Oparcie: Nie" + } + }, + "question": "Czy ta ławka ma oparcie?" + }, + "bench-colour": { + "mappings": { + "0": { + "then": "Kolor: brązowy" + }, + "1": { + "then": "Kolor: zielony" + }, + "2": { + "then": "Kolor: szary" }, "3": { - "options": { - "0": { - "question": "Przyjmuje karty debetowe" - } - } + "then": "Kolor: biały" }, "4": { - "options": { - "0": { - "question": "Przyjmuje karty kredytowe" - } - } + "then": "Kolor: czerwony" }, "5": { - "options": { - "0": { - "question": "Z oraz bez zdjęć" - }, - "1": { - "question": "Ma co najmniej jedno zdjęcie" - }, - "2": { - "question": "Prawdopodobnie nie ma zdjęcia" - } - } + "then": "Kolor: czarny" }, "6": { - "options": { - "0": { - "question": "Z wypustkami dla niewidomych" - } - } + "then": "Kolor: niebieski" }, "7": { - "options": { - "0": { - "question": "Z lub bez wypustek dla niewidomych" - }, - "1": { - "question": "Z wypustkami dla niewidomych" - }, - "2": { - "question": "Bez wypustek dla niewidomych" - }, - "3": { - "question": "Brak informacji o wypustkach dla niewidomych" - } - } - } - } - }, - "fixme": { - "name": "Obiekty OSM z znacznikami FIXME", - "tagRenderings": { - "fixme": { - "mappings": { - "0": { - "then": "Ten problem został rozwiązany" - } - }, - "question": "Co jest nie tak z tym obiektem?" - }, - "note": { - "render": "Tekst notatki: {note}" + "then": "Kolor: żółty" } + }, + "question": "Jaki kolor ma ta ławka?", + "render": "Kolor: {colour}" }, - "title": { - "render": "Obiekt OSM z znacznikiem FIXME" - } - }, - "food": { - "deletion": { - "extraDeleteReasons": { - "0": { - "explanation": "{title()} jest zamknięte na stałe" - } - }, - "nonDeleteMappings": { - "0": { - "then": "To tak naprawdę jest pub" - }, - "1": { - "then": "To tak naprawdę jest kawiarnia" - } - } + "bench-direction": { + "question": "W jakim kierunku patrzysz siedząc na ławce?", + "render": "Siedząc na ławce, patrzy się w kierunku {direction}°." }, - "filter": { + "bench-material": { + "mappings": { + "0": { + "then": "Materiał: drewno" + }, "1": { - "options": { - "0": { - "question": "Rezerwacja nie jest wymagana" - } - } + "then": "Materiał: metal" }, "2": { - "options": { - "0": { - "question": "Ma menu wegetariańskie" - }, - "1": { - "question": "Tylko fast-foody" - }, - "2": { - "question": "Tylko restauracje" - } - } + "then": "Materiał: kamień" }, "3": { - "options": { - "0": { - "question": "Ma menu wegańskie" - } - } - } - }, - "name": "Restauracje i fast-foody", - "presets": { - "0": { - "title": "restauracja" - } - }, - "tagRenderings": { - "Cuisine": { - "mappings": { - "0": { - "then": "To jest pizzeria" - }, - "2": { - "then": "Podaje głównie makarony" - }, - "3": { - "then": "To jest stoisko z kebabem" - }, - "5": { - "then": "Są tu podawane burgery" - } - } - }, - "Reservation": { - "mappings": { - "2": { - "then": "W tym miejscu możliwa jest rezerwacja" - }, - "3": { - "then": "Rezerwacja nie jest możliwa w tym miejscu" - } - }, - "question": "Czy w tym miejscu rezerwacja jest wymagana?" - }, - "Vegan (no friture)": { - "mappings": { - "0": { - "then": "Brak dań wegańskich" - }, - "1": { - "then": "Pewne dania wegańskie są dostępne" - }, - "2": { - "then": "Dostępne są dania wegańskie" - }, - "3": { - "then": "Wszystkie dania są wegańskie" - } - } - }, - "Vegetarian (no friture)": { - "mappings": { - "0": { - "then": "Brak dań wegetariańskich" - }, - "1": { - "then": "Pewne dania wegetariańskie są dostępne" - }, - "2": { - "then": "Dostępne są dania wegetariańskie" - }, - "3": { - "then": "Wszystkie dania są wegetariańskie" - } - }, - "question": "Czy ta restauracja ma danie wegetariańskie?" - }, - "friture-oil": { - "mappings": { - "0": { - "then": "Smażenie jest na oleju roślinnym" - }, - "1": { - "then": "Smażenie jest na oleju zwierzęcym" - } - } - } - }, - "title": { - "mappings": { - "0": { - "then": "Restauracja {name}" - } - }, - "render": "Restauracja" - } - }, - "ghost_bike": { - "description": "Warstwa pokazujące miejsca upamiętnienia rowerzystów, którzy zginęli w wypadkach drogowych", - "name": "Duch roweru", - "presets": { - "0": { - "title": "Duch roweru" - } - }, - "tagRenderings": { - "ghost_bike-name": { - "mappings": { - "0": { - "then": "Ku pamięci {name}" - } - } - } - }, - "title": { - "render": "Duch roweru" - } - }, - "indoors": { - "tagRenderings": { - "ref": { - "question": "Jaki jest numer referencyjny tego pomieszczenia?", - "render": "To pomieszczenie ma numer referencyjny {ref}" - } - }, - "title": { - "mappings": { - "0": { - "then": "Wewnętrzne pomieszczenie {name}" - } - } - } - }, - "information_board": { - "description": "Warstwa pokazujące przydrożne tablice informacyjne dla turystów (np. informujące o krajobrazie, budynku, obiekcie, mapa, ...)", - "name": "Tablice informacyjne", - "presets": { - "0": { - "title": "tablica informacyjna" - } - }, - "title": { - "render": "Tablica informacyjna" - } - }, - "kerbs": { - "description": "Warstwa pokazująca krawężniki.", - "filter": { - "0": { - "options": { - "0": { - "question": "Wszystkie rodzaje krawężników" - }, - "1": { - "question": "Podniesiony krawężnik (>3 cm)" - }, - "2": { - "question": "Obniżony krawężnik (~3 cm)" - }, - "4": { - "question": "Brak krawężnika" - }, - "5": { - "question": "Krawężnik z nieznaną wysokością" - } - } - } - }, - "name": "Krawężniki", - "presets": { - "0": { - "title": "krawężnik" - } - }, - "tagRenderings": { - "kerb-height": { - "freeform": { - "placeholder": "Wysokość krawężnika" - }, - "question": "Jaka jest wysokość tego krawężnika?", - "render": "Wysokość krawężnika: {kerb:height}" - }, - "kerb-type": { - "mappings": { - "0": { - "then": "Ten krawężnik jest wyniesiony (>3 cm)" - }, - "1": { - "then": "Ten krawężnik jest obniżony (~3 cm)" - }, - "3": { - "then": "Nie ma tutaj krawężnika" - }, - "4": { - "then": "Jest krawężnik o nieznanej wysokości" - } - }, - "question": "Jaka jest wysokość tego krawężnika?" - }, - "tactile-paving": { - "mappings": { - "0": { - "then": "Ten krawężnik ma wypustki dla niewidomych." - }, - "1": { - "then": "Ten krawężnik nie ma wypustek dla niewidomych." - }, - "2": { - "then": "Ten krawężnik ma wypustki dla niewidomych, ale nieprawidłowe." - } - }, - "question": "Czy na tym krawężniku są wypustki dla niewidomych?" - } - }, - "title": { - "render": "Krawężnik" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": "centymetry", - "humanSingular": "centymetr" - }, - "1": { - "human": "metry", - "humanSingular": "metr" - } - } - } - } - }, - "kindergarten_childcare": { - "name": "Przedszkola i żłobki", - "presets": { - "0": { - "title": "przedszkole" - }, - "1": { - "title": "żłobek" - } - }, - "tagRenderings": { - "capacity": { - "question": "Jak wiele dzieci (maksymalnie) może być tutaj zapisanych?", - "render": "Ta placówka ma miejsce na {capacity} dzieci" - }, - "childcare-type": { - "mappings": { - "0": { - "then": "To jest przedszkole, gdzie małe dzieci otrzymują wczesną edukację." - } - }, - "question": "Jaki to rodzaj placówki?" - }, - "name": { - "question": "Jaka jest nazwa tej placówki?", - "render": "Ta placówka nazywa się {name}" - }, - "opening_hours": { - "override": { - "question": "W jakich godzinach ten żłobek jest otwarty?" - } - } - }, - "title": { - "mappings": { - "0": { - "then": "Przedszkole {name}" - }, - "1": { - "then": "Żłobek {name}" - } - } - } - }, - "last_click": { - "mapRendering": { - "0": { - "label": { - "mappings": { - "0": { - "then": "Utwórz nową notatkę na mapie" - } - }, - "render": "Kliknij tutaj, aby dodać nowy obiekt" - } - } - }, - "title": { - "mappings": { - "0": { - "then": "Dodaj nowy punkt lub dodaj notatkę" - }, - "1": { - "then": "Dodaj nową notatkę" - }, - "2": { - "then": "Dodaj nowy punkt" - } - } - } - }, - "map": { - "description": "Mapa, przeznaczona dla turystów, która jest zainstalowana w przestrzeni publicznej na stałe", - "name": "Mapy", - "presets": { - "0": { - "description": "Dodaj brakującą mapę", - "title": "mapa" - } - }, - "tagRenderings": { - "map-attribution": { - "mappings": { - "0": { - "then": "Źródło, czyli OpenStreetMap, jest w widoczny sposób podane, zawiera informację o licencji ODBL" - } - } - }, - "map-map_source": { - "mappings": { - "0": { - "then": "Ta mapa bazuje na OpenStreetMap" - } - }, - "question": "Na jakich danych bazuje ta mapa?", - "render": "Ta mapa bazuje na {map_source}" - }, - "map_size": { - "mappings": { - "0": { - "then": "Plan pomieszczeń w budynku" - }, - "2": { - "then": "Mapa pokazująca wieś lub niewielkie miasto" - }, - "3": { - "then": " Mapa miasta" - }, - "4": { - "then": "Mapa całego regionu, pokazująca wiele miast i wsi" - } - }, - "question": "Jaki jest rozmiar obszaru pokazanego na tej mapie?" - }, - "map_type": { - "mappings": { - "1": { - "then": "Mapa z wszystkimi ulicami i ścieżkami w danym obszarze.

Ulica w większości mają nazwy; kąty, odległości itp. są poprawne

" - }, - "2": { - "then": "To jest mapa schematyczna.

Mapa-szkic z tylko ważnymi drogami i POI. Kąty, odległości itp. są tylko ilustratywne, niedokładne.

" - } - }, - "question": "Jaki rodzaj mapy jest pokazany?" - } - }, - "title": { - "render": "Mapa" - } - }, - "maproulette": { - "description": "Warstwa pokazująca wszystkie zadania w MapRoulette", - "filter": { - "0": { - "options": { - "0": { - "question": "Pokaż zadania z wszystkimi statusami" - }, - "1": { - "question": "Pokaż zadania, które zostały stworzone" - }, - "6": { - "question": "Pokaż zadania, które są już wykonane" - }, - "7": { - "question": "Pokaż zadania oznaczone jako zbyt trudne" - }, - "8": { - "question": "Pokaż zadania, które są wyłączone" - } - } - }, - "1": { - "options": { - "0": { - "question": "Nazwa wyzwania zawiera {search}" - } - } - }, - "2": { - "options": { - "0": { - "question": "ID wyzwania pasuje do {search}" - } - } - } - }, - "name": "Zadania MapRoulette", - "tagRenderings": { - "mark_duplicate": { - "render": { - "special": { - "message": "Oznacz jako nieznalezione lub fałszywie pozytywne" - } - } - }, - "mark_fixed": { - "render": { - "special": { - "message": "Oznacz jako naprawione" - } - } - }, - "mark_too_hard": { - "render": { - "special": { - "message": "Oznacz jako zbyt trudne" - } - } - }, - "status": { - "mappings": { - "0": { - "then": "Zadanie jest stworzone" - }, - "1": { - "then": "Zadanie jest naprawione" - }, - "2": { - "then": "Zadanie jest fałszywie pozytywne" - }, - "3": { - "then": "Zadanie jest pominięte" - }, - "4": { - "then": "Zadania jest usunięte" - }, - "5": { - "then": "Zadania jest już wykonane" - }, - "6": { - "then": "Zadanie jest oznaczone jako zbyt trudne" - }, - "7": { - "then": "Zadanie jest wyłączone" - } - } - } - }, - "title": { - "render": "Obiekt MapRoulette: {parentName}" - } - }, - "maproulette_challenge": { - "filter": { - "0": { - "options": { - "0": { - "question": "Pokaż zadania z wszystkimi statusami" - }, - "1": { - "question": "Pokaż zadania, które zostały stworzone" - }, - "2": { - "question": "Pokaż zadania, które są już wykonane" - } - } - } - } - }, - "note": { - "title": { - "mappings": { - "0": { - "then": "Zamknięta notatka" - } - }, - "render": "Notatka" - } - }, - "observation_tower": { - "description": "Wieże z panoramicznym widokiem", - "name": "Wieże obserwacyjne", - "tagRenderings": { - "Fee": { - "mappings": { - "0": { - "then": "Darmowe wejście" - } - }, - "question": "Ile kosztuje wstęp na tę wieżę?", - "render": "Wizyta na tej wieży kosztuje {charge}" - }, - "Height": { - "question": "Jaka jest wysokość tej wieży?", - "render": "Ta wieża ma wysokość {height}" - }, - "Operator": { - "question": "Kto obsługuje tę wieżę?", - "render": "Obsługiwana przez {operator}" - }, - "access": { - "mappings": { - "0": { - "then": "Ta wieża jest publicznie dostępna" - }, - "1": { - "then": "Ta wieża można być zwiedzana tylko z przewodnikiem" - } - } - }, - "elevator": { - "mappings": { - "0": { - "then": "Ta wieża ma windę, która zabiera zwiedzających na górę" - }, - "1": { - "then": "Ta wieża nie ma windy" - } - }, - "question": "Czy ta wieża ma windę?" - }, - "name": { - "mappings": { - "0": { - "then": "Ta wieża nie ma określonej nazwy" - } - }, - "question": "Jaka jest nazwa tej wieży?", - "render": "Ta wieża nazywa się {name}" - }, - "step_count": { - "question": "Ile pojedynczych stopni trzeba pokonać, aby dostać się na górę tej wieży?", - "render": "Ta wieża ma {step_count} stopni na górę" - } - }, - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "Wieża obserwacyjna" - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": " metr" - } - } - } - } - }, - "osm_community_index": { - "description": "Warstwa pokazująca społeczności OpenStreetMap", - "filter": { - "0": { - "options": { - "0": { - "question": "Kraj" - } - } - }, - "2": { - "options": { - "0": { - "question": "Region" - } - } + "then": "Materiał: beton" }, "4": { - "options": { - "0": { - "question": "Terytorium" - } - } + "then": "Materiał: plastik" }, "5": { - "options": { - "0": { - "question": "Świat" - } - } + "then": "Materiał: stal" + } + }, + "question": "Z czego wykonana jest ławka (siedzisko)?", + "render": "Materiał: {material}" + }, + "bench-memorial": { + "mappings": { + "0": { + "then": "Ta ławka jest pomnikiem upamiętniającym kogoś lub coś" + }, + "1": { + "then": "Ta ławka nie jest pomnikiem upamiętniającym kogoś lub coś" + } + }, + "question": "Czy ta ławka służy jako pomnik upamiętniający kogoś lub coś?" + }, + "bench-seats": { + "question": "Ile siedzeń ma ta ławka?", + "render": "{seats} siedzeń" + }, + "bench-survey:date": { + "question": "Kiedy ostatnio badano tę ławkę?", + "render": "Ławka ta była ostatnio badana w dniu {survey:date}" + } + }, + "title": { + "render": "Ławka" + } + }, + "bench_at_pt": { + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "Ten przystanek autobusowy nie jest już używany" + } + }, + "nonDeleteMappings": { + "0": { + "then": "Ten przystanek autobusowy nie ma ławki (nigdy jej nie było lub została usunięta)" + } + } + }, + "description": "Warstwa pokazująca wszystkie przystanki transportu publicznego, które mają ławki", + "name": "Ławki na przystankach komunikacji miejskiej", + "tagRenderings": { + "bench_at_pt-name": { + "render": "{name}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Ławka na przystanku komunikacji miejskiej" + } + }, + "render": "Ławka" + } + }, + "bicycle_library": { + "description": "Obiekt, w którym rowery można wypożyczyć na dłuższy okres" + }, + "bicycle_rental": { + "tagRenderings": { + "rental_types": { + "rewrite": { + "into": { + "0": { + "1": "rowery miejskie" + }, + "1": { + "1": "rowery elektryczne" + }, + "2": { + "1": "rowery dla dzieci" + }, + "3": { + "1": "rowery BMX" + }, + "4": { + "1": "rowery górskie" + }, + "6": { + "1": "tandem" + } + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "Wypożyczalnia rowerów" + } + }, + "bike_parking": { + "name": "Parking dla rowerów", + "presets": { + "0": { + "title": "Parking dla rowerów" + } + }, + "tagRenderings": { + "Access": { + "mappings": { + "0": { + "then": "Dostępne publicznie" + } + }, + "question": "Kto może używać tego parkingu dla rowerów?", + "render": "{access}" + }, + "Bicycle parking type": { + "question": "Jaki jest typ tego parkingu dla rowerów?", + "render": "Jest to parking rowerowy typu: {bicycle_parking}" + }, + "Capacity": { + "render": "Miejsce na {capacity} rowerów" + }, + "Underground?": { + "mappings": { + "2": { + "then": "Parking na dachu" + } + }, + "question": "Jaka jest względna lokalizacja tego parkingu rowerowego?" + } + }, + "title": { + "render": "Parking dla rowerów" + } + }, + "bike_repair_station": { + "presets": { + "0": { + "description": "Urządzenie do pompowania opon w stałym miejscu w przestrzeni publicznej.", + "title": "pompka do roweru" + }, + "1": { + "title": "stacja naprawy rowerów i pompka" + } + }, + "tagRenderings": { + "Operational status": { + "mappings": { + "0": { + "then": "Pompka rowerowa jest zepsuta" + }, + "1": { + "then": "Pompka rowerowa jest sprawna" + } + }, + "question": "Czy pompka rowerowa jest nadal sprawna?" + }, + "access": { + "mappings": { + "1": { + "then": "Dostępne publicznie" + }, + "2": { + "then": "Tylko dla klientów" + } + } + }, + "bike_repair_station-electrical_pump": { + "mappings": { + "0": { + "then": "Pompa ręczna" + }, + "1": { + "then": "Pompka elektryczna" + } + }, + "question": "Czy jest to elektryczna pompka do roweru?" + }, + "bike_repair_station-manometer": { + "mappings": { + "0": { + "then": "Jest manometr" + }, + "1": { + "then": "Nie ma manometru" + }, + "2": { + "then": "Jest manometr, ale jest uszkodzony" + } + }, + "question": "Czy pompka posiada wskaźnik ciśnienia lub manometr?" + }, + "bike_repair_station-valves": { + "question": "Jakie zawory są obsługiwane?", + "render": "Ta pompka obsługuje następujące zawory: {valves}" + }, + "send_email_about_broken_pump": { + "render": { + "special": { + "button_text": "Zgłoś, że ta pompka rowerowa jest zepsuta", + "subject": "Zepsuta pompka rowerowa" + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Stacja naprawy rowerów" + }, + "1": { + "then": "Stacja naprawy rowerów" + }, + "2": { + "then": "Zepsuta pompka" + }, + "3": { + "then": "Pompka do rowerów {name}" + }, + "4": { + "then": "Pompka do rowerów" + } + } + } + }, + "bike_shop": { + "tagRenderings": { + "bike_shop-access": { + "render": "Dostępne tylko dla {access}" + } + } + }, + "bike_themed_object": { + "name": "Obiekt związany z rowerami", + "title": { + "render": "Obiekt związany z rowerami" + } + }, + "birdhide": { + "name": "Miejsca do obserwacji ptaków", + "tagRenderings": { + "bird-hide-wheelchair": { + "mappings": { + "3": { + "then": "Niedostępne dla osób na wózkach" + } + } + }, + "birdhide-operator": { + "mappings": { + "0": { + "then": "Obsługiwane przez Natuurpunt" + } + }, + "render": "Obsługiwane przez {operator}" + } + } + }, + "cafe_pub": { + "name": "Kawiarnie i puby", + "presets": { + "0": { + "title": "pub" + }, + "1": { + "title": "bar" + }, + "2": { + "title": "Kawiarnia" + }, + "3": { + "title": "klub nocny lub dyskoteka" + } + }, + "tagRenderings": { + "Classification": { + "question": "Jakiego rodzaju jest to kawiarnia?" + } + }, + "title": { + "render": "Pub" + } + }, + "car_rental": { + "description": "Miejsca, w których można wypożyczyć samochód", + "name": "Wypożyczalnia samochodów", + "presets": { + "0": { + "description": "Miejsce, w którym można wypożyczyć samochód", + "title": "wypożyczalnia samochodów" + } + }, + "tagRenderings": { + "name": { + "freeform": { + "placeholder": "Nazwa wypożyczalni samochodów" + }, + "mappings": { + "0": { + "then": "Ta wypożyczalnia samochodów nie ma nazwy" + } + }, + "question": "Jaka jest nazwa tej wypożyczalni samochodów?", + "render": "Ta wypożyczalnia samochodów nazywa się {name}" + } + }, + "title": { + "render": "Wypożyczalnia samochodów" + } + }, + "charging_station": { + "description": "Stacja ładowania", + "filter": { + "0": { + "options": { + "0": { + "question": "Wszystkie rodzaje pojazdów" + }, + "1": { + "question": "Stacja ładowania dla rowerów" + }, + "2": { + "question": "Stacja ładowania dla samochodów" + } + } + }, + "1": { + "options": { + "0": { + "question": "Tylko działające stacje ładowania" + } + } + } + }, + "name": "Stacje ładowania", + "presets": { + "1": { + "title": "stacja ładowania dla samochodów" + } + }, + "tagRenderings": { + "Available_charging_stations (generated)": { + "mappings": { + "13": { + "then": "Tesla Supercharger" + } + } + }, + "Network": { + "mappings": { + "1": { + "then": "Nie jest częścią większej sieci" + } + }, + "question": "Czy ta stacja ładowania jest częścią sieci?" + }, + "OH": { + "override": { + "question": "Kiedy otwiera się ta stacja ładowania?" + } + }, + "Operational status": { + "mappings": { + "0": { + "then": "Ta stacja ładowania działa" + }, + "1": { + "then": "Ta stacja ładowania jest zepsuta" + }, + "2": { + "then": "Planowana jest tutaj stacja ładowania" + }, + "3": { + "then": "Budowana jest tutaj stacja ładowania" + } + } + }, + "Operator": { + "render": "Ta stacja ładowania jest obsługiwana przez {operator}" + } + }, + "title": { + "render": "Stacja ładowania" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " minut", + "humanSingular": " minuta" + }, + "1": { + "human": " godzin", + "humanSingular": " godzina" + }, + "2": { + "human": " dni", + "humanSingular": " dzień" + } + } + } + } + }, + "climbing_gym": { + "tagRenderings": { + "shoe_rental": { + "mappings": { + "2": { + "then": "Można tutaj wypożyczyć buty do wspinaczki" + }, + "3": { + "then": "Nie można wypożyczyć tutaj butów do wspinaczki" + } + }, + "question": "Czy można tutaj wypożyczyć buty do wspinaczki?" + } + } + }, + "climbing_opportunity": { + "tagRenderings": { + "climbing-opportunity-name": { + "render": "{name}" + } + } + }, + "clock": { + "presets": { + "0": { + "title": "zegar" + }, + "1": { + "description": "Publicznie widoczny zegar zamontowany na ścianie", + "title": "zegar na ścianie" + } + }, + "tagRenderings": { + "barometer": { + "mappings": { + "0": { + "then": "Ten zegar wyświetla również ciśnienie" + }, + "1": { + "then": "Ten zegar nie wyświetla ciśnienia" + }, + "2": { + "then": "Ten zegar prawdopodobnie nie wyświetla ciśnienia" + } + }, + "question": "Czy ten zegar wyświetla ciśnienie?" + }, + "date": { + "mappings": { + "0": { + "then": "Ten zegar wyświetla również datę" + }, + "1": { + "then": "Ten zegar nie wyświetla daty" + }, + "2": { + "then": "Ten zegar prawdopodobnie nie wyświetla daty" + } + }, + "question": "Czy ten zegar wyświetla datę?" + }, + "display": { + "mappings": { + "0": { + "then": "Ten zegar pokazuje czas za pomocą wskazówek" + }, + "1": { + "then": "Ten zegar wyświetla czas za pomocą cyfr" + }, + "3": { + "then": "Ten zegar wyświetla czas w niestandardowy sposób, np. używając systemu binarnego, wody lub czegoś innego" + } + }, + "question": "Jak ten zegar wyświetla czas?" + }, + "hygrometer": { + "mappings": { + "0": { + "then": "Ten zegar wyświetla również wilgotność" + }, + "1": { + "then": "Ten zegar nie wyświetla wilgotności" + }, + "2": { + "then": "Ten zegar prawdopodobnie nie wyświetla wilgotności" + } + }, + "question": "Czy ten zegar wyświetla również wilgotność?" + }, + "support": { + "mappings": { + "0": { + "then": "Ten zegar jest zamontowany na słupie" + }, + "1": { + "then": "Ten zegar jest zamontowany na ścianie" + }, + "2": { + "then": "Ten zegar jest częścią bilbordu" + }, + "3": { + "then": "Ten zegar jest na ziemi" + } + }, + "question": "W jaki sposób zamontowany jest ten zegar?" + }, + "thermometer": { + "mappings": { + "0": { + "then": "Ten zegar wyświetla również temperaturę" + }, + "1": { + "then": "Ten zegar nie wyświetla temperatury" + }, + "2": { + "then": "Ten zegar prawdopodobnie nie wyświetla temperatury" + } + }, + "question": "Czy ten zegar wyświetla również temperaturę?" + }, + "visibility": { + "mappings": { + "0": { + "then": "Ten zegar jest widoczny z około 5 metrów (mały zegar ścienny)" + }, + "1": { + "then": "Ten zegar jest widoczny z około 20 metrów (średniej wielkości zegar na bilbordzie)" + }, + "2": { + "then": "Ten zegar jest widoczny z ponad 20 metrów (np. zegar kościelny lub stacyjny)" + } + }, + "question": "Jaka jest widoczność tego zegara?" + } + }, + "title": { + "render": "Zegar" + } + }, + "crossings": { + "tagRenderings": { + "crossing-is-zebra": { + "question": "Czy to jest przejście dla pieszych typu \"zebra\"?" + } + } + }, + "cycleways_and_roads": { + "tagRenderings": { + "Maxspeed (for road)": { + "mappings": { + "0": { + "then": "Maksymalna prędkość tutaj to 20 km/h" + }, + "1": { + "then": "Maksymalna prędkość tutaj to 30 km/h" + }, + "2": { + "then": "Maksymalna prędkość tutaj to 50 km/h" + }, + "3": { + "then": "Maksymalna prędkość tutaj to 70 km/h" + }, + "4": { + "then": "Maksymalna prędkość tutaj to 90 km/h" + } + }, + "question": "Jaka jest maksymalna prędkość na tej ulicy?", + "render": "Maksymalna prędkość na tej drodze to {maxspeed} km/h" + }, + "is lit?": { + "mappings": { + "0": { + "then": "Ta ulica jest oświetlona" + }, + "1": { + "then": "Ta droga nie jest oświetlona" + }, + "2": { + "then": "Ta droga jest oświetlona w nocy" + }, + "3": { + "then": "Ta droga jest oświetlona 24/7" + } + }, + "question": "Czy ta ulica jest oświetlona?" + } + }, + "title": { + "mappings": { + "5": { + "then": "Pas rowerowy" + } + } + } + }, + "defibrillator": { + "presets": { + "0": { + "title": "defibrylator" + }, + "1": { + "title": "defibrylator na ścianie" + } + }, + "tagRenderings": { + "defibrillator-access": { + "mappings": { + "0": { + "then": "Dostępny publicznie" + }, + "1": { + "then": "Dostępny publicznie" + }, + "2": { + "then": "Dostępny tylko dla klientów" + }, + "3": { + "then": "Niedostępny publicznie (np. dostępny tylko dla personelu, właścicieli, ...)" + }, + "4": { + "then": "Niedostępny, być może tylko do profesjonalnego użytku" + } + }, + "question": "Czy ten defibrylator jest swobodnie dostępny?" + }, + "defibrillator-defibrillator": { + "mappings": { + "0": { + "then": "Nie ma informacji o rodzaju urządzenia" + }, + "1": { + "then": "To jest ręczny defibrylator dla profesjonalistów" + }, + "2": { + "then": "To jest zwykły automatyczny defibrylator" + }, + "3": { + "then": "To jest specjalny rodzaj defibrylatora: {defibrillator}" + } + }, + "question": "Czy to jest zwykły automatyczny defibrylator czy ręczny defibrylator tylko dla profesjonalistów?" + }, + "defibrillator-defibrillator:location": { + "question": "Proszę podaj opis gdzie znajduje się defibrylator (w lokalnym języku)", + "render": "Dodatkowe informacje o lokalizacji (w lokalnym języku):
{defibrillator:location}" + }, + "defibrillator-defibrillator:location:en": { + "question": "Proszę podaj opis gdzie znajduje się defibrylator (po angielsku)", + "render": "Dodatkowe informacje o lokalizacji (po angielsku):
{defibrillator:location:en}" + }, + "defibrillator-defibrillator:location:fr": { + "question": "Proszę podaj opis gdzie znajduje się defibrylator (po francusku)", + "render": "Dodatkowe informacje o lokalizacji (po francusku):
{defibrillator:location:fr}" + }, + "defibrillator-description": { + "render": "Dodatkowe informacje: {description}" + }, + "defibrillator-fixme": { + "render": "Więcej informacji dla doświadczonych użytkowników OpenStreetMap: {fixme}" + }, + "defibrillator-indoors": { + "mappings": { + "0": { + "then": "Ten defibrylator jest wewnątrz budynku" + }, + "1": { + "then": "Ten defibrylator jest na dworze" + } + }, + "question": "Czy ten defibrylator znajduje się wewnątrz budynku?" + }, + "defibrillator-level": { + "mappings": { + "0": { + "then": "Ten defibrylator jest na parterze" + }, + "1": { + "then": "Ten defibrylator jest na pierwszym piętrze" + } + }, + "question": "Na którym piętrze jest ten defibrylator?", + "render": "Ten defibrylator jest na piętrze {level}" + }, + "defibrillator-ref": { + "render": "Oficjalny numer identyfikacyjny urządzenia: {ref}" + }, + "defibrillator-survey:date": { + "mappings": { + "0": { + "then": "Sprawdzone dzisiaj!" + } + } + }, + "opening_hours_24_7": { + "override": { + "question": "W jakich godzinach dostępny jest ten defibrylator?" + } + } + }, + "title": { + "render": "Defibrylator" + } + }, + "dentist": { + "description": "Ta warstwa pokazuje gabinety dentystyczne", + "name": "Dentysta", + "tagRenderings": { + "name": { + "question": "Jaka jest nazwa tego gabinetu dentystycznego?", + "render": "Nazwa tego gabinetu dentystycznego to {name}" + } + } + }, + "doctors": { + "tagRenderings": { + "specialty": { + "mappings": { + "1": { + "then": "To jest ginekolog" + }, + "2": { + "then": "To jest psychiatra" + }, + "3": { + "then": "To jest pediatra" + } + }, + "question": "W czym specjalizuje się ten lekarz?", + "render": "Ten lekarz specjalizuje się w {healthcare:speciality}" + } + } + }, + "elevator": { + "name": "Winda", + "presets": { + "0": { + "title": "winda" + } + }, + "tagRenderings": { + "door-width": { + "question": "Jaka jest szerokość drzwi windy?", + "render": "Drzwi tej windy mają szerokość {canonical(door:width)}" + }, + "elevator-width": { + "question": "Jaka jest szerokość tej windy?", + "render": "Szerokość tej windy to {canonical(elevator:width)}" + }, + "operational_status": { + "mappings": { + "0": { + "then": "Ta winda jest zepsuta" + }, + "1": { + "then": "Ta winda jest nieczynna np. z powodu renowacji" + }, + "2": { + "then": "Ta winda działa" + }, + "3": { + "then": "Ta winda działa" + } + }, + "question": "Czy ta winda działa?" + } + }, + "title": { + "render": "Winda" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": "metr" + }, + "1": { + "human": "centymetr" + } + } + } + } + }, + "elongated_coin": { + "tagRenderings": { + "coin": { + "freeform": { + "placeholder": "Rodzaj monety (np. 10 centów)" + } + } + } + }, + "entrance": { + "tagRenderings": { + "Entrance type": { + "mappings": { + "2": { + "then": "To jest główne wejście" + }, + "4": { + "then": "To jest wejście serwisowe - zazwyczaj używane tylko przez pracowników, dostawy, …" + }, + "5": { + "then": "To jest wyjście bez możliwości wejścia" }, "6": { - "options": { - "0": { - "question": "Inne społeczności" - } - } + "then": "To jest wejście, którym nie można wychodzić" + }, + "7": { + "then": "To jest wyjście ewakuacyjne" + }, + "8": { + "then": "To jest wejście do prywatnego domu" } + }, + "question": "Jakiego rodzaju jest to wejście?" }, - "name": "Indeks społeczności OSM", - "title": { - "render": "Indeks społeczności OSM" + "automatic_door": { + "mappings": { + "0": { + "then": "Te drzwi są automatyczne" + }, + "1": { + "then": "Te drzwi nie są automatyczne" + }, + "2": { + "then": "Te drzwi automatycznie się otwierają, kiedy zostanie wykryty ruch" + } + } + }, + "kerb-height": { + "freeform": { + "placeholder": "Wysokość progu w drzwiach" + }, + "mappings": { + "0": { + "then": "Te drzwi nie mają progu" + } + } } + }, + "title": { + "render": "Wejście" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": "metr" + }, + "1": { + "human": "centrymetr" + } + } + } + } + }, + "etymology": { + "tagRenderings": { + "simple etymology": { + "question": "Po czym nazwany jest ten obiekt?", + "render": "Nazwane po {name:etymology}" + }, + "wikipedia": { + "render": "Istnieje artykuł Wikipedii na temat tej ulicy:
{wikipedia():max-height:25rem}" + } + } + }, + "extinguisher": { + "description": "Warstwa mapy pokazująca gaśnice.", + "name": "Mapa gaśnic", + "presets": { + "0": { + "description": "Gaśnica to małe, przenośne urządzenie do gaszenia ognia", + "title": "gaśnica" + } + }, + "tagRenderings": { + "extinguisher-location": { + "mappings": { + "0": { + "then": "Znajduje się wewnątrz budynku." + }, + "1": { + "then": "Znajduje się na dworze." + } + }, + "question": "Gdzie się znajduje?", + "render": "Lokalizacja: {location}" + } + }, + "title": { + "render": "Gaśnice" + } + }, + "filters": { + "filter": { + "0": { + "options": { + "0": { + "question": "Otwarte teraz" + } + } + }, + "1": { + "options": { + "0": { + "question": "Przyjmuje gotówkę" + } + } + }, + "2": { + "options": { + "0": { + "question": "Przyjmuje karty płatnicze" + } + } + }, + "3": { + "options": { + "0": { + "question": "Przyjmuje karty debetowe" + } + } + }, + "4": { + "options": { + "0": { + "question": "Przyjmuje karty kredytowe" + } + } + }, + "5": { + "options": { + "0": { + "question": "Z oraz bez zdjęć" + }, + "1": { + "question": "Ma co najmniej jedno zdjęcie" + }, + "2": { + "question": "Prawdopodobnie nie ma zdjęcia" + } + } + }, + "6": { + "options": { + "0": { + "question": "Z wypustkami dla niewidomych" + } + } + }, + "7": { + "options": { + "0": { + "question": "Z lub bez wypustek dla niewidomych" + }, + "1": { + "question": "Z wypustkami dla niewidomych" + }, + "2": { + "question": "Bez wypustek dla niewidomych" + }, + "3": { + "question": "Brak informacji o wypustkach dla niewidomych" + } + } + } + } + }, + "fixme": { + "name": "Obiekty OSM z znacznikami FIXME", + "tagRenderings": { + "fixme": { + "mappings": { + "0": { + "then": "Ten problem został rozwiązany" + } + }, + "question": "Co jest nie tak z tym obiektem?" + }, + "note": { + "render": "Tekst notatki: {note}" + } + }, + "title": { + "render": "Obiekt OSM z znacznikiem FIXME" + } + }, + "food": { + "deletion": { + "extraDeleteReasons": { + "0": { + "explanation": "{title()} jest zamknięte na stałe" + } + }, + "nonDeleteMappings": { + "0": { + "then": "To tak naprawdę jest pub" + }, + "1": { + "then": "To tak naprawdę jest kawiarnia" + } + } + }, + "filter": { + "1": { + "options": { + "0": { + "question": "Rezerwacja nie jest wymagana" + } + } + }, + "2": { + "options": { + "0": { + "question": "Ma menu wegetariańskie" + }, + "1": { + "question": "Tylko fast-foody" + }, + "2": { + "question": "Tylko restauracje" + } + } + }, + "3": { + "options": { + "0": { + "question": "Ma menu wegańskie" + } + } + } + }, + "name": "Restauracje i fast-foody", + "presets": { + "0": { + "title": "restauracja" + } + }, + "tagRenderings": { + "Cuisine": { + "mappings": { + "0": { + "then": "To jest pizzeria" + }, + "2": { + "then": "Podaje głównie makarony" + }, + "3": { + "then": "To jest stoisko z kebabem" + }, + "5": { + "then": "Są tu podawane burgery" + } + } + }, + "Reservation": { + "mappings": { + "2": { + "then": "W tym miejscu możliwa jest rezerwacja" + }, + "3": { + "then": "Rezerwacja nie jest możliwa w tym miejscu" + } + }, + "question": "Czy w tym miejscu rezerwacja jest wymagana?" + }, + "Vegan (no friture)": { + "mappings": { + "0": { + "then": "Brak dań wegańskich" + }, + "1": { + "then": "Pewne dania wegańskie są dostępne" + }, + "2": { + "then": "Dostępne są dania wegańskie" + }, + "3": { + "then": "Wszystkie dania są wegańskie" + } + } + }, + "Vegetarian (no friture)": { + "mappings": { + "0": { + "then": "Brak dań wegetariańskich" + }, + "1": { + "then": "Pewne dania wegetariańskie są dostępne" + }, + "2": { + "then": "Dostępne są dania wegetariańskie" + }, + "3": { + "then": "Wszystkie dania są wegetariańskie" + } + }, + "question": "Czy ta restauracja ma danie wegetariańskie?" + }, + "friture-oil": { + "mappings": { + "0": { + "then": "Smażenie jest na oleju roślinnym" + }, + "1": { + "then": "Smażenie jest na oleju zwierzęcym" + } + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Restauracja {name}" + } + }, + "render": "Restauracja" + } + }, + "ghost_bike": { + "description": "Warstwa pokazujące miejsca upamiętnienia rowerzystów, którzy zginęli w wypadkach drogowych", + "name": "Duch roweru", + "presets": { + "0": { + "title": "Duch roweru" + } + }, + "tagRenderings": { + "ghost_bike-name": { + "mappings": { + "0": { + "then": "Ku pamięci {name}" + } + } + } + }, + "title": { + "render": "Duch roweru" + } + }, + "indoors": { + "tagRenderings": { + "ref": { + "question": "Jaki jest numer referencyjny tego pomieszczenia?", + "render": "To pomieszczenie ma numer referencyjny {ref}" + } + }, + "title": { + "mappings": { + "0": { + "then": "Wewnętrzne pomieszczenie {name}" + } + } + } + }, + "information_board": { + "description": "Warstwa pokazujące przydrożne tablice informacyjne dla turystów (np. informujące o krajobrazie, budynku, obiekcie, mapa, ...)", + "name": "Tablice informacyjne", + "presets": { + "0": { + "title": "tablica informacyjna" + } + }, + "title": { + "render": "Tablica informacyjna" + } + }, + "kerbs": { + "description": "Warstwa pokazująca krawężniki.", + "filter": { + "0": { + "options": { + "0": { + "question": "Wszystkie rodzaje krawężników" + }, + "1": { + "question": "Podniesiony krawężnik (>3 cm)" + }, + "2": { + "question": "Obniżony krawężnik (~3 cm)" + }, + "4": { + "question": "Brak krawężnika" + }, + "5": { + "question": "Krawężnik z nieznaną wysokością" + } + } + } + }, + "name": "Krawężniki", + "presets": { + "0": { + "title": "krawężnik" + } + }, + "tagRenderings": { + "kerb-height": { + "freeform": { + "placeholder": "Wysokość krawężnika" + }, + "question": "Jaka jest wysokość tego krawężnika?", + "render": "Wysokość krawężnika: {kerb:height}" + }, + "kerb-type": { + "mappings": { + "0": { + "then": "Ten krawężnik jest wyniesiony (>3 cm)" + }, + "1": { + "then": "Ten krawężnik jest obniżony (~3 cm)" + }, + "3": { + "then": "Nie ma tutaj krawężnika" + }, + "4": { + "then": "Jest krawężnik o nieznanej wysokości" + } + }, + "question": "Jaka jest wysokość tego krawężnika?" + }, + "tactile-paving": { + "mappings": { + "0": { + "then": "Ten krawężnik ma wypustki dla niewidomych." + }, + "1": { + "then": "Ten krawężnik nie ma wypustek dla niewidomych." + }, + "2": { + "then": "Ten krawężnik ma wypustki dla niewidomych, ale nieprawidłowe." + } + }, + "question": "Czy na tym krawężniku są wypustki dla niewidomych?" + } + }, + "title": { + "render": "Krawężnik" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": "centymetry", + "humanSingular": "centymetr" + }, + "1": { + "human": "metry", + "humanSingular": "metr" + } + } + } + } + }, + "kindergarten_childcare": { + "name": "Przedszkola i żłobki", + "presets": { + "0": { + "title": "przedszkole" + }, + "1": { + "title": "żłobek" + } + }, + "tagRenderings": { + "capacity": { + "question": "Jak wiele dzieci (maksymalnie) może być tutaj zapisanych?", + "render": "Ta placówka ma miejsce na {capacity} dzieci" + }, + "childcare-type": { + "mappings": { + "0": { + "then": "To jest przedszkole, gdzie małe dzieci otrzymują wczesną edukację." + } + }, + "question": "Jaki to rodzaj placówki?" + }, + "name": { + "question": "Jaka jest nazwa tej placówki?", + "render": "Ta placówka nazywa się {name}" + }, + "opening_hours": { + "override": { + "question": "W jakich godzinach ten żłobek jest otwarty?" + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Przedszkole {name}" + }, + "1": { + "then": "Żłobek {name}" + } + } + } + }, + "last_click": { + "mapRendering": { + "0": { + "label": { + "mappings": { + "0": { + "then": "Utwórz nową notatkę na mapie" + } + }, + "render": "Kliknij tutaj, aby dodać nowy obiekt" + } + } + }, + "title": { + "mappings": { + "0": { + "then": "Dodaj nowy punkt lub dodaj notatkę" + }, + "1": { + "then": "Dodaj nową notatkę" + }, + "2": { + "then": "Dodaj nowy punkt" + } + } + } + }, + "map": { + "description": "Mapa, przeznaczona dla turystów, która jest zainstalowana w przestrzeni publicznej na stałe", + "name": "Mapy", + "presets": { + "0": { + "description": "Dodaj brakującą mapę", + "title": "mapa" + } + }, + "tagRenderings": { + "map-attribution": { + "mappings": { + "0": { + "then": "Źródło, czyli OpenStreetMap, jest w widoczny sposób podane, zawiera informację o licencji ODBL" + } + } + }, + "map-map_source": { + "mappings": { + "0": { + "then": "Ta mapa bazuje na OpenStreetMap" + } + }, + "question": "Na jakich danych bazuje ta mapa?", + "render": "Ta mapa bazuje na {map_source}" + }, + "map_size": { + "mappings": { + "0": { + "then": "Plan pomieszczeń w budynku" + }, + "2": { + "then": "Mapa pokazująca wieś lub niewielkie miasto" + }, + "3": { + "then": " Mapa miasta" + }, + "4": { + "then": "Mapa całego regionu, pokazująca wiele miast i wsi" + } + }, + "question": "Jaki jest rozmiar obszaru pokazanego na tej mapie?" + }, + "map_type": { + "mappings": { + "1": { + "then": "Mapa z wszystkimi ulicami i ścieżkami w danym obszarze.

Ulica w większości mają nazwy; kąty, odległości itp. są poprawne

" + }, + "2": { + "then": "To jest mapa schematyczna.

Mapa-szkic z tylko ważnymi drogami i POI. Kąty, odległości itp. są tylko ilustratywne, niedokładne.

" + } + }, + "question": "Jaki rodzaj mapy jest pokazany?" + } + }, + "title": { + "render": "Mapa" + } + }, + "maproulette": { + "description": "Warstwa pokazująca wszystkie zadania w MapRoulette", + "filter": { + "0": { + "options": { + "0": { + "question": "Pokaż zadania z wszystkimi statusami" + }, + "1": { + "question": "Pokaż zadania, które zostały stworzone" + }, + "6": { + "question": "Pokaż zadania, które są już wykonane" + }, + "7": { + "question": "Pokaż zadania oznaczone jako zbyt trudne" + }, + "8": { + "question": "Pokaż zadania, które są wyłączone" + } + } + }, + "1": { + "options": { + "0": { + "question": "Nazwa wyzwania zawiera {search}" + } + } + }, + "2": { + "options": { + "0": { + "question": "ID wyzwania pasuje do {search}" + } + } + } + }, + "name": "Zadania MapRoulette", + "tagRenderings": { + "mark_duplicate": { + "render": { + "special": { + "message": "Oznacz jako nieznalezione lub fałszywie pozytywne" + } + } + }, + "mark_fixed": { + "render": { + "special": { + "message": "Oznacz jako naprawione" + } + } + }, + "mark_too_hard": { + "render": { + "special": { + "message": "Oznacz jako zbyt trudne" + } + } + }, + "status": { + "mappings": { + "0": { + "then": "Zadanie jest stworzone" + }, + "1": { + "then": "Zadanie jest naprawione" + }, + "2": { + "then": "Zadanie jest fałszywie pozytywne" + }, + "3": { + "then": "Zadanie jest pominięte" + }, + "4": { + "then": "Zadania jest usunięte" + }, + "5": { + "then": "Zadania jest już wykonane" + }, + "6": { + "then": "Zadanie jest oznaczone jako zbyt trudne" + }, + "7": { + "then": "Zadanie jest wyłączone" + } + } + } + }, + "title": { + "render": "Obiekt MapRoulette: {parentName}" + } + }, + "maproulette_challenge": { + "filter": { + "0": { + "options": { + "0": { + "question": "Pokaż zadania z wszystkimi statusami" + }, + "1": { + "question": "Pokaż zadania, które zostały stworzone" + }, + "2": { + "question": "Pokaż zadania, które są już wykonane" + } + } + } + } + }, + "note": { + "title": { + "mappings": { + "0": { + "then": "Zamknięta notatka" + } + }, + "render": "Notatka" + } + }, + "observation_tower": { + "description": "Wieże z panoramicznym widokiem", + "name": "Wieże obserwacyjne", + "tagRenderings": { + "Fee": { + "mappings": { + "0": { + "then": "Darmowe wejście" + } + }, + "question": "Ile kosztuje wstęp na tę wieżę?", + "render": "Wizyta na tej wieży kosztuje {charge}" + }, + "Height": { + "question": "Jaka jest wysokość tej wieży?", + "render": "Ta wieża ma wysokość {height}" + }, + "Operator": { + "question": "Kto obsługuje tę wieżę?", + "render": "Obsługiwana przez {operator}" + }, + "access": { + "mappings": { + "0": { + "then": "Ta wieża jest publicznie dostępna" + }, + "1": { + "then": "Ta wieża można być zwiedzana tylko z przewodnikiem" + } + } + }, + "elevator": { + "mappings": { + "0": { + "then": "Ta wieża ma windę, która zabiera zwiedzających na górę" + }, + "1": { + "then": "Ta wieża nie ma windy" + } + }, + "question": "Czy ta wieża ma windę?" + }, + "name": { + "mappings": { + "0": { + "then": "Ta wieża nie ma określonej nazwy" + } + }, + "question": "Jaka jest nazwa tej wieży?", + "render": "Ta wieża nazywa się {name}" + }, + "step_count": { + "question": "Ile pojedynczych stopni trzeba pokonać, aby dostać się na górę tej wieży?", + "render": "Ta wieża ma {step_count} stopni na górę" + } + }, + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "Wieża obserwacyjna" + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": " metr" + } + } + } + } + }, + "osm_community_index": { + "description": "Warstwa pokazująca społeczności OpenStreetMap", + "filter": { + "0": { + "options": { + "0": { + "question": "Kraj" + } + } + }, + "2": { + "options": { + "0": { + "question": "Region" + } + } + }, + "4": { + "options": { + "0": { + "question": "Terytorium" + } + } + }, + "5": { + "options": { + "0": { + "question": "Świat" + } + } + }, + "6": { + "options": { + "0": { + "question": "Inne społeczności" + } + } + } + }, + "name": "Indeks społeczności OSM", + "title": { + "render": "Indeks społeczności OSM" + } }, "parcel_lockers": { - "description": "Warstwa pokazująca paczkomaty umożliwiające odbieranie i wysyłanie przesyłek.", - "name": "Paczkomaty", - "presets": { - "0": { - "title": "paczkomat" - } - }, - "tagRenderings": { - "brand": { - "freeform": { - "placeholder": "Marka" - }, - "mappings": { - "0": { - "then": "To jest paczkomat Amazonu" - }, - "3": { - "then": "To jest paczkomat PostNL" - } - }, - "question": "Jakiej marki jest ten paczkomat?", - "render": "To jest paczkomat marki {brand}" - }, - "mail-in": { - "mappings": { - "0": { - "then": "Z tego paczkomatu można wysyłać przesyłki" - }, - "1": { - "then": "Z tego paczkomatu nie można wysyłać przesyłek" - } - }, - "question": "Czy z tego paczkomatu można wysyłać przesyłki?" - }, - "operator": { - "freeform": { - "placeholder": "Operator" - }, - "render": "Ten paczkomat jest obsługiwany przez {operator}" - }, - "pickup": { - "mappings": { - "0": { - "then": "Z tego paczkomatu można odbierać przesyłki" - }, - "1": { - "then": "Z tego paczkomatu nie można odbierać przesyłek" - } - }, - "question": "Czy z tego paczkomatu można odbierać przesyłki?" - } - }, - "title": { - "mappings": { - "0": { - "then": "Paczkomat {brand}" - } - }, - "render": "Paczkomat" + "description": "Warstwa pokazująca paczkomaty umożliwiające odbieranie i wysyłanie przesyłek.", + "name": "Paczkomaty", + "presets": { + "0": { + "title": "paczkomat" } + }, + "tagRenderings": { + "brand": { + "freeform": { + "placeholder": "Marka" + }, + "mappings": { + "0": { + "then": "To jest paczkomat Amazonu" + }, + "3": { + "then": "To jest paczkomat PostNL" + } + }, + "question": "Jakiej marki jest ten paczkomat?", + "render": "To jest paczkomat marki {brand}" + }, + "mail-in": { + "mappings": { + "0": { + "then": "Z tego paczkomatu można wysyłać przesyłki" + }, + "1": { + "then": "Z tego paczkomatu nie można wysyłać przesyłek" + } + }, + "question": "Czy z tego paczkomatu można wysyłać przesyłki?" + }, + "operator": { + "freeform": { + "placeholder": "Operator" + }, + "render": "Ten paczkomat jest obsługiwany przez {operator}" + }, + "pickup": { + "mappings": { + "0": { + "then": "Z tego paczkomatu można odbierać przesyłki" + }, + "1": { + "then": "Z tego paczkomatu nie można odbierać przesyłek" + } + }, + "question": "Czy z tego paczkomatu można odbierać przesyłki?" + } + }, + "title": { + "mappings": { + "0": { + "then": "Paczkomat {brand}" + } + }, + "render": "Paczkomat" + } }, "parking": { - "description": "Warstwa pokazująca parkingi samochodowe", - "name": "Parking", - "presets": { - "0": { - "title": "parking samochodowy" - } - }, - "tagRenderings": { - "capacity": { - "freeform": { - "placeholder": "Liczba miejsc parkingowych" - }, - "question": "Ile miejsc parkingowych jest na tym parkingu?", - "render": "Jest {capacity} miejsc parkingowych" - }, - "capacity-disabled": { - "freeform": { - "placeholder": "Liczba miejsc parkingowych przeznaczonych dla niepełnosprawnych" - }, - "mappings": { - "0": { - "then": "Są tutaj miejsca parkingowe dla niepełnosprawnych, ale nie wiadomo ile" - }, - "1": { - "then": "Nie ma tutaj żadnych miejsc parkingowych dla niepełnosprawnych" - }, - "2": { - "then": "Nie ma tutaj żadnych miejsc parkingowych dla niepełnosprawnych" - } - }, - "question": "Jak wiele miejsc parkingowych dla niepełnosprawnych znajduje się na tym parkingu?", - "render": "Jest {capacity:disabled} miejsc parkingowych dla niepełnosprawnych" - }, - "parking-type": { - "mappings": { - "2": { - "then": "To jest podziemny parking" - }, - "3": { - "then": "To jest wielopiętrowy parking" - }, - "5": { - "then": "To jest pas do parkowania na jezdni" - } - }, - "question": "Jaki to rodzaj parkingu?" - } - }, - "title": { - "render": "Parking samochodowy" + "description": "Warstwa pokazująca parkingi samochodowe", + "name": "Parking", + "presets": { + "0": { + "title": "parking samochodowy" } + }, + "tagRenderings": { + "capacity": { + "freeform": { + "placeholder": "Liczba miejsc parkingowych" + }, + "question": "Ile miejsc parkingowych jest na tym parkingu?", + "render": "Jest {capacity} miejsc parkingowych" + }, + "capacity-disabled": { + "freeform": { + "placeholder": "Liczba miejsc parkingowych przeznaczonych dla niepełnosprawnych" + }, + "mappings": { + "0": { + "then": "Są tutaj miejsca parkingowe dla niepełnosprawnych, ale nie wiadomo ile" + }, + "1": { + "then": "Nie ma tutaj żadnych miejsc parkingowych dla niepełnosprawnych" + }, + "2": { + "then": "Nie ma tutaj żadnych miejsc parkingowych dla niepełnosprawnych" + } + }, + "question": "Jak wiele miejsc parkingowych dla niepełnosprawnych znajduje się na tym parkingu?", + "render": "Jest {capacity:disabled} miejsc parkingowych dla niepełnosprawnych" + }, + "parking-type": { + "mappings": { + "2": { + "then": "To jest podziemny parking" + }, + "3": { + "then": "To jest wielopiętrowy parking" + }, + "5": { + "then": "To jest pas do parkowania na jezdni" + } + }, + "question": "Jaki to rodzaj parkingu?" + } + }, + "title": { + "render": "Parking samochodowy" + } }, "parking_spaces": { - "description": "Warstwa pokazująca pojedyncze miejsca parkingowe.", - "name": "Miejsca parkingowe", - "tagRenderings": { - "type": { - "mappings": { - "0": { - "then": "To jest zwykłe miejsce parkingowe." - }, - "1": { - "then": "To jest zwykłe miejsce parkingowe." - }, - "2": { - "then": "To jest miejsce parkingowe dla niepełnosprawnych." - }, - "3": { - "then": "To jest prywatne miejsce parkingowe." - }, - "4": { - "then": "To miejsce parkingowe jest zarezerwowane dla ładowania pojazdów." - }, - "5": { - "then": "To miejsce parkingowe jest przeznaczone dla dostaw." - }, - "8": { - "then": "To miejsce parkingowe jest przeznaczone dla busów." - }, - "9": { - "then": "To miejsce parkingowe jest przeznaczone dla motocykli." - }, - "10": { - "then": "To miejsce jest przeznaczone dla rodziców z dziećmi." - }, - "11": { - "then": "To jest miejsce parkingowe przeznaczone dla pracowników." - }, - "12": { - "then": "To miejsce parkingowe jest przeznaczone dla taksówek." - } - } + "description": "Warstwa pokazująca pojedyncze miejsca parkingowe.", + "name": "Miejsca parkingowe", + "tagRenderings": { + "type": { + "mappings": { + "0": { + "then": "To jest zwykłe miejsce parkingowe." + }, + "1": { + "then": "To jest zwykłe miejsce parkingowe." + }, + "2": { + "then": "To jest miejsce parkingowe dla niepełnosprawnych." + }, + "3": { + "then": "To jest prywatne miejsce parkingowe." + }, + "4": { + "then": "To miejsce parkingowe jest zarezerwowane dla ładowania pojazdów." + }, + "5": { + "then": "To miejsce parkingowe jest przeznaczone dla dostaw." + }, + "8": { + "then": "To miejsce parkingowe jest przeznaczone dla busów." + }, + "9": { + "then": "To miejsce parkingowe jest przeznaczone dla motocykli." + }, + "10": { + "then": "To miejsce jest przeznaczone dla rodziców z dziećmi." + }, + "11": { + "then": "To jest miejsce parkingowe przeznaczone dla pracowników." + }, + "12": { + "then": "To miejsce parkingowe jest przeznaczone dla taksówek." } + } } + } }, "postoffices": { - "tagRenderings": { - "parcel-from": { - "mappings": { - "0": { - "then": "Można tutaj wysłać paczki" - }, - "1": { - "then": "Nie można tutaj wysłać paczek" - } - }, - "question": "Czy można tutaj wysłać paczkę?" + "tagRenderings": { + "parcel-from": { + "mappings": { + "0": { + "then": "Można tutaj wysłać paczki" + }, + "1": { + "then": "Nie można tutaj wysłać paczek" } + }, + "question": "Czy można tutaj wysłać paczkę?" } + } }, "public_bookcase": { - "tagRenderings": { - "public_bookcase-brand": { - "mappings": { - "0": { - "then": "Część sieci \"Little Free Library\"" - } - } + "tagRenderings": { + "public_bookcase-brand": { + "mappings": { + "0": { + "then": "Część sieci \"Little Free Library\"" } + } } + } }, "questions": { - "tagRenderings": { - "check_date": { - "mappings": { - "0": { - "then": "Ten obiekt został ostatnio sprawdzony dzisiaj" - } - }, - "question": "Kiedy ten obiekt został ostatnio sprawdzony?", - "render": "Ten obiekt był ostatnio sprawdzony {check_date}" - }, - "denominations-coins": { - "mappings": { - "0": { - "then": "Akceptowane są monety 1 centowe" - }, - "1": { - "then": "Akceptowane są monety 2 centowe" - }, - "2": { - "then": "Akceptowane są monety 5 centowe" - }, - "3": { - "then": "Akceptowane są monety 10-centowe" - }, - "4": { - "then": "Akceptowane są monety 20-centowe" - }, - "5": { - "then": "Akceptowane są monety 50-centowe" - }, - "6": { - "then": "Akceptowane są monety 1 euro" - }, - "7": { - "then": "Akceptowane są monety 2 euro" - } - }, - "question": "Jakimi monetami można tutaj zapłacić?" - }, - "denominations-notes": { - "mappings": { - "0": { - "then": "Banknoty 5 euro są akceptowane" - }, - "1": { - "then": "Banknoty 10 euro są akceptowane" - }, - "2": { - "then": "Banknoty 20 euro są akceptowane" - }, - "3": { - "then": "Banknoty 50 euro są akceptowane" - }, - "4": { - "then": "Banknoty 100 euro są akceptowane" - }, - "5": { - "then": "Banknoty 200 euro są akceptowane" - }, - "6": { - "then": "Banknoty 500 euro są akceptowane" - } - }, - "question": "Jakimi banknotami można tu zapłacić?" - }, - "description": { - "question": "Czy jest jeszcze coś istotnego, czego nie mogłeś podać w poprzednich pytaniach? Dodaj to tutaj.", - "questionHint": "Nie powtarzaj już podanych faktów" - }, - "dog-access": { - "mappings": { - "0": { - "then": "Psy dozwolone" - }, - "1": { - "then": "Psy nie dozwolone" - }, - "2": { - "then": "Psy dozwolone, ale muszą być na smyczy" - }, - "3": { - "then": "Psy dozwolone i mogą biegać bez ograniczeń" - } - }, - "question": "Czy w tej firmie psy są dozwolone?" - }, - "email": { - "question": "Jaki jest adres e-mail do {title()}?" - }, - "induction-loop": { - "mappings": { - "0": { - "then": "To miejsce ma pętlę indukcyjną audio" - }, - "1": { - "then": "To miejsce nie ma pętli indukcyjnej dźwięku" - } - }, - "question": "Czy to miejsce ma pętlę indukcyjną dźwięku dla osób niedosłyszących?" - }, - "internet": { - "mappings": { - "0": { - "then": "To miejsce oferuje bezprzewodowy dostęp do Internetu" - }, - "1": { - "then": "To miejsce nie oferuje dostępu do Internetu" - }, - "2": { - "then": "To miejsce oferuje dostęp do Internetu" - }, - "3": { - "then": "To miejsce oferuje dostęp do Internetu za pośrednictwem terminala lub komputera" - }, - "4": { - "then": "To miejsce oferuje przewodowy dostęp do Internetu" - } - }, - "question": "Czy to miejsce oferuje dostęp do Internetu?" - }, - "internet-fee": { - "mappings": { - "0": { - "then": "W tym miejscu dostęp do Internetu jest płatny" - }, - "1": { - "then": "Dostęp do Internetu jest w tym miejscu bezpłatny" - }, - "2": { - "then": "Dostęp do Internetu jest w tym miejscu bezpłatny, tylko dla klientów" - } - }, - "question": "Czy dostęp do Internetu jest płatny?" - }, - "internet-ssid": { - "freeform": { - "placeholder": "Wprowadź nazwę sieci" - }, - "question": "Jaka jest nazwa sieci dla bezprzewodowego dostępu do Internetu?", - "render": "Nazwa sieci to {internet_access:ssid}" - }, - "level": { - "mappings": { - "0": { - "then": "Znajduje się pod ziemią" - }, - "1": { - "then": "Znajduje się na parterze" - }, - "2": { - "then": "Znajduje się na parterze" - }, - "3": { - "then": "Znajduje się na pierwszym piętrze" - }, - "4": { - "then": "Położone na pierwszym poziomie piwnicy" - } - }, - "question": "Na jakim poziomie znajduje się ta funkcja?", - "render": "Znajduje się na {level} piętrze" - }, - "luminous_or_lit": { - "mappings": { - "0": { - "then": "Ten obiekt zarówno emituje światło, jak i jest oświetlany przez zewnętrzne źródło światła" - }, - "1": { - "then": "Ten obiekt emituje światło" - }, - "2": { - "then": "Ten obiekt jest oświetlony zewnętrznie, np. przez reflektor lub inne światła" - }, - "3": { - "then": "Obiekt ten nie emituje światła i nie jest oświetlany z zewnątrz" - } - }, - "question": "Czy ten obiekt jest oświetlony lub emituje światło?" - }, - "multilevels": { - "override": { - "question": "Na jakie poziomy jedzie ta winda?", - "render": "Ta winda jedzie na piętra {level}" - } - }, - "opening_hours": { - "question": "Jakie są godziny otwarcia {title()}?", - "render": "

Godziny otwarcia

{opening_hours_table(opening_hours)}" - }, - "opening_hours_24_7": { - "override": { - "mappings": { - "0": { - "then": "Otwarte 24/7 (również w święta)" - } - } - } - }, - "opening_hours_by_appointment": { - "override": { - "mappings": { - "0": { - "then": "Tylko po wcześniejszym umówieniu się" - }, - "1": { - "then": "Tylko po wcześniejszym umówieniu się" - } - } - } - }, - "payment-options": { - "mappings": { - "0": { - "then": "Płatność gotówkowa jest tutaj dostępna" - }, - "1": { - "then": "Płatność kartą jest tutaj dostępna" - } - }, - "question": "Jakie metody płatności są tutaj dostępne?" - }, - "payment-options-advanced": { - "override": { - "mappings+": { - "0": { - "then": "Płatność odbywa się za pomocą dedykowanej aplikacji" - }, - "1": { - "then": "Płatność odbywa się za pomocą karty członkowskiej" - } - } - } - }, - "payment-options-split": { - "override": { - "mappings+": { - "0": { - "then": "Monety są tutaj akceptowane" - }, - "1": { - "then": "Banknoty są tutaj akceptowane" - }, - "2": { - "then": "Akceptowane są tutaj karty debetowe" - }, - "3": { - "then": "Akceptowane są tutaj karty kredytowe" - } - } - } - }, - "phone": { - "question": "Jaki jest numer telefonu do {title()}?" - }, - "service:electricity": { - "mappings": { - "0": { - "then": "W budynku znajduje się wiele gniazdek elektrycznych, gdzie klienci mogą naładować swoje urządzenia" - }, - "1": { - "then": "W budynku znajduje się kilka gniazdek elektrycznych, gdzie klienci mogą naładować swoje urządzenia" - }, - "2": { - "then": "W budynku nie ma gniazdek elektrycznych dostępnych dla klientów, ale mogą zostać one udostępnione po spytaniu obsługi" - }, - "3": { - "then": "W budynku nie ma gniazdek elektrycznych dostępnych dla klientów" - } - }, - "question": "Czy w tym przybytku znajdują się gniazdka elektryczne, gdzie klienci mogą naładować swoje urządzenia?" - }, - "smoking": { - "mappings": { - "0": { - "then": "Palenie jest dozwolone" - }, - "1": { - "then": "Palenie jest zakazane" - }, - "2": { - "then": "Palenie jest dozwolone na zewnątrz." - } - }, - "question": "Czy w {title()} wolno palić?" - }, - "website": { - "question": "Jaka jest strona internetowa {title()}?" - }, - "wheelchair-access": { - "mappings": { - "0": { - "then": "W tym miejscu zainstalowane zostały udogodnienia dla osób na wózkach inwalidzkich" - }, - "1": { - "then": "To miejsce jest łatwo dostępne dla osób na wózkach inwalidzkich" - }, - "2": { - "then": "To miejsce jest dostępne dla osób na wózkach inwalidzkich, ale z pewnymi trudnościami" - }, - "3": { - "then": "To miejsce jest niedostępne dla osób na wózkach inwalidzkich" - } - }, - "question": "Czy to miejsce jest dostępne dla osób na wózkach inwalidzkich?" - }, - "wikipedia": { - "mappings": { - "0": { - "then": "Link do strony Wikipedii nie został jeszcze określony" - }, - "1": { - "then": "Link do strony Wikipedii nie został jeszcze określony" - } - }, - "question": "Jaki jest powiązany obiekt Wikidata?" + "tagRenderings": { + "check_date": { + "mappings": { + "0": { + "then": "Ten obiekt został ostatnio sprawdzony dzisiaj" } + }, + "question": "Kiedy ten obiekt został ostatnio sprawdzony?", + "render": "Ten obiekt był ostatnio sprawdzony {check_date}" + }, + "denominations-coins": { + "mappings": { + "0": { + "then": "Akceptowane są monety 1 centowe" + }, + "1": { + "then": "Akceptowane są monety 2 centowe" + }, + "2": { + "then": "Akceptowane są monety 5 centowe" + }, + "3": { + "then": "Akceptowane są monety 10-centowe" + }, + "4": { + "then": "Akceptowane są monety 20-centowe" + }, + "5": { + "then": "Akceptowane są monety 50-centowe" + }, + "6": { + "then": "Akceptowane są monety 1 euro" + }, + "7": { + "then": "Akceptowane są monety 2 euro" + } + }, + "question": "Jakimi monetami można tutaj zapłacić?" + }, + "denominations-notes": { + "mappings": { + "0": { + "then": "Banknoty 5 euro są akceptowane" + }, + "1": { + "then": "Banknoty 10 euro są akceptowane" + }, + "2": { + "then": "Banknoty 20 euro są akceptowane" + }, + "3": { + "then": "Banknoty 50 euro są akceptowane" + }, + "4": { + "then": "Banknoty 100 euro są akceptowane" + }, + "5": { + "then": "Banknoty 200 euro są akceptowane" + }, + "6": { + "then": "Banknoty 500 euro są akceptowane" + } + }, + "question": "Jakimi banknotami można tu zapłacić?" + }, + "description": { + "question": "Czy jest jeszcze coś istotnego, czego nie mogłeś podać w poprzednich pytaniach? Dodaj to tutaj.", + "questionHint": "Nie powtarzaj już podanych faktów" + }, + "dog-access": { + "mappings": { + "0": { + "then": "Psy dozwolone" + }, + "1": { + "then": "Psy nie dozwolone" + }, + "2": { + "then": "Psy dozwolone, ale muszą być na smyczy" + }, + "3": { + "then": "Psy dozwolone i mogą biegać bez ograniczeń" + } + }, + "question": "Czy w tej firmie psy są dozwolone?" + }, + "email": { + "question": "Jaki jest adres e-mail do {title()}?" + }, + "induction-loop": { + "mappings": { + "0": { + "then": "To miejsce ma pętlę indukcyjną audio" + }, + "1": { + "then": "To miejsce nie ma pętli indukcyjnej dźwięku" + } + }, + "question": "Czy to miejsce ma pętlę indukcyjną dźwięku dla osób niedosłyszących?" + }, + "internet": { + "mappings": { + "0": { + "then": "To miejsce oferuje bezprzewodowy dostęp do Internetu" + }, + "1": { + "then": "To miejsce nie oferuje dostępu do Internetu" + }, + "2": { + "then": "To miejsce oferuje dostęp do Internetu" + }, + "3": { + "then": "To miejsce oferuje dostęp do Internetu za pośrednictwem terminala lub komputera" + }, + "4": { + "then": "To miejsce oferuje przewodowy dostęp do Internetu" + } + }, + "question": "Czy to miejsce oferuje dostęp do Internetu?" + }, + "internet-fee": { + "mappings": { + "0": { + "then": "W tym miejscu dostęp do Internetu jest płatny" + }, + "1": { + "then": "Dostęp do Internetu jest w tym miejscu bezpłatny" + }, + "2": { + "then": "Dostęp do Internetu jest w tym miejscu bezpłatny, tylko dla klientów" + } + }, + "question": "Czy dostęp do Internetu jest płatny?" + }, + "internet-ssid": { + "freeform": { + "placeholder": "Wprowadź nazwę sieci" + }, + "question": "Jaka jest nazwa sieci dla bezprzewodowego dostępu do Internetu?", + "render": "Nazwa sieci to {internet_access:ssid}" + }, + "level": { + "mappings": { + "0": { + "then": "Znajduje się pod ziemią" + }, + "1": { + "then": "Znajduje się na parterze" + }, + "2": { + "then": "Znajduje się na parterze" + }, + "3": { + "then": "Znajduje się na pierwszym piętrze" + }, + "4": { + "then": "Położone na pierwszym poziomie piwnicy" + } + }, + "question": "Na jakim poziomie znajduje się ta funkcja?", + "render": "Znajduje się na {level} piętrze" + }, + "luminous_or_lit": { + "mappings": { + "0": { + "then": "Ten obiekt zarówno emituje światło, jak i jest oświetlany przez zewnętrzne źródło światła" + }, + "1": { + "then": "Ten obiekt emituje światło" + }, + "2": { + "then": "Ten obiekt jest oświetlony zewnętrznie, np. przez reflektor lub inne światła" + }, + "3": { + "then": "Obiekt ten nie emituje światła i nie jest oświetlany z zewnątrz" + } + }, + "question": "Czy ten obiekt jest oświetlony lub emituje światło?" + }, + "multilevels": { + "override": { + "question": "Na jakie poziomy jedzie ta winda?", + "render": "Ta winda jedzie na piętra {level}" + } + }, + "opening_hours": { + "question": "Jakie są godziny otwarcia {title()}?", + "render": "

Godziny otwarcia

{opening_hours_table(opening_hours)}" + }, + "opening_hours_24_7": { + "override": { + "mappings": { + "0": { + "then": "Otwarte 24/7 (również w święta)" + } + } + } + }, + "opening_hours_by_appointment": { + "override": { + "mappings": { + "0": { + "then": "Tylko po wcześniejszym umówieniu się" + }, + "1": { + "then": "Tylko po wcześniejszym umówieniu się" + } + } + } + }, + "payment-options": { + "mappings": { + "0": { + "then": "Płatność gotówkowa jest tutaj dostępna" + }, + "1": { + "then": "Płatność kartą jest tutaj dostępna" + } + }, + "question": "Jakie metody płatności są tutaj dostępne?" + }, + "payment-options-advanced": { + "override": { + "mappings+": { + "0": { + "then": "Płatność odbywa się za pomocą dedykowanej aplikacji" + }, + "1": { + "then": "Płatność odbywa się za pomocą karty członkowskiej" + } + } + } + }, + "payment-options-split": { + "override": { + "mappings+": { + "0": { + "then": "Monety są tutaj akceptowane" + }, + "1": { + "then": "Banknoty są tutaj akceptowane" + }, + "2": { + "then": "Akceptowane są tutaj karty debetowe" + }, + "3": { + "then": "Akceptowane są tutaj karty kredytowe" + } + } + } + }, + "phone": { + "question": "Jaki jest numer telefonu do {title()}?" + }, + "service:electricity": { + "mappings": { + "0": { + "then": "W budynku znajduje się wiele gniazdek elektrycznych, gdzie klienci mogą naładować swoje urządzenia" + }, + "1": { + "then": "W budynku znajduje się kilka gniazdek elektrycznych, gdzie klienci mogą naładować swoje urządzenia" + }, + "2": { + "then": "W budynku nie ma gniazdek elektrycznych dostępnych dla klientów, ale mogą zostać one udostępnione po spytaniu obsługi" + }, + "3": { + "then": "W budynku nie ma gniazdek elektrycznych dostępnych dla klientów" + } + }, + "question": "Czy w tym przybytku znajdują się gniazdka elektryczne, gdzie klienci mogą naładować swoje urządzenia?" + }, + "smoking": { + "mappings": { + "0": { + "then": "Palenie jest dozwolone" + }, + "1": { + "then": "Palenie jest zakazane" + }, + "2": { + "then": "Palenie jest dozwolone na zewnątrz." + } + }, + "question": "Czy w {title()} wolno palić?" + }, + "website": { + "question": "Jaka jest strona internetowa {title()}?" + }, + "wheelchair-access": { + "mappings": { + "0": { + "then": "W tym miejscu zainstalowane zostały udogodnienia dla osób na wózkach inwalidzkich" + }, + "1": { + "then": "To miejsce jest łatwo dostępne dla osób na wózkach inwalidzkich" + }, + "2": { + "then": "To miejsce jest dostępne dla osób na wózkach inwalidzkich, ale z pewnymi trudnościami" + }, + "3": { + "then": "To miejsce jest niedostępne dla osób na wózkach inwalidzkich" + } + }, + "question": "Czy to miejsce jest dostępne dla osób na wózkach inwalidzkich?" + }, + "wikipedia": { + "mappings": { + "0": { + "then": "Link do strony Wikipedii nie został jeszcze określony" + }, + "1": { + "then": "Link do strony Wikipedii nie został jeszcze określony" + } + }, + "question": "Jaki jest powiązany obiekt Wikidata?" } + } }, "reception_desk": { - "tagRenderings": { - "desk-height": { - "question": "Jaka jest wysokość tego biurka recepcji? ", - "questionHint": "Jest to mierzone od podłogi do najniższej użytecznej części biurka", - "render": "Wysokość tego biurka to {canonical(desk:height)}" - } - }, - "units": { - "0": { - "applicableUnits": { - "0": { - "human": "metr" - }, - "1": { - "human": "centymetr" - } - } - } + "tagRenderings": { + "desk-height": { + "question": "Jaka jest wysokość tego biurka recepcji? ", + "questionHint": "Jest to mierzone od podłogi do najniższej użytecznej części biurka", + "render": "Wysokość tego biurka to {canonical(desk:height)}" } + }, + "units": { + "0": { + "applicableUnits": { + "0": { + "human": "metr" + }, + "1": { + "human": "centymetr" + } + } + } + } }, "recycling": { - "tagRenderings": { - "recycling-accepts": { - "mappings": { - "16": { - "then": "Plastik może być tutaj poddany recyklingowi" - } - } + "tagRenderings": { + "recycling-accepts": { + "mappings": { + "16": { + "then": "Plastik może być tutaj poddany recyklingowi" } + } } + } }, "school": { - "tagRenderings": { - "school-language": { - "render": { - "special": { - "render_all": "Następujące języki są używane w tej szkole:{list()}", - "render_single_language": "Język {language():font-bold} jest głównym językiem używanym w tej szkole" - } - } - }, - "school-name": { - "question": "Jaką nazwę ma ta szkoła?", - "render": "Ta szkoła nazywa się {name}" - }, - "target-audience": { - "mappings": { - "3": { - "then": "To jest szkoła dla uczniów z autyzmem" - }, - "6": { - "then": "To jest szkoła dla uczniów głuchych i słabosłyszących" - }, - "7": { - "then": "To jest szkoła dla uczniów z niepełnosprawnościami" - }, - "8": { - "then": "To jest szkoła dla uczniów z specjalnymi potrzebami" - } - } + "tagRenderings": { + "school-language": { + "render": { + "special": { + "render_all": "Następujące języki są używane w tej szkole:{list()}", + "render_single_language": "Język {language():font-bold} jest głównym językiem używanym w tej szkole" } + } }, - "title": { - "render": "Szkoła {name}" + "school-name": { + "question": "Jaką nazwę ma ta szkoła?", + "render": "Ta szkoła nazywa się {name}" + }, + "target-audience": { + "mappings": { + "3": { + "then": "To jest szkoła dla uczniów z autyzmem" + }, + "6": { + "then": "To jest szkoła dla uczniów głuchych i słabosłyszących" + }, + "7": { + "then": "To jest szkoła dla uczniów z niepełnosprawnościami" + }, + "8": { + "then": "To jest szkoła dla uczniów z specjalnymi potrzebami" + } + } } + }, + "title": { + "render": "Szkoła {name}" + } }, "windturbine": { - "title": { - "mappings": { - "0": { - "then": "{name}" - } - }, - "render": "turbina wiatrowa" - } + "title": { + "mappings": { + "0": { + "then": "{name}" + } + }, + "render": "turbina wiatrowa" + } } -} \ No newline at end of file + } +} diff --git a/langs/layers/pt.json b/langs/layers/pt.json index c9719c968..0b555ee2d 100644 --- a/langs/layers/pt.json +++ b/langs/layers/pt.json @@ -233,7 +233,11 @@ }, "artwork-website": { "question": "Existe um site com mais informações sobre esta obra de arte?", - "render": "Mais informações neste site" + "render": { + "special": { + "text": "Mais informações neste site" + } + } }, "artwork_subject": { "question": "O que esta obra de arte representa?", diff --git a/langs/layers/ru.json b/langs/layers/ru.json index a320c85f5..b32efc029 100644 --- a/langs/layers/ru.json +++ b/langs/layers/ru.json @@ -117,7 +117,11 @@ }, "artwork-website": { "question": "Есть ли сайт с более подробной информацией об этой работе?", - "render": "Больше информации на этом сайте" + "render": { + "special": { + "text": "Больше информации на этом сайте" + } + } } }, "title": { @@ -996,7 +1000,11 @@ "render": "В знак памяти о {subject}" }, "ghost_bike-source": { - "render": "Доступна более подробная информация" + "render": { + "special": { + "text": "Доступна более подробная информация" + } + } }, "ghost_bike-start_date": { "render": "Установлен {start_date}" @@ -1295,13 +1303,6 @@ } } }, - "nature_reserve": { - "tagRenderings": { - "Email": { - "render": "{email}" - } - } - }, "observation_tower": { "name": "Смотровые башни", "title": { @@ -1515,7 +1516,11 @@ }, "public_bookcase-website": { "question": "Есть ли веб-сайт с более подробной информацией об этом общественном книжном шкафе?", - "render": "Более подробная информация на сайте" + "render": { + "special": { + "text": "Более подробная информация на сайте" + } + } } }, "title": { diff --git a/langs/layers/zh_Hant.json b/langs/layers/zh_Hant.json index 82fb3ca3b..1b07031cf 100644 --- a/langs/layers/zh_Hant.json +++ b/langs/layers/zh_Hant.json @@ -72,7 +72,11 @@ }, "artwork-website": { "question": "在那個網站能夠找到更多藝術品的資訊?", - "render": "這個網站有更多資訊" + "render": { + "special": { + "text": "這個網站有更多資訊" + } + } } }, "title": { diff --git a/langs/nb_NO.json b/langs/nb_NO.json index 74da37d95..3c56e2c00 100644 --- a/langs/nb_NO.json +++ b/langs/nb_NO.json @@ -300,17 +300,6 @@ "doDelete": "Fjern bilde", "dontDelete": "Avbryt", "isDeleted": "Slettet", - "nearbyPictures": { - "allFiltered": "Ingen bilder samsvarte", - "browseNearby": "Utforsk bilder i nærheten …", - "confirm": "Valgt bilde viser {title()}", - "loadMore": "Last inn flere bilder", - "loading": "Laster inn bilder i nærheten …", - "noImageSelected": "Velg et bilde for å knytte det til objektet", - "nothingFound": "Fant ingen bilder i nærheten …", - "removeFilters": "Klikk her for å fjerne filterne", - "title": "Bilder i nærheten" - }, "pleaseLogin": "Logg inn for å legge til et bilde", "respectPrivacy": "Ikke ta bilder av folk eller bilskilt. Ikke last opp Google Maps, Google Streetview eller andre opphavsrettsbeskyttede kilder.", "toBig": "Bildet ditt på {actual_size} er for stort. Det kan maksimalt være {max_size}.", diff --git a/langs/nl.json b/langs/nl.json index 1a82b45e7..1a7e651cb 100644 --- a/langs/nl.json +++ b/langs/nl.json @@ -404,20 +404,6 @@ "doDelete": "Verwijder afbeelding", "dontDelete": "Annuleren", "isDeleted": "Verwijderd", - "nearbyPictures": { - "allFiltered": "Geen enkele afbeelding voldoet aan je filter", - "browseNearby": "Bekijk afbeeldingen van deze buurt…", - "confirm": "De geselecteerde afbeelding toont {title()}", - "hasMatchingPicture": "Is er een afbeelding die dit object toont? Selecteer deze hieronder:", - "loadMore": "Toon meer afbeeldingen", - "loading": "Afbeeldingen worden geladen…", - "noImageSelected": "Selecteer een afbeelding om deze te linken", - "nothingFound": "Geen afbeeldingen van deze buurt gevonden…", - "onlyTowards": "Toon enkel afbeeldingen die naar dit object kijken", - "removeFilters": "Verwijder alle filters", - "title": "Afbeeldingen van de buurt", - "withinRadius": "Toon enkel afbeeldingen die gemaakt zijn binnen {radius} meter van dit object" - }, "pleaseLogin": "Gelieve je aan te melden om een foto toe te voegen", "respectPrivacy": "Fotografeer geen mensen of nummerplaten. Voeg geen Google Maps, Google Streetview of foto's met auteursrechten toe.", "toBig": "Je afbeelding is te groot, namelijk {actual_size}. Gelieve afbeeldingen van maximaal {max_size} te gebruiken", diff --git a/langs/pa_PK.json b/langs/pa_PK.json index 15de79618..48e25c330 100644 --- a/langs/pa_PK.json +++ b/langs/pa_PK.json @@ -85,12 +85,7 @@ "addPicture": "تصویر پایو", "doDelete": "تصویر ہٹاؤ", "dontDelete": "رد کرو", - "isDeleted": "مٹائی گئی", - "nearbyPictures": { - "browseNearby": "نیڑے تیڑے تے تصویراں ویکھو۔ ۔ ۔", - "loadMore": "ہور تصویراں لوڈ کرو", - "title": "نیڑے تیڑے تے تصویراں" - } + "isDeleted": "مٹائی گئی" }, "move": { "cancel": "چلݨ رد کرو" diff --git a/langs/pl.json b/langs/pl.json index a7983b322..d4d949a35 100644 --- a/langs/pl.json +++ b/langs/pl.json @@ -268,13 +268,6 @@ "doDelete": "Usuń ilustrację", "dontDelete": "Anuluj", "isDeleted": "Usunięte", - "nearbyPictures": { - "browseNearby": "Przeglądaj zdjęcia w pobliżu…", - "loadMore": "Załaduj więcej zdjęć", - "loading": "Wczytywanie obrazów w pobliżu…", - "nothingFound": "Nie znaleziono zdjęć w pobliżu…", - "removeFilters": "Kliknij tutaj, aby usunąć filtry" - }, "pleaseLogin": "Zaloguj się, by dodać zdjęcie", "respectPrivacy": "Nie fotografuj ludzi i tablic rejestracyjnych. Nie wysyłaj także treści z Google Maps, Google Streetview ani innych licencjonowanych źródeł.", "uploadDone": "Twoje zdjęcie zostało dodane. Dzięki za pomoc!", diff --git a/langs/pt.json b/langs/pt.json index bc70ecd62..1b2767540 100644 --- a/langs/pt.json +++ b/langs/pt.json @@ -297,20 +297,6 @@ "doDelete": "Remover imagem", "dontDelete": "Cancelar", "isDeleted": "Eliminada", - "nearbyPictures": { - "allFiltered": "Nenhuma imagem correspondeu ao seu filtro", - "browseNearby": "Procurar imagens próximas…", - "confirm": "A imagem selecionada mostra {title()}", - "hasMatchingPicture": "Será que uma imagem corresponde ao objeto? Selecione abaixo", - "loadMore": "Carregar mais imagens", - "loading": "A carregar imagens próximas…", - "noImageSelected": "Selecione uma imagem para ligá-la ao objeto", - "nothingFound": "Não foram encontradas imagens próximas…", - "onlyTowards": "Mostrar apenas fotografias que são tiradas em direção a este objeto", - "removeFilters": "Clique aqui para remover os filtros", - "title": "Fotografias próximas", - "withinRadius": "Mostrar apenas fotografias que são tiradas num raio de {radius} metros deste objeto" - }, "pleaseLogin": "Entre na sua conta para adicionar uma imagem", "respectPrivacy": "Não fotografe pessoas nem placas de veículos. Não envie imagens do Google Maps, do Google Streetview ou outras fontes protegidas por direitos de autor.", "toBig": "A sua imagem é muito grande porque tem {actual_size}. Use imagens com o máximo {max_size}", diff --git a/langs/pt_BR.json b/langs/pt_BR.json index c72ba63eb..d6af7cb4d 100644 --- a/langs/pt_BR.json +++ b/langs/pt_BR.json @@ -141,9 +141,6 @@ "doDelete": "Remover imagem", "dontDelete": "Cancelar", "isDeleted": "Excluída", - "nearbyPictures": { - "browseNearby": "Navegue pelas imagens próximas…" - }, "pleaseLogin": "Faça login para adicionar uma imagem", "respectPrivacy": "Não fotografe pessoas e nem placas de veículos. Não faça upload do Google Maps, Google Streetview ou outras fontes protegidas por direitos autorais.", "uploadDone": "Sua foto foi adicionada. Obrigado por ajudar!", diff --git a/langs/sl.json b/langs/sl.json index 70b3d22f6..ffaadefb2 100644 --- a/langs/sl.json +++ b/langs/sl.json @@ -66,8 +66,7 @@ "addPicture": "Dodaj sliko", "doDelete": "Odstrani sliko", "dontDelete": "Prekliči", - "isDeleted": "Izbrisana", - "nearbyPictures": {} + "isDeleted": "Izbrisana" }, "importInspector": {}, "importLayer": {}, diff --git a/langs/sv.json b/langs/sv.json index 06a1d189d..35a494b8a 100644 --- a/langs/sv.json +++ b/langs/sv.json @@ -69,7 +69,6 @@ "doDelete": "Ta bort bild", "dontDelete": "Avbryt", "isDeleted": "Borttagen", - "nearbyPictures": {}, "pleaseLogin": "Logga in för att lägga till en bild", "respectPrivacy": "Fotografera inte personer eller registreringsskyltar. Ladda inte upp från Google Maps, Google Streetview eller andra upphovsrättsskyddade källor.", "toBig": "Din bild är för stor då den är {actual_size}. Vänligen använd endast bilder som är högst {max_size}", diff --git a/langs/themes/de.json b/langs/themes/de.json index 8a31bbcd5..c3897e52a 100644 --- a/langs/themes/de.json +++ b/langs/themes/de.json @@ -1350,4 +1350,4 @@ "shortDescription": "Eine Karte mit Abfalleimern", "title": "Abfalleimer" } -} \ No newline at end of file +} diff --git a/langs/themes/en.json b/langs/themes/en.json index ca9c5a4f9..d07b53164 100644 --- a/langs/themes/en.json +++ b/langs/themes/en.json @@ -858,12 +858,12 @@ "description": "This maps shows all the changes made with MapComplete", "layers": { "0": { - "description": "Shows all MapComplete changes", + "description": "Show all MapComplete changes", "filter": { "0": { "options": { "0": { - "question": "Themename contains {search}" + "question": "Theme name contains {search}" } } }, @@ -920,12 +920,12 @@ "name": "Changeset centers", "tagRenderings": { "contributor": { - "question": "What contributor did make this change?", + "question": "Which contributor made this change?", "render": "Change made by {user}" }, "host": { "question": "What host (website) was this change made with?", - "render": "Change with with {host}" + "render": "Change made with {host}" }, "locale": { "question": "What locale (language) was this change made in?", @@ -936,7 +936,7 @@ }, "theme-id": { "question": "What theme was used to make this change?", - "render": "Change with theme {theme}" + "render": "Change with theme {theme}" }, "version": { "question": "What version of MapComplete was used to make this change?", @@ -957,7 +957,7 @@ } } }, - "shortDescription": "Shows changes made by MapComplete", + "shortDescription": "Show changes made with MapComplete", "title": "Changes made with MapComplete" }, "maproulette": { diff --git a/langs/themes/fr.json b/langs/themes/fr.json index 1154031d0..21da83331 100644 --- a/langs/themes/fr.json +++ b/langs/themes/fr.json @@ -844,6 +844,65 @@ }, "title": "Ressauts et traversées" }, + "mapcomplete-changes": { + "description": "Cette carte montre tous les changements faits avec MapComplete", + "layers": { + "0": { + "filter": { + "5": { + "options": { + "0": { + "question": "Langage utilisateur (code-ISO) {search}" + } + } + }, + "7": { + "options": { + "0": { + "question": "Le groupe de modifications a ajouté au moins une image" + } + } + } + }, + "tagRenderings": { + "contributor": { + "question": "Quel contributeur a fait cette modification ?", + "render": "Modification faite par {user}" + }, + "host": { + "render": "Modification faite avec {host}" + }, + "locale": { + "question": "En quelle langue est-ce que ce changement a été fait ?" + }, + "show_changeset_id": { + "render": "Groupe de modifications {id}" + }, + "theme-id": { + "question": "Quel thème a été utilisé pour faire cette modification ?", + "render": "Modifié avec le thème {theme}" + }, + "version": { + "question": "Quelle version de MapComplete a été utilisée pour faire cette modification ?", + "render": "Fait avec {editor}" + } + }, + "title": { + "render": "Groupe de modifications pour {theme}" + } + }, + "1": { + "override": { + "tagRenderings+": { + "0": { + "render": "D'autres statistiques sont disponibles ici" + } + } + } + } + }, + "title": "Changements faits avec MapComplete" + }, "maproulette": { "description": "Thème MapRoulette permettant d’afficher, rechercher, filtrer et résoudre les tâches.", "title": "Tâches MapRoulette" diff --git a/langs/themes/nl.json b/langs/themes/nl.json index 8344d4fba..2affa3f47 100644 --- a/langs/themes/nl.json +++ b/langs/themes/nl.json @@ -936,6 +936,89 @@ }, "title": "Stoepranden en oversteekplaatsen" }, + "mapcomplete-changes": { + "description": "Deze kaart toont alle wijzigingen die met MapComplete gemaakt werden", + "layers": { + "0": { + "description": "Toon alle MapComplete wijzigingen", + "filter": { + "0": { + "options": { + "0": { + "question": "Themenaam bevat {search}" + } + } + }, + "1": { + "options": { + "0": { + "question": "Gemaakt door bijdrager {search}" + } + } + }, + "2": { + "options": { + "0": { + "question": "Niet gemaakt door bijdrager {search}" + } + } + }, + "3": { + "options": { + "0": { + "question": "Gemaakt voor {search}" + } + } + }, + "4": { + "options": { + "0": { + "question": "Gemaakt na {search}" + } + } + }, + "5": { + "options": { + "0": { + "question": "De taal van de bijdrager is {search}" + } + } + }, + "6": { + "options": { + "0": { + "question": "Gemaakt met host {search}" + } + } + }, + "7": { + "options": { + "0": { + "question": "Changeset bevat minstens één afbeelding" + } + } + } + }, + "name": "Centerpunt van changeset", + "tagRenderings": { + "contributor": { + "question": "Welke bijdrager maakte deze wijziging?", + "render": "Wijziging gemaakt door {user}" + }, + "host": { + "question": "Met welke host (website) werd deze wijziging gemaakt?", + "render": "Wijziging gemaakt met {host}" + }, + "locale": { + "question": "In welke locale (taal) werd deze wijziging gemaakt?", + "render": "De gebruikerstaal is {locale}" + } + } + } + }, + "shortDescription": "Toon wijzigingen gemaakt met MapComplete", + "title": "Wijzigingen gemaakt met MapComplete" + }, "maproulette": { "description": "Thema met MapRoulette taken, waar je ze kunt zoeken, filteren en ze oplossen.", "title": "MapRoulette taken" diff --git a/langs/zh_Hant.json b/langs/zh_Hant.json index e168f70f3..8772a0778 100644 --- a/langs/zh_Hant.json +++ b/langs/zh_Hant.json @@ -280,20 +280,6 @@ "doDelete": "移除圖片", "dontDelete": "取消", "isDeleted": "已移除", - "nearbyPictures": { - "allFiltered": "沒有符合篩選器的圖片", - "browseNearby": "瀏覽附近的圖片…", - "confirm": "選取的圖片顯示 {title()}", - "hasMatchingPicture": "有圖片符合物件嗎?請從底下結果選取", - "loadMore": "載入更多圖片", - "loading": "載入附近圖片…", - "noImageSelected": "選取圖片來連結到物件", - "nothingFound": "附近沒有找到圖片…", - "onlyTowards": "只顯示往這個物件方向照的圖片", - "removeFilters": "點這裡來移除篩選", - "title": "附近圖片", - "withinRadius": "只顯示這個物件半徑 {radius} 公尺內照的圖片" - }, "pleaseLogin": "請登入以新增圖片", "respectPrivacy": "請別照人像或是車牌,不要上傳 Google 地圖、Google 街景或其他受版權保護的資料來源。", "toBig": "{actual_size} 因此照片太大,請使用最大 {max_size} 的照片", diff --git a/package-lock.json b/package-lock.json index 1264b5d76..9256578de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "mangrove-reviews-typescript": "^1.1.0", "maplibre-gl": "^3.2.0", "opening_hours": "^3.6.0", - "osm-auth": "^1.0.2", + "osm-auth": "^2.2.0", "osmtogeojson": "^3.0.0-beta.5", "papaparse": "^5.3.1", "pic4carto": "^2.1.15", @@ -72,9 +72,13 @@ "@types/prompt-sync": "^4.1.0", "@types/wikidata-sdk": "^6.1.0", "@types/xml2js": "^0.4.9", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", "assert": "^2.0.0", "chai": "^4.3.6", "dependency-cruiser": "^10.4.0", + "eslint": "^8.45.0", + "eslint-plugin-svelte": "^2.32.2", "fs": "0.0.1-security", "node-html-parser": "^6.1.5", "prettier": "^2.8.8", @@ -89,12 +93,19 @@ "ts-node": "^10.9.1", "ts2json-schema": "^1.4.0", "tslib": "^2.5.0", - "tslint": "^6.1.3", - "tslint-no-circular-imports": "^0.7.0", "typescript": "^4.7.4", "vite": "^4.0.5" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -1634,6 +1645,144 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "node_modules/@jest/schemas": { "version": "29.4.0", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.0.tgz", @@ -3682,9 +3831,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/json5": { @@ -3766,6 +3915,12 @@ "@types/node": "*" } }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "node_modules/@types/showdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.0.tgz", @@ -3803,6 +3958,295 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz", + "integrity": "sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/type-utils": "6.1.0", + "@typescript-eslint/utils": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.1.0.tgz", + "integrity": "sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz", + "integrity": "sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/utils": "6.1.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -4107,6 +4551,15 @@ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -4436,15 +4889,6 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/bytewise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", @@ -4919,6 +5363,20 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "devOptional": true }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/css-line-break": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", @@ -5433,6 +5891,18 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -5454,6 +5924,18 @@ "doctest-ts-improved": "dist/main.js" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5719,6 +6201,378 @@ "source-map": "~0.6.1" } }, + "node_modules/eslint": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.6.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-svelte": { + "version": "2.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.32.2.tgz", + "integrity": "sha512-Jgbop2fNZsoxxkklZAIbDNhwAPynvnCtUXLsEC6O2qax7N/pfe2cNqT0ZoBbubXKJitQQDEyVDQ1rZs4ZWcrTA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@jridgewell/sourcemap-codec": "^1.4.14", + "debug": "^4.3.1", + "esutils": "^2.0.3", + "known-css-properties": "^0.27.0", + "postcss": "^8.4.5", + "postcss-load-config": "^3.1.4", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.11", + "semver": "^7.5.3", + "svelte-eslint-parser": "^0.32.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0-0", + "svelte": "^3.37.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-svelte/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-svelte/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-svelte/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -5731,12 +6585,35 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "optional": true, - "peer": true, + "devOptional": true, "engines": { "node": ">=4.0" } @@ -6001,6 +6878,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6035,6 +6924,40 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "node_modules/follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", @@ -6362,6 +7285,26 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -6379,6 +7322,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -6720,6 +7669,15 @@ } ] }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/immutable": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", @@ -6742,6 +7700,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/incremental-convex-hull": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/incremental-convex-hull/-/incremental-convex-hull-1.0.1.tgz", @@ -7012,6 +7979,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -7300,17 +8276,6 @@ "node": ">=4" } }, - "node_modules/jshashes": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/jshashes/-/jshashes-1.0.8.tgz", - "integrity": "sha512-btmQZ/w1rj8Lb6nEwvhjM7nBYoj54yaEFo2PWh3RkxZ8qNwuvOxvQYN/JxVuwoMmdIluL+XwYVJ+pEEZoSYybQ==", - "bin": { - "hashes": "bin/hashes" - }, - "engines": { - "node": "*" - } - }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -7334,6 +8299,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json-stringify-pretty-compact": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", @@ -7477,6 +8448,12 @@ "node": ">=6" } }, + "node_modules/known-css-properties": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", + "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "dev": true + }, "node_modules/latlon2country": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/latlon2country/-/latlon2country-1.2.6.tgz", @@ -7549,6 +8526,12 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -8043,6 +9026,18 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -8189,18 +9184,6 @@ "node": ">= 0.4" } }, - "node_modules/ohauth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ohauth/-/ohauth-1.0.1.tgz", - "integrity": "sha512-R9ZUN3+FVCwzeOOHCJpzA9jw/byRxp5O9X06mTL6Sp/LIQn/rLrMv6cwYctX+hoIKzRUsalGJXZ1kG5wBmSskQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dependencies": { - "jshashes": "~1.0.8" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8372,16 +9355,14 @@ } }, "node_modules/osm-auth": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/osm-auth/-/osm-auth-1.1.2.tgz", - "integrity": "sha512-oLaU+c/TP7eKAZpBN4S1mv/N94IXp5A+wLpDfAVlpq/b6iikas8ZthXPqhM8QKg/qB8RaKvZPJgxqYS+5m8G8g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/osm-auth/-/osm-auth-2.2.0.tgz", + "integrity": "sha512-x93jAMaYWqPgfVeOMydFLFpFC8ERnlIKXwiUOrYYWTDEWqq15K/BI5UAjzuYXvLg0WxVxM8YC4N1T30SZeKJBQ==", "dependencies": { - "ohauth": "~1.0.1", - "resolve-url": "~0.2.1", "store": "~2.0.12" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/osm-polygon-features": { @@ -8488,11 +9469,29 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pathe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", @@ -8585,6 +9584,99 @@ "splaytree": "^3.1.0" } }, + "node_modules/postcss": { + "version": "8.4.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz", + "integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-scss": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.6.tgz", + "integrity": "sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + } + ], + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.19" + } + }, "node_modules/postcss-selector-parser": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", @@ -8597,6 +9689,23 @@ "node": ">=4" } }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/potpack": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.0.0.tgz", @@ -9191,12 +10300,6 @@ "protocol-buffers-schema": "^3.3.1" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -9608,6 +10711,27 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/showdown": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", @@ -9721,6 +10845,15 @@ "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -9869,12 +11002,6 @@ "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, "node_modules/sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -10054,9 +11181,9 @@ } }, "node_modules/svelte": { - "version": "3.55.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.55.1.tgz", - "integrity": "sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==", + "version": "3.59.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.2.tgz", + "integrity": "sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==", "engines": { "node": ">= 8" } @@ -10083,6 +11210,33 @@ "svelte": "^3.55.0" } }, + "node_modules/svelte-eslint-parser": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.32.1.tgz", + "integrity": "sha512-GCSfeIzdgk53CaOzK+s/+l2igfTno3mWGkwoDYAwPes/rD9Al2fc7ksfopjx5UL87S7dw1eL73F6wNYiiuhzIA==", + "dev": true, + "dependencies": { + "eslint-scope": "^7.0.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "postcss": "^8.4.25", + "postcss-scss": "^4.0.6" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "svelte": "^3.37.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "svelte": { + "optional": true + } + } + }, "node_modules/svelte-hmr": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.1.tgz", @@ -10242,40 +11396,6 @@ "node": ">=10.13.0" } }, - "node_modules/tailwindcss/node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/tailwindcss/node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/tailwindcss/node_modules/postcss-import": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", @@ -10310,34 +11430,6 @@ "postcss": "^8.3.3" } }, - "node_modules/tailwindcss/node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, "node_modules/tailwindcss/node_modules/postcss-nested": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", @@ -10439,6 +11531,12 @@ "utrie": "^1.0.2" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -10588,6 +11686,18 @@ "node": ">=14" } }, + "node_modules/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-json-schema-generator": { "version": "0.95.0", "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-0.95.0.tgz", @@ -10809,117 +11919,6 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "devOptional": true }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" - }, - "engines": { - "node": ">=4.8.0" - }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" - } - }, - "node_modules/tslint-no-circular-imports": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tslint-no-circular-imports/-/tslint-no-circular-imports-0.7.0.tgz", - "integrity": "sha512-k3wxpeMC4ef40UbpfBVHEHIzKfNZq5/SCtAO1YjGsaNTklo+K53/TWLrym+poA65RJFDiYgYNWvkeIIkJNA0Vw==", - "dev": true, - "peerDependencies": { - "tslint": ">=5.0.0", - "typescript": ">=2.1.0" - } - }, - "node_modules/tslint/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/tslint/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/tslint/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/tslint/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/tslint/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -11519,9 +12518,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11896,40 +12895,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/vite/node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/vite/node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/vitefu": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.4.tgz", @@ -12404,6 +13369,12 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -13487,6 +14458,102 @@ "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", "optional": true }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, "@jest/schemas": { "version": "29.4.0", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.0.tgz", @@ -15090,9 +16157,9 @@ } }, "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "@types/json5": { @@ -15174,6 +16241,12 @@ "@types/node": "*" } }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "@types/showdown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.0.tgz", @@ -15210,6 +16283,185 @@ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" }, + "@typescript-eslint/eslint-plugin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.1.0.tgz", + "integrity": "sha512-qg7Bm5TyP/I7iilGyp6DRqqkt8na00lI6HbjWZObgk3FFSzH5ypRwAHXJhJkwiRtTcfn+xYQIMOR5kJgpo6upw==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/type-utils": "6.1.0", + "@typescript-eslint/utils": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/parser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.1.0.tgz", + "integrity": "sha512-hIzCPvX4vDs4qL07SYzyomamcs2/tQYXg5DtdAfj35AyJ5PIUqhsLf4YrEIFzZcND7R2E8tpQIZKayxg8/6Wbw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.1.0.tgz", + "integrity": "sha512-AxjgxDn27hgPpe2rQe19k0tXw84YCOsjDJ2r61cIebq1t+AIxbgiXKvD4999Wk49GVaAcdJ/d49FYel+Pp3jjw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.1.0.tgz", + "integrity": "sha512-kFXBx6QWS1ZZ5Ni89TyT1X9Ag6RXVIVhqDs0vZE/jUeWlBv/ixq2diua6G7ece6+fXw3TvNRxP77/5mOMusx2w==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.1.0", + "@typescript-eslint/utils": "6.1.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/types": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.1.0.tgz", + "integrity": "sha512-+Gfd5NHCpDoHDOaU/yIF3WWRI2PcBRKKpP91ZcVbL0t5tQpqYWBs3z/GGhvU+EV1D0262g9XCnyqQh19prU0JQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.1.0.tgz", + "integrity": "sha512-nUKAPWOaP/tQjU1IQw9sOPCDavs/iU5iYLiY/6u7gxS7oKQoi4aUxXS1nrrVGTyBBaGesjkcwwHkbkiD5eBvcg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/visitor-keys": "6.1.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/utils": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.1.0.tgz", + "integrity": "sha512-wp652EogZlKmQoMS5hAvWqRKplXvkuOnNzZSE0PVvsKjpexd/XznRVHAtrfHFYmqaJz0DFkjlDsGYC9OXw+OhQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.1.0", + "@typescript-eslint/types": "6.1.0", + "@typescript-eslint/typescript-estree": "6.1.0", + "semver": "^7.5.4" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.1.0.tgz", + "integrity": "sha512-yQeh+EXhquh119Eis4k0kYhj9vmFzNpbhM3LftWQVwqVjipCkwHBQOZutcYW+JVkjtTG9k8nrZU1UoNedPDd1A==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.1.0", + "eslint-visitor-keys": "^3.4.1" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -15448,6 +16700,12 @@ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==" }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -15682,12 +16940,6 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==", - "dev": true - }, "bytewise": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", @@ -16045,6 +17297,17 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "devOptional": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "css-line-break": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", @@ -16414,6 +17677,15 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -16432,6 +17704,15 @@ "typescript": "^4.6.2" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -16647,17 +17928,297 @@ "source-map": "~0.6.1" } }, + "eslint": { + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.6.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-plugin-svelte": { + "version": "2.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.32.2.tgz", + "integrity": "sha512-Jgbop2fNZsoxxkklZAIbDNhwAPynvnCtUXLsEC6O2qax7N/pfe2cNqT0ZoBbubXKJitQQDEyVDQ1rZs4ZWcrTA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@jridgewell/sourcemap-codec": "^1.4.14", + "debug": "^4.3.1", + "esutils": "^2.0.3", + "known-css-properties": "^0.27.0", + "postcss": "^8.4.5", + "postcss-load-config": "^3.1.4", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.11", + "semver": "^7.5.3", + "svelte-eslint-parser": "^0.32.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "dependencies": { + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "optional": true, - "peer": true + "devOptional": true }, "estree-walker": { "version": "2.0.2", @@ -16873,6 +18434,15 @@ "escape-string-regexp": "^1.0.5" } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -16895,6 +18465,33 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", @@ -17149,6 +18746,20 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -17163,6 +18774,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -17411,6 +19028,12 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, "immutable": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", @@ -17427,6 +19050,12 @@ "resolve-from": "^4.0.0" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, "incremental-convex-hull": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/incremental-convex-hull/-/incremental-convex-hull-1.0.1.tgz", @@ -17621,6 +19250,12 @@ "define-properties": "^1.1.3" } }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -17830,11 +19465,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "jshashes": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/jshashes/-/jshashes-1.0.8.tgz", - "integrity": "sha512-btmQZ/w1rj8Lb6nEwvhjM7nBYoj54yaEFo2PWh3RkxZ8qNwuvOxvQYN/JxVuwoMmdIluL+XwYVJ+pEEZoSYybQ==" - }, "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -17855,6 +19485,12 @@ "jsonify": "^0.0.1" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "json-stringify-pretty-compact": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", @@ -17968,6 +19604,12 @@ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true }, + "known-css-properties": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.27.0.tgz", + "integrity": "sha512-uMCj6+hZYDoffuvAJjFAPz56E9uoowFHmTkqRtRq5WyC5Q6Cu/fTZKNQpX/RbzChBYLLl3lo8CjFZBAZXq9qFg==", + "dev": true + }, "latlon2country": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/latlon2country/-/latlon2country-1.2.6.tgz", @@ -18022,6 +19664,12 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -18401,6 +20049,18 @@ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -18513,14 +20173,6 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, - "ohauth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ohauth/-/ohauth-1.0.1.tgz", - "integrity": "sha512-R9ZUN3+FVCwzeOOHCJpzA9jw/byRxp5O9X06mTL6Sp/LIQn/rLrMv6cwYctX+hoIKzRUsalGJXZ1kG5wBmSskQ==", - "requires": { - "jshashes": "~1.0.8" - } - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -18651,12 +20303,10 @@ "dev": true }, "osm-auth": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/osm-auth/-/osm-auth-1.1.2.tgz", - "integrity": "sha512-oLaU+c/TP7eKAZpBN4S1mv/N94IXp5A+wLpDfAVlpq/b6iikas8ZthXPqhM8QKg/qB8RaKvZPJgxqYS+5m8G8g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/osm-auth/-/osm-auth-2.2.0.tgz", + "integrity": "sha512-x93jAMaYWqPgfVeOMydFLFpFC8ERnlIKXwiUOrYYWTDEWqq15K/BI5UAjzuYXvLg0WxVxM8YC4N1T30SZeKJBQ==", "requires": { - "ohauth": "~1.0.1", - "resolve-url": "~0.2.1", "store": "~2.0.12" } }, @@ -18732,11 +20382,23 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, "pathe": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", @@ -18816,6 +20478,46 @@ "splaytree": "^3.1.0" } }, + "postcss": { + "version": "8.4.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz", + "integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==", + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "dependencies": { + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + } + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "requires": {} + }, + "postcss-scss": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.6.tgz", + "integrity": "sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==", + "dev": true, + "requires": {} + }, "postcss-selector-parser": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", @@ -19236,11 +20938,6 @@ "protocol-buffers-schema": "^3.3.1" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -19553,6 +21250,21 @@ } } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "showdown": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", @@ -19632,6 +21344,12 @@ "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -19739,12 +21457,6 @@ } } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, "sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", @@ -19878,9 +21590,9 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "svelte": { - "version": "3.55.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.55.1.tgz", - "integrity": "sha512-S+87/P0Ve67HxKkEV23iCdAh/SX1xiSfjF1HOglno/YTbSTW7RniICMCofWGdJJbdjw3S+0PfFb1JtGfTXE0oQ==" + "version": "3.59.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.2.tgz", + "integrity": "sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==" }, "svelte-check": { "version": "3.0.3", @@ -19898,6 +21610,19 @@ "typescript": "^4.9.4" } }, + "svelte-eslint-parser": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.32.1.tgz", + "integrity": "sha512-GCSfeIzdgk53CaOzK+s/+l2igfTno3mWGkwoDYAwPes/rD9Al2fc7ksfopjx5UL87S7dw1eL73F6wNYiiuhzIA==", + "dev": true, + "requires": { + "eslint-scope": "^7.0.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "postcss": "^8.4.25", + "postcss-scss": "^4.0.6" + } + }, "svelte-hmr": { "version": "0.15.1", "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.1.tgz", @@ -19983,21 +21708,6 @@ "is-glob": "^4.0.3" } }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" - }, - "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, "postcss-import": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", @@ -20016,15 +21726,6 @@ "camelcase-css": "^2.0.1" } }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - } - }, "postcss-nested": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", @@ -20108,6 +21809,12 @@ "utrie": "^1.0.2" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -20231,6 +21938,13 @@ "punycode": "^2.3.0" } }, + "ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "requires": {} + }, "ts-json-schema-generator": { "version": "0.95.0", "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-0.95.0.tgz", @@ -20392,96 +22106,6 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "devOptional": true }, - "tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tslint-no-circular-imports": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tslint-no-circular-imports/-/tslint-no-circular-imports-0.7.0.tgz", - "integrity": "sha512-k3wxpeMC4ef40UbpfBVHEHIzKfNZq5/SCtAO1YjGsaNTklo+K53/TWLrym+poA65RJFDiYgYNWvkeIIkJNA0Vw==", - "dev": true, - "requires": {} - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -21015,9 +22639,9 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" }, "typescript-json-schema": { "version": "0.50.1", @@ -21248,23 +22872,6 @@ "postcss": "^8.4.20", "resolve": "^1.22.1", "rollup": "^3.7.0" - }, - "dependencies": { - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" - }, - "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - } } }, "vite-node": { @@ -21605,4 +23212,4 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 20ce152ef..fff429293 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,58 @@ { "name": "mapcomplete", - "version": "0.31.4", + "version": "0.32.0", "repository": "https://github.com/pietervdvn/MapComplete", "description": "A small website to edit OSM easily", "bugs": "https://github.com/pietervdvn/MapComplete/issues", "homepage": "https://mapcomplete.org", "main": "index.ts", "type": "module", + "config": { + "#": "Various endpoints that are instance-specific", + "#oauth_credentials:comment": [ + "`oauth_credentials` are the OAuth-2 credentials for the production-OSM server and the test-server.", + "Are you deploying your own instance? Register your application too.", + "See https://wiki.openstreetmap.org/wiki/OAuth#Registering_your_application_as_OAuth_2.0_consumer for instructions", + "Use `https:////land.html` as redirect URIs. You can add `http://127.0.0.1:1234/land.html` too for local development.", + "Alternatively, you can override the `osm` credentials using the environment variables `VITE_OSM_OAUTH_CLIENT_ID` and `VITE_OSM_OAUTH_SECRET`" + ], + "oauth_credentials": { + "osm_pietervdvn": { + "#": "This client_id is registered by 'Pieter Vander Vennet' on OSM.org", + "oauth_client_id": "sa1ngLJBJ8McmzHElN8NYtIDm5TZTYEYhq3-0snO4Qc", + "oauth_secret": "XU_cD5Mvw9VKk9T0t_gO8V7cbRC4Hmw2Tb4Rv0Zmz-U", + "url": "https://www.openstreetmap.org" + }, + "osm": { + "#": "This client-id is registered by 'MapComplete' on osm.org", + "oauth_client_id": "K93H1d8ve7p-tVLE1ZwsQ4lAFLQk8INx5vfTLMu5DWk", + "oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg", + "url": "https://www.openstreetmap.org" + }, + "osm-test": { + "oauth_client_id": "HwUn6GPxGm1m9WwMarxTglhy6dBTM4YkaV1I9h6pDGU", + "oauth_secret": "luFZtPJg7j96K6WM6RpcZ_3M-r6muuDq6fG1ygk0I_4", + "url": "https://master.apis.dev.openstreetmap.org" + } + }, + "api_keys": { + "#": "Various API-keys for various services. Feel free to reuse those in another MapComplete-hosted version", + "imgur": "7070e7167f0a25a", + "mapillary_v4": "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" + }, + "default_overpass_urls": [ + "https://overpass-api.de/api/interpreter", + "https://overpass.kumi.systems/api/interpreter", + "https://overpass.openstreetmap.ru/cgi/interpreter" + ], + "country_coder_host": "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country" + }, "scripts": { "start": "npm run generate:layeroverview && npm run strt", "strt": "vite --host", "strttest": "export NODE_OPTIONS=--max_old_space_size=8364 && parcel serve test.html assets/templates/*.svg assets/templates/fonts/*.ttf", "watch:css": "tailwindcss -i index.css -o public/css/index-tailwind-output.css --watch", - "generate:css": "tailwindcss -i index.css -o public/css/index-tailwind-output.css", + "generate:css": "tailwindcss -i src/index.css -o public/css/index-tailwind-output.css", "generate:doctests": "doctest-ts-improved . --ignore .*.spec.ts --ignore .*ConfigJson.ts", "test:run-only": "vitest --run test", "test": " export NODE_OPTIONS=\"--max-old-space-size=8192\" && npm run clean:tests && (npm run generate:doctests 2>&1 | grep -v \"No doctests found in\") && npm run test:run-only && npm run clean:tests", @@ -27,6 +67,7 @@ "generate:cache:speelplekken": "npm run generate:layeroverview && vite-node scripts/generateCache.ts -- speelplekken 14 ../MapComplete-data/speelplekken_cache/ 51.20 4.35 51.09 4.56", "generate:cache:natuurpunt": "npm run generate:layeroverview && vite-node scripts/generateCache.ts -- natuurpunt 12 ../MapComplete-data/natuurpunt_cache/ 50.40 2.1 51.54 6.4 --generate-point-overview nature_reserve,visitor_information_centre", "generate:layeroverview": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts", + "generate:mapcomplete-changes-theme": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts -- --generate-change-map", "refresh:layeroverview": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts -- --force", "generate:licenses": "vite-node scripts/generateLicenseInfo.ts -- --no-fail", "query:licenses": "vite-node scripts/generateLicenseInfo.ts -- --query", @@ -39,6 +80,9 @@ "generate": "mkdir -p ./assets/generated; npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:translations; npm run reset:layeroverview; npm run generate:service-worker", "generate:charging-stations": "cd ./assets/layers/charging_station && vite-node csvToJson.ts && cd -", "prepare-deploy": "npm run generate:service-worker && ./scripts/build.sh", + "lint": "npm run lint:prettier && npm run lint:eslint", + "lint:eslint": "eslint ./src", + "lint:prettier": "prettier --check '**/*.ts' '**/*.svelte'", "format": "prettier --write '**/*.ts' '**/*.svelte'", "clean:tests": "find . -type f -name \"*.doctest.ts\" | xargs -r rm", "clean": "rm -rf .cache/ && (find *.html | grep -v \"^\\(404\\|index\\|land\\|test\\|studio\\|theme\\|style_test\\|statistics\\).html\" | xargs -r rm) && (ls | grep \"^index_[a-zA-Z_-]\\+\\.ts$\" | xargs -r rm)", @@ -93,7 +137,7 @@ "mangrove-reviews-typescript": "^1.1.0", "maplibre-gl": "^3.2.0", "opening_hours": "^3.6.0", - "osm-auth": "^1.0.2", + "osm-auth": "^2.2.0", "osmtogeojson": "^3.0.0-beta.5", "papaparse": "^5.3.1", "pic4carto": "^2.1.15", @@ -125,9 +169,13 @@ "@types/prompt-sync": "^4.1.0", "@types/wikidata-sdk": "^6.1.0", "@types/xml2js": "^0.4.9", + "@typescript-eslint/eslint-plugin": "^6.1.0", + "@typescript-eslint/parser": "^6.1.0", "assert": "^2.0.0", "chai": "^4.3.6", "dependency-cruiser": "^10.4.0", + "eslint": "^8.45.0", + "eslint-plugin-svelte": "^2.32.2", "fs": "0.0.1-security", "node-html-parser": "^6.1.5", "prettier": "^2.8.8", @@ -142,8 +190,6 @@ "ts-node": "^10.9.1", "ts2json-schema": "^1.4.0", "tslib": "^2.5.0", - "tslint": "^6.1.3", - "tslint-no-circular-imports": "^0.7.0", "typescript": "^4.7.4", "vite": "^4.0.5" } diff --git a/public/css/index-tailwind-output.css b/public/css/index-tailwind-output.css index e2b1f304b..91a0cd7e0 100644 --- a/public/css/index-tailwind-output.css +++ b/public/css/index-tailwind-output.css @@ -698,13 +698,6 @@ video { position: sticky; } -.inset-0 { - top: 0px; - right: 0px; - bottom: 0px; - left: 0px; -} - .-inset-1 { top: -0.25rem; right: -0.25rem; @@ -744,26 +737,6 @@ video { bottom: 0px; } -.top-12 { - top: 3rem; -} - -.left-3 { - left: 0.75rem; -} - -.top-3 { - top: 0.75rem; -} - -.right-2 { - right: 0.5rem; -} - -.bottom-3 { - bottom: 0.75rem; -} - .right-1\/3 { right: 33.333333%; } @@ -780,14 +753,6 @@ video { top: 2.5rem; } -.left-1\/2 { - left: 50%; -} - -.top-1\/2 { - top: 50%; -} - .isolate { isolation: isolate; } @@ -874,6 +839,11 @@ video { margin-right: 0.5rem; } +.my-1 { + margin-top: 0.25rem; + margin-bottom: 0.25rem; +} + .mx-4 { margin-left: 1rem; margin-right: 1rem; @@ -896,10 +866,6 @@ video { margin-right: 1.5rem; } -.mt-6 { - margin-top: 1.5rem; -} - .mt-1 { margin-top: 0.25rem; } @@ -976,14 +942,6 @@ video { margin-left: -1.5rem; } -.-ml-12 { - margin-left: -3rem; -} - -.-mt-12 { - margin-top: -3rem; -} - .mr-3 { margin-right: 0.75rem; } @@ -1122,11 +1080,6 @@ video { height: 1rem; } -.h-min { - height: -webkit-min-content; - height: min-content; -} - .h-1\/2 { height: 50%; } @@ -1328,23 +1281,6 @@ video { animation: spin 1s linear infinite; } -@-webkit-keyframes pulse { - 50% { - opacity: .5; - } -} - -@keyframes pulse { - 50% { - opacity: .5; - } -} - -.animate-pulse { - -webkit-animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; - animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; -} - .cursor-pointer { cursor: pointer; } @@ -1458,6 +1394,12 @@ video { column-gap: 0.25rem; } +.space-x-1 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.25rem * var(--tw-space-x-reverse)); + margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse))); +} + .space-y-reverse > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 1; } @@ -1506,8 +1448,8 @@ video { overflow: hidden; } -.overflow-scroll { - overflow: scroll; +.overflow-x-auto { + overflow-x: auto; } .overflow-y-auto { @@ -1557,18 +1499,14 @@ video { border-radius: 1rem; } -.rounded-3xl { - border-radius: 1.5rem; +.rounded-md { + border-radius: 0.375rem; } .rounded-lg { border-radius: 0.5rem; } -.rounded-md { - border-radius: 0.375rem; -} - .rounded-sm { border-radius: 0.125rem; } @@ -1699,11 +1637,6 @@ video { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.bg-red-500 { - --tw-bg-opacity: 1; - background-color: rgb(239 68 68 / var(--tw-bg-opacity)); -} - .bg-black { --tw-bg-opacity: 1; background-color: rgb(0 0 0 / var(--tw-bg-opacity)); @@ -1740,10 +1673,6 @@ video { padding: 0.5rem; } -.p-3 { - padding: 0.75rem; -} - .p-4 { padding: 1rem; } @@ -1780,6 +1709,11 @@ video { padding-right: 0.5rem; } +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + .pl-1 { padding-left: 0.25rem; } @@ -1788,10 +1722,6 @@ video { padding-right: 0.5rem; } -.pl-3 { - padding-left: 0.75rem; -} - .pl-2 { padding-left: 0.5rem; } @@ -1820,6 +1750,10 @@ video { padding-left: 1rem; } +.pl-3 { + padding-left: 0.75rem; +} + .pr-0 { padding-right: 0px; } @@ -1879,11 +1813,6 @@ video { line-height: 1.5rem; } -.text-xs { - font-size: 0.75rem; - line-height: 1rem; -} - .font-bold { font-weight: 700; } @@ -2122,12 +2051,6 @@ video { backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia); } -.transition-colors { - transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - .transition { transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, -webkit-transform, -webkit-filter, -webkit-backdrop-filter; transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; @@ -2136,6 +2059,12 @@ video { transition-duration: 150ms; } +.transition-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + .ease-in-out { transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } @@ -2736,10 +2665,6 @@ a.link-underline { } @media (min-width: 640px) { - .sm\:top-3 { - top: 0.75rem; - } - .sm\:m-2 { margin: 0.5rem; } @@ -2778,40 +2703,18 @@ a.link-underline { height: 6rem; } - .sm\:w-fit { - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - } - .sm\:w-24 { width: 6rem; } - .sm\:max-w-sm { - max-width: 24rem; - } - .sm\:max-w-xl { max-width: 36rem; } - .sm\:flex-row { - flex-direction: row; - } - - .sm\:flex-wrap { - flex-wrap: wrap; - } - .sm\:flex-nowrap { flex-wrap: nowrap; } - .sm\:items-start { - align-items: flex-start; - } - .sm\:items-stretch { align-items: stretch; } @@ -2832,10 +2735,6 @@ a.link-underline { padding: 0.5rem; } - .sm\:pl-0 { - padding-left: 0px; - } - .sm\:pt-1 { padding-top: 0.25rem; } @@ -2901,10 +2800,6 @@ a.link-underline { width: 2rem; } - .md\:w-1\/3 { - width: 33.333333%; - } - .md\:w-6\/12 { width: 50%; } diff --git a/scripts/@types/eli.ts b/scripts/@types/eli.ts new file mode 100644 index 000000000..87e1f85af --- /dev/null +++ b/scripts/@types/eli.ts @@ -0,0 +1,213 @@ +import { Feature, FeatureCollection } from "geojson" + +export interface Eli extends FeatureCollection { + features: EliEntry[] +} + +export interface EliEntry extends Feature { + properties: { + /** + * The name of the imagery source + */ + name: string + + /** + * Whether the imagery name should be translated + */ + i18n?: boolean + + /** + * Type of layer + */ + type: "tms" | "wms" | "bing" | "scanex" | "wms_endpoint" | "wmts" + + /** + * A rough categorisation of different types of layers. + * @see https://github.com/osmlab/editor-layer-index/blob/gh-pages/CONTRIBUTING.md#categories + */ + category?: + | "photo" + | "map" + | "historicmap" + | "osmbasedmap" + | "historicphoto" + | "qa" + | "elevation" + | "other" + + /** + * A URL template for imagery tiles + */ + url: string + + /** + * The minimum zoom level + */ + min_zoom?: number + + /** + * The maximum zoom level + */ + max_zoom?: number + + /** + * explicit/implicit permission by the owner for use in OSM + */ + permission_osm?: "explicit" | "implicit" | "no" + + /** + * A URL for the license or permissions for the imagery + */ + license_url?: string + + /** + * A URL for the privacy policy of the operator or false if there is no existing privacy policy for tis imagery. + */ + privacy_policy_url?: string | boolean + + /** + * A unique identifier for the source; used in imagery_used changeset tag + */ + id: string + + /** + * A short English-language description of the source + */ + description?: string + + /** + * The ISO 3166-1 alpha-2 two letter country code in upper case. Use ZZ for unknown or multiple. + */ + country_code?: string + + /** + * Whether this imagery should be shown in the default world-wide menu + */ + default?: boolean + + /** + * Whether this imagery is the best source for the region + */ + best?: boolean + + /** + * The age of the oldest imagery or data in the source, as an RFC3339 date or leading portion of one + */ + start_date?: string + + /** + * The age of the newest imagery or data in the source, as an RFC3339 date or leading portion of one + */ + end_date?: string + + /** + * HTTP header to check for information if the tile is invalid + */ + no_tile_header?: { [header: string]: string[] } | null + + /** + * 'true' if tiles are transparent and can be overlaid on another source + */ + overlay?: boolean + + /** + * Available projections + */ + available_projections?: string[] + + /** + * Attribution + */ + attribution?: { + /** + * URL + */ + url?: string + + /** + * Text + */ + text?: string + + /** + * HTML formatted attribution + */ + html?: string + + /** + * Whether attribution is required + */ + required?: boolean + } + + /** + * A URL for an image, that can be displayed in the list of imagery layers next to the name + */ + icon?: string + + /** + * A link to an EULA text that has to be accepted by the user, before the imagery source is added. Can contain {lang} to be replaced by a current user language wiki code (like FR:) or an empty string for the default English text. + */ + eula?: string + + /** + * A URL for an image, that is displayed in the mapview for attribution + */ + "logo-image"?: string + + /** + * Customized text for the terms of use link (default is "Background Terms of Use") + */ + "terms-of-use-text"?: string + + /** + * Specify a checksum for tiles, which aren't real tiles. `type` is the digest type and can be MD5, SHA-1, SHA-256, SHA-384 and SHA-512, value is the hex encoded checksum in lower case. To create a checksum save the tile as file and upload it to e.g. https://defuse.ca/checksums.htm. + */ + "no-tile-checksum"?: string + + /** + * header-name attribute specifies a header returned by tile server, that will be shown as `metadata-key` attribute in Show Tile Info dialog + */ + "metadata-header"?: string + + /** + * Set to `true` if imagery source is properly aligned and does not need imagery offset adjustments. This is used for OSM based sources too. + */ + "valid-georeference"?: boolean + + /** + * Size of individual tiles delivered by a TMS service + */ + "tile-size"?: number + + /** + * Whether tiles status can be accessed by appending /status to the tile URL and can be submitted for re-rendering by appending /dirty. + */ + "mod-tile-features"?: string + + /** + * HTTP headers to be sent to server. It has two attributes header-name and header-value. May be specified multiple times. + */ + "custom-http-headers"?: { "header-name": string; "header-value": string }[] + + /** + * Default layer to open (when using WMS_ENDPOINT type). Contains list of layer tag with two attributes - name and style, e.g. `\"default-layers\": [\"layer\": { name=\"Basisdata_NP_Basiskart_JanMayen_WMTS_25829\" \"style\":\"default\" } ]` (not allowed in `mirror` attribute) + */ + "default-layers"?: { layer: { "layer-name": string; "layer-style": string } }[] + + /** + * format to use when connecting tile server (when using WMS_ENDPOINT type) + */ + format?: string + + /** + * If `true` transparent tiles will be requested from WMS server + */ + transparent?: boolean + + /** + * minimum expiry time for tiles in seconds. The larger the value, the longer entry in cache will be considered valid + */ + "minimum-tile-expire"?: number + } +} diff --git a/scripts/GenerateSeries.ts b/scripts/GenerateSeries.ts index 6ed84955f..3017e8180 100644 --- a/scripts/GenerateSeries.ts +++ b/scripts/GenerateSeries.ts @@ -1,10 +1,10 @@ import { existsSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from "fs" import ScriptUtils from "./ScriptUtils" -import { Utils } from "../Utils" +import { Utils } from "../src/Utils" import Script from "./Script" -import { GeoOperations } from "../Logic/GeoOperations" +import { GeoOperations } from "../src/Logic/GeoOperations" import { Feature, Polygon } from "geojson" -import { Tiles } from "../Models/TileRange" +import { Tiles } from "../src/Models/TileRange" class StatsDownloader { private readonly urlTemplate = diff --git a/scripts/downloadEli.ts b/scripts/downloadEli.ts index 39f903ba2..97758888b 100644 --- a/scripts/downloadEli.ts +++ b/scripts/downloadEli.ts @@ -1,6 +1,6 @@ import Script from "./Script" import { Utils } from "../src/Utils" -import { FeatureCollection } from "geojson" +import { Eli, EliEntry } from "./@types/eli" import fs from "fs" class DownloadEli extends Script { @@ -12,8 +12,8 @@ class DownloadEli extends Script { // Target should use '.json' instead of '.geojson', as the latter cannot be imported by the build systems const target = args[0] ?? "src/assets/editor-layer-index.json" - const eli = await Utils.downloadJson(url) - const keptLayers = [] + const eli: Eli = await Utils.downloadJson(url) + const keptLayers: EliEntry[] = [] console.log("Got", eli.features.length, "ELI-entries") for (let layer of eli.features) { const props = layer.properties @@ -45,11 +45,11 @@ class DownloadEli extends Script { continue } - if (props.permission_url === "no") { + if (props.permission_osm === "no") { continue } - if (props.max_zoom < 19) { + if (props.max_zoom && props.max_zoom < 19) { // We want users to zoom to level 19 when adding a point // If they are on a layer which hasn't enough precision, they can not zoom far enough. This is confusing, so we don't use this layer continue @@ -60,24 +60,24 @@ class DownloadEli extends Script { continue } - const keptKeys = [ - "name", - "id", - "url", - "attribution", - "type", - "category", - "min_zoom", - "max_zoom", - "best", - "default", - "tile-size", - ] - layer.properties = {} - for (const keptKey of keptKeys) { - if (props[keptKey]) { - layer.properties[keptKey] = props[keptKey] - } + if (props.url.startsWith("http://")) { + // Mixed content will not work properly, so we don't use this layer + continue + } + + // Override the layer, so it contains only the properties we need + layer.properties = { + name: props.name, + id: props.id, + url: props.url, + attribution: props.attribution, + type: props.type, + category: props.category, + min_zoom: props.min_zoom, + max_zoom: props.max_zoom, + best: props.best ? true : undefined, + default: props.default ? true : undefined, + "tile-size": props["tile-size"], } layer = { properties: layer.properties, type: layer.type, geometry: layer.geometry } diff --git a/scripts/fixQuestionHint.ts b/scripts/fixQuestionHint.ts index e7b0a1b1e..1406d2b32 100644 --- a/scripts/fixQuestionHint.ts +++ b/scripts/fixQuestionHint.ts @@ -1,10 +1,10 @@ import * as fs from "fs" -import { DesugaringStep } from "../Models/ThemeConfig/Conversion/Conversion" -import { LayerConfigJson } from "../Models/ThemeConfig/Json/LayerConfigJson" -import { QuestionableTagRenderingConfigJson } from "../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" +import { DesugaringStep } from "../src/Models/ThemeConfig/Conversion/Conversion" +import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" +import { QuestionableTagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" import * as fakedom from "fake-dom" import Script from "./Script" -import { FixedUiElement } from "../UI/Base/FixedUiElement" +import { FixedUiElement } from "../src/UI/Base/FixedUiElement" class ExtractQuestionHint extends DesugaringStep { constructor() { diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index 8cf68d9ff..926932c35 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -20,7 +20,7 @@ import { DesugaringContext } from "../src/Models/ThemeConfig/Conversion/Conversi import { Utils } from "../src/Utils" import Script from "./Script" import { AllSharedLayers } from "../src/Customizations/AllSharedLayers" - +import { parse as parse_html } from "node-html-parser" // This scripts scans 'src/assets/layers/*.json' for layer definition files and 'src/assets/themes/*.json' for theme definition files. // It spits out an overview of those to be used to load them @@ -269,7 +269,8 @@ class LayerOverviewUtils extends Script { if ( recompiledThemes.length > 0 && - !(recompiledThemes.length === 1 && recompiledThemes[0] === "mapcomplete-changes") + !(recompiledThemes.length === 1 && recompiledThemes[0] === "mapcomplete-changes") && + args.indexOf("--generate-change-map") >= 0 ) { // mapcomplete-changes shows an icon for each corresponding mapcomplete-theme const iconsPerTheme = Array.from(sharedThemes.values()).map((th) => ({ @@ -516,7 +517,9 @@ class LayerOverviewUtils extends Script { hideFromOverview: t.hideFromOverview ?? false, shortDescription: t.shortDescription ?? - new Translation(t.description).FirstSentence().translations, + new Translation(t.description) + .FirstSentence() + .OnEveryLanguage((s) => parse_html(s).innerText).translations, mustHaveLanguage: t.mustHaveLanguage?.length > 0, } }) diff --git a/src/Logic/ImageProviders/Mapillary.ts b/src/Logic/ImageProviders/Mapillary.ts index 1fbbbc145..102bb709b 100644 --- a/src/Logic/ImageProviders/Mapillary.ts +++ b/src/Logic/ImageProviders/Mapillary.ts @@ -86,7 +86,7 @@ export class Mapillary extends ImageProvider { public async DownloadAttribution(url: string): Promise { const license = new LicenseInfo() - license.artist = "Contributor name unavailable" + license.artist = undefined license.license = "CC BY-SA 4.0" // license.license = "Creative Commons Attribution-ShareAlike 4.0 International License"; license.attributionRequired = true diff --git a/src/Logic/Osm/Actions/ChangeTagAction.ts b/src/Logic/Osm/Actions/ChangeTagAction.ts index 1abfb6798..72fbffab4 100644 --- a/src/Logic/Osm/Actions/ChangeTagAction.ts +++ b/src/Logic/Osm/Actions/ChangeTagAction.ts @@ -28,7 +28,7 @@ export default class ChangeTagAction extends OsmChangeAction { currentTags: Record, meta: { theme: string - changeType: "answer" | "soft-delete" | "add-image" | string + changeType: "answer" | "soft-delete" | "add-image" | "link-image" | string } ) { super(elementId, true) diff --git a/src/Logic/Osm/Actions/LinkPicture.ts b/src/Logic/Osm/Actions/LinkPicture.ts new file mode 100644 index 000000000..014a836a0 --- /dev/null +++ b/src/Logic/Osm/Actions/LinkPicture.ts @@ -0,0 +1,32 @@ +import ChangeTagAction from "./ChangeTagAction" +import { Tag } from "../../Tags/Tag" + +export default class LinkPicture extends ChangeTagAction { + /** + * Adds a link to an image + * @param elementId + * @param proposedKey: a key which might be used, typically `image`. If the key is already used with a different URL, `key+":0"` will be used instead (or a higher number if needed) + * @param url + * @param currentTags + * @param meta + * + */ + constructor( + elementId: string, + proposedKey: "image" | "mapillary" | "wiki_commons" | string, + url: string, + currentTags: Record, + meta: { + theme: string + changeType: "add-image" | "link-image" + } + ) { + let key = proposedKey + let i = 0 + while (currentTags[key] !== undefined && currentTags[key] !== url) { + key = proposedKey + ":" + i + i++ + } + super(elementId, new Tag(key, url), currentTags, meta) + } +} diff --git a/src/Logic/Osm/OsmConnection.ts b/src/Logic/Osm/OsmConnection.ts index a14d30849..b4b47d68e 100644 --- a/src/Logic/Osm/OsmConnection.ts +++ b/src/Logic/Osm/OsmConnection.ts @@ -1,8 +1,10 @@ -import osmAuth from "osm-auth" +// @ts-ignore +import { osmAuth } from "osm-auth" import { Store, Stores, UIEventSource } from "../UIEventSource" import { OsmPreferences } from "./OsmPreferences" import { Utils } from "../../Utils" - +import { LocalStorageSource } from "../Web/LocalStorageSource" +import * as config from "../../../package.json" export default class UserDetails { public loggedIn = false public name = "Not logged in" @@ -22,23 +24,18 @@ export default class UserDetails { } } +export interface AuthConfig { + "#"?: string // optional comment + oauth_client_id: string + oauth_secret: string + url: string +} + export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable" export class OsmConnection { - public static readonly oauth_configs = { - osm: { - oauth_consumer_key: "hivV7ec2o49Two8g9h8Is1VIiVOgxQ1iYexCbvem", - oauth_secret: "wDBRTCem0vxD7txrg1y6p5r8nvmz8tAhET7zDASI", - url: "https://www.openstreetmap.org", - // OAUTH 1.0 application - // https://www.openstreetmap.org/user/Pieter%20Vander%20Vennet/oauth_clients/7404 - }, - "osm-test": { - oauth_consumer_key: "Zgr7EoKb93uwPv2EOFkIlf3n9NLwj5wbyfjZMhz2", - oauth_secret: "3am1i1sykHDMZ66SGq4wI2Z7cJMKgzneCHp3nctn", - url: "https://master.apis.dev.openstreetmap.org", - }, - } + public static readonly oauth_configs: Record = + config.config.oauth_credentials public auth public userDetails: UIEventSource public isLoggedIn: Store @@ -53,11 +50,7 @@ export class OsmConnection { "not-attempted" ) public preferencesHandler: OsmPreferences - public readonly _oauth_config: { - oauth_consumer_key: string - oauth_secret: string - url: string - } + public readonly _oauth_config: AuthConfig private readonly _dryRun: Store private fakeUser: boolean private _onLoggedIn: ((userDetails: UserDetails) => void)[] = [] @@ -83,6 +76,19 @@ export class OsmConnection { console.debug("Using backend", this._oauth_config.url) this._iframeMode = Utils.runningFromConsole ? false : window !== window.top + // Check if there are settings available in environment variables, and if so, use those + if ( + import.meta.env.VITE_OSM_OAUTH_CLIENT_ID !== undefined && + import.meta.env.VITE_OSM_OAUTH_SECRET !== undefined + ) { + console.debug("Using environment variables for oauth config") + this._oauth_config = { + oauth_client_id: import.meta.env.VITE_OSM_OAUTH_CLIENT_ID, + oauth_secret: import.meta.env.VITE_OSM_OAUTH_SECRET, + url: "https://www.openstreetmap.org", + } + } + this.userDetails = new UIEventSource( new UserDetails(this._oauth_config.url), "userDetails" @@ -190,6 +196,9 @@ export class OsmConnection { const self = this console.log("Trying to log in...") this.updateAuthObject() + LocalStorageSource.Get("location_before_login").setData( + Utils.runningFromConsole ? undefined : window.location.href + ) this.auth.xhr( { method: "GET", @@ -202,13 +211,8 @@ export class OsmConnection { if (err.status == 401) { console.log("Clearing tokens...") // Not authorized - our token probably got revoked - // Reset all the tokens - const tokens = [ - "https://www.openstreetmap.orgoauth_request_token_secret", - "https://www.openstreetmap.orgoauth_token", - "https://www.openstreetmap.orgoauth_token_secret", - ] - tokens.forEach((token) => localStorage.removeItem(token)) + self.auth.logout() + self.LogOut() } return } @@ -310,6 +314,7 @@ export class OsmConnection { ): Promise { return await this.interact(path, "POST", header, content) } + public async put( path: string, content?: string, @@ -486,15 +491,29 @@ export class OsmConnection { // Same for an iframe... this.auth = new osmAuth({ - oauth_consumer_key: this._oauth_config.oauth_consumer_key, - oauth_secret: this._oauth_config.oauth_secret, + client_id: this._oauth_config.oauth_client_id, url: this._oauth_config.url, - landing: standalone ? undefined : window.location.href, + scope: "read_prefs write_prefs write_api write_gpx write_notes", + redirect_uri: Utils.runningFromConsole + ? "https://mapcomplete.org/land.html" + : window.location.protocol + "//" + window.location.host + "/land.html", singlepage: !standalone, auto: true, }) } + /** + * To be called by land.html + */ + public finishLogin(callback: (previousURL: string) => void) { + this.auth.authenticate(function () { + // Fully authed at this point + console.log("Authentication successful!") + const previousLocation = LocalStorageSource.Get("location_before_login") + callback(previousLocation.data) + }) + } + private CheckForMessagesContinuously() { const self = this if (this.isChecking) { diff --git a/src/Logic/Web/NearbyImagesSearch.ts b/src/Logic/Web/NearbyImagesSearch.ts new file mode 100644 index 000000000..665cc66e7 --- /dev/null +++ b/src/Logic/Web/NearbyImagesSearch.ts @@ -0,0 +1,222 @@ +import { IndexedFeatureSource } from "../FeatureSource/FeatureSource" +import { GeoOperations } from "../GeoOperations" +import { ImmutableStore, Store, Stores, UIEventSource } from "../UIEventSource" +import { Mapillary } from "../ImageProviders/Mapillary" +import P4C from "pic4carto" +import { Utils } from "../../Utils" +export interface NearbyImageOptions { + lon: number + lat: number + // Radius of the upstream search + searchRadius?: 500 | number + maxDaysOld?: 1095 | number + blacklist: Store<{ url: string }[]> + shownImagesCount?: UIEventSource + towardscenter?: UIEventSource + allowSpherical?: UIEventSource + // Radius of what is shown. Useless to select a value > searchRadius; defaults to searchRadius + shownRadius?: UIEventSource +} + +export interface P4CPicture { + pictureUrl: string + date?: number + coordinates: { lat: number; lng: number } + provider: "Mapillary" | string + author? + license? + detailsUrl?: string + direction? + osmTags?: object /*To copy straight into OSM!*/ + thumbUrl: string + details: { + isSpherical: boolean + } +} + +/** + * Uses Pic4wCarto to fetch nearby images from various providers + */ +export default class NearbyImagesSearch { + private static readonly services = [ + "mapillary", + "flickr", + "openstreetcam", + "wikicommons", + ] as const + + private individualStores + private readonly _store: UIEventSource = new UIEventSource([]) + public readonly store: Store = this._store + private readonly _options: NearbyImageOptions + + constructor(options: NearbyImageOptions, features: IndexedFeatureSource) { + this.individualStores = NearbyImagesSearch.services.map((s) => + NearbyImagesSearch.buildPictureFetcher(options, s) + ) + this._options = options + if (features !== undefined) { + const osmImages = new ImagesInLoadedDataFetcher(features).fetchAround({ + lat: options.lat, + lon: options.lon, + searchRadius: options.searchRadius ?? 100, + }) + this.individualStores.push( + new ImmutableStore({ images: osmImages, beforeFilter: osmImages.length }) + ) + } + for (const source of this.individualStores) { + source.addCallback(() => this.update()) + } + this.update() + } + + private static buildPictureFetcher( + options: NearbyImageOptions, + fetcher: "mapillary" | "flickr" | "openstreetcam" | "wikicommons" + ): Store<{ images: P4CPicture[]; beforeFilter: number }> { + const picManager = new P4C.PicturesManager({ usefetchers: [fetcher] }) + const searchRadius = options.searchRadius ?? 100 + const maxAgeSeconds = (options.maxDaysOld ?? 3 * 365) * 24 * 60 * 60 * 1000 + + const p4cStore = Stores.FromPromise( + picManager.startPicsRetrievalAround( + new P4C.LatLng(options.lat, options.lon), + searchRadius, + { + mindate: new Date().getTime() - maxAgeSeconds, + towardscenter: false, + } + ) + ) + return p4cStore.map( + (images) => { + if (images === undefined) { + return undefined + } + const beforeFilterCount = images.length + if (!options?.allowSpherical?.data) { + images = images?.filter((i) => i.details.isSpherical !== true) + } + + const shownRadius = options?.shownRadius?.data ?? searchRadius + if (shownRadius !== searchRadius) { + images = images.filter((i) => { + const d = GeoOperations.distanceBetween( + [i.coordinates.lng, i.coordinates.lat], + [options.lon, options.lat] + ) + return d <= shownRadius + }) + } + if (options.towardscenter?.data) { + images = images.filter((i) => { + if (i.direction === undefined || isNaN(i.direction)) { + return false + } + const bearing = GeoOperations.bearing( + [i.coordinates.lng, i.coordinates.lat], + [options.lon, options.lat] + ) + const diff = Math.abs((i.direction - bearing) % 360) + return diff < 40 + }) + } + + images?.sort((a, b) => { + const distanceA = GeoOperations.distanceBetween( + [a.coordinates.lng, a.coordinates.lat], + [options.lon, options.lat] + ) + const distanceB = GeoOperations.distanceBetween( + [b.coordinates.lng, b.coordinates.lat], + [options.lon, options.lat] + ) + return distanceA - distanceB + }) + + return { images, beforeFilter: beforeFilterCount } + }, + [options.blacklist, options.allowSpherical, options.towardscenter, options.shownRadius] + ) + } + + private update() { + const seen: Set = new Set(this._options.blacklist.data.map((d) => d.url)) + let beforeFilter = 0 + let result: P4CPicture[] = [] + for (const source of this.individualStores) { + const imgs = source.data + if (imgs === undefined) { + continue + } + beforeFilter = beforeFilter + imgs.beforeFilter + for (const img of imgs.images) { + if (seen.has(img.pictureUrl)) { + continue + } + seen.add(img.pictureUrl) + result.push(img) + } + } + const c = [this._options.lon, this._options.lat] + result.sort((a, b) => { + const da = GeoOperations.distanceBetween([a.coordinates.lng, a.coordinates.lat], c) + const db = GeoOperations.distanceBetween([b.coordinates.lng, b.coordinates.lat], c) + return da - db + }) + if (Utils.sameList(result, this._store.data)) { + // return + } + this._store.setData(result) + } +} + +/** + * Extracts pictures from currently loaded features + */ +class ImagesInLoadedDataFetcher { + private indexedFeatures: IndexedFeatureSource + + constructor(indexedFeatures: IndexedFeatureSource) { + this.indexedFeatures = indexedFeatures + } + + public fetchAround(loc: { lon: number; lat: number; searchRadius?: number }): P4CPicture[] { + const foundImages: P4CPicture[] = [] + this.indexedFeatures.features.data.forEach((feature) => { + const props = feature.properties + const images = [] + if (props.image) { + images.push(props.image) + } + for (let i = 0; i < 10; i++) { + if (props["image:" + i]) { + images.push(props["image:" + i]) + } + } + if (images.length == 0) { + return + } + const centerpoint = GeoOperations.centerpointCoordinates(feature) + const d = GeoOperations.distanceBetween(centerpoint, [loc.lon, loc.lat]) + if (loc.searchRadius !== undefined && d > loc.searchRadius) { + return + } + for (const image of images) { + foundImages.push({ + pictureUrl: image, + thumbUrl: image, + coordinates: { lng: centerpoint[0], lat: centerpoint[1] }, + provider: "OpenStreetMap", + details: { + isSpherical: false, + }, + osmTags: { image }, + }) + } + }) + + return foundImages + } +} diff --git a/src/Models/Constants.ts b/src/Models/Constants.ts index ad7e9a62d..2d7a87e74 100644 --- a/src/Models/Constants.ts +++ b/src/Models/Constants.ts @@ -1,14 +1,13 @@ -import { Utils } from "../Utils" import * as meta from "../../package.json" +import { Utils } from "../Utils" export type PriviligedLayerType = (typeof Constants.priviliged_layers)[number] export default class Constants { public static vNumber = meta.version - public static ImgurApiKey = "7070e7167f0a25a" - public static readonly mapillary_client_token_v4 = - "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" + public static ImgurApiKey = meta.config.api_keys.imgur + public static readonly mapillary_client_token_v4 = meta.config.api_keys.mapillary_v4 /** * API key for Maproulette @@ -19,15 +18,7 @@ export default class Constants { */ public static readonly MaprouletteApiKey = "" - public static defaultOverpassUrls = [ - // The official instance, 10000 queries per day per project allowed - "https://overpass-api.de/api/interpreter", - // 'Fair usage' - "https://overpass.kumi.systems/api/interpreter", - // Offline: "https://overpass.nchc.org.tw/api/interpreter", - "https://overpass.openstreetmap.ru/cgi/interpreter", - // Doesn't support nwr: "https://overpass.openstreetmap.fr/api/interpreter" - ] + public static defaultOverpassUrls = meta.config.default_overpass_urls public static readonly added_by_default = [ "selected_element", @@ -100,6 +91,7 @@ export default class Constants { "etymology", "food", "cafes_and_pubs", + "shops", "playgrounds", "hailhydrant", "toilets", @@ -113,9 +105,8 @@ export default class Constants { * In seconds */ static zoomToLocationTimeout = 15 - static countryCoderEndpoint: string = - "https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/latlon2country" - public static readonly OsmPreferenceKeyPicturesLicense = "pictures-license" + static countryCoderEndpoint: string = meta.config.country_coder_host + /** * These are the values that are allowed to use as 'backdrop' icon for a map pin */ diff --git a/src/Models/ThemeConfig/Conversion/Validation.ts b/src/Models/ThemeConfig/Conversion/Validation.ts index d79c7bc17..d51ae560e 100644 --- a/src/Models/ThemeConfig/Conversion/Validation.ts +++ b/src/Models/ThemeConfig/Conversion/Validation.ts @@ -1,42 +1,43 @@ -import { DesugaringStep, Each, Fuse, On } from "./Conversion" -import { LayerConfigJson } from "../Json/LayerConfigJson" -import LayerConfig from "../LayerConfig" -import { Utils } from "../../../Utils" -import Constants from "../../Constants" -import { Translation } from "../../../UI/i18n/Translation" -import { LayoutConfigJson } from "../Json/LayoutConfigJson" -import LayoutConfig from "../LayoutConfig" -import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" -import { TagUtils } from "../../../Logic/Tags/TagUtils" -import { ExtractImages } from "./FixImages" -import { And } from "../../../Logic/Tags/And" -import Translations from "../../../UI/i18n/Translations" -import Svg from "../../../Svg" -import FilterConfigJson from "../Json/FilterConfigJson" -import DeleteConfig from "../DeleteConfig" -import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson" -import Validators from "../../../UI/InputElement/Validators" -import TagRenderingConfig from "../TagRenderingConfig" +import { DesugaringStep, Each, Fuse, On } from "./Conversion"; +import { LayerConfigJson } from "../Json/LayerConfigJson"; +import LayerConfig from "../LayerConfig"; +import { Utils } from "../../../Utils"; +import Constants from "../../Constants"; +import { Translation } from "../../../UI/i18n/Translation"; +import { LayoutConfigJson } from "../Json/LayoutConfigJson"; +import LayoutConfig from "../LayoutConfig"; +import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"; +import { TagUtils } from "../../../Logic/Tags/TagUtils"; +import { ExtractImages } from "./FixImages"; +import { And } from "../../../Logic/Tags/And"; +import Translations from "../../../UI/i18n/Translations"; +import Svg from "../../../Svg"; +import FilterConfigJson from "../Json/FilterConfigJson"; +import DeleteConfig from "../DeleteConfig"; +import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"; +import Validators from "../../../UI/InputElement/Validators"; +import TagRenderingConfig from "../TagRenderingConfig"; +import { parse as parse_html } from "node-html-parser"; class ValidateLanguageCompleteness extends DesugaringStep { - private readonly _languages: string[] + private readonly _languages: string[]; constructor(...languages: string[]) { super( "Checks that the given object is fully translated in the specified languages", [], "ValidateLanguageCompleteness" - ) - this._languages = languages ?? ["en"] + ); + this._languages = languages ?? ["en"]; } convert( obj: any, context: string ): { result: LayerConfig; errors: string[]; warnings: string[] } { - const errors = [] - const warnings: string[] = [] - const translations = Translation.ExtractAllTranslationsFrom(obj) + const errors = []; + const warnings: string[] = []; + const translations = Translation.ExtractAllTranslationsFrom(obj); for (const neededLanguage of this._languages) { translations .filter( @@ -47,38 +48,38 @@ class ValidateLanguageCompleteness extends DesugaringStep { .forEach((missing) => { errors.push( context + - "A theme should be translation-complete for " + - neededLanguage + - ", but it lacks a translation for " + - missing.context + - ".\n\tThe known translation is " + - missing.tr.textFor("en") - ) - }) + "A theme should be translation-complete for " + + neededLanguage + + ", but it lacks a translation for " + + missing.context + + ".\n\tThe known translation is " + + missing.tr.textFor("en") + ); + }); } return { result: obj, errors, - warnings, - } + warnings + }; } } export class DoesImageExist extends DesugaringStep { - private readonly _knownImagePaths: Set - private readonly _ignore?: Set - private readonly doesPathExist: (path: string) => boolean = undefined + private readonly _knownImagePaths: Set; + private readonly _ignore?: Set; + private readonly doesPathExist: (path: string) => boolean = undefined; constructor( knownImagePaths: Set, checkExistsSync: (path: string) => boolean = undefined, ignore?: Set ) { - super("Checks if an image exists", [], "DoesImageExist") - this._ignore = ignore - this._knownImagePaths = knownImagePaths - this.doesPathExist = checkExistsSync + super("Checks if an image exists", [], "DoesImageExist"); + this._ignore = ignore; + this._knownImagePaths = knownImagePaths; + this.doesPathExist = checkExistsSync; } convert( @@ -86,53 +87,53 @@ export class DoesImageExist extends DesugaringStep { context: string ): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } { if (this._ignore?.has(image)) { - return { result: image } + return { result: image }; } - const errors = [] - const warnings = [] - const information = [] + const errors = []; + const warnings = []; + const information = []; if (image.indexOf("{") >= 0) { - information.push("Ignoring image with { in the path: " + image) - return { result: image } + information.push("Ignoring image with { in the path: " + image); + return { result: image }; } if (image === "assets/SocialImage.png") { - return { result: image } + return { result: image }; } if (image.match(/[a-z]*/)) { if (Svg.All[image + ".svg"] !== undefined) { // This is a builtin img, e.g. 'checkmark' or 'crosshair' - return { result: image } + return { result: image }; } } if (image.startsWith("<") && image.endsWith(">")) { // This is probably HTML, you're on your own here - return { result: image } + return { result: image }; } if (!this._knownImagePaths.has(image)) { if (this.doesPathExist === undefined) { errors.push( `Image with path ${image} not found or not attributed; it is used in ${context}` - ) + ); } else if (!this.doesPathExist(image)) { errors.push( `Image with path ${image} does not exist; it is used in ${context}.\n Check for typo's and missing directories in the path.` - ) + ); } else { errors.push( `Image with path ${image} is not attributed (but it exists); execute 'npm run query:licenses' to add the license information and/or run 'npm run generate:licenses' to compile all the license info` - ) + ); } } return { result: image, errors, warnings, - information, - } + information + }; } } @@ -141,11 +142,11 @@ class ValidateTheme extends DesugaringStep { * The paths where this layer is originally saved. Triggers some extra checks * @private */ - private readonly _path?: string - private readonly _isBuiltin: boolean + private readonly _path?: string; + private readonly _isBuiltin: boolean; //private readonly _sharedTagRenderings: Map - private readonly _validateImage: DesugaringStep - private readonly _extractImages: ExtractImages = undefined + private readonly _validateImage: DesugaringStep; + private readonly _extractImages: ExtractImages = undefined; constructor( doesImageExist: DoesImageExist, @@ -153,12 +154,12 @@ class ValidateTheme extends DesugaringStep { isBuiltin: boolean, sharedTagRenderings?: Set ) { - super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme") - this._validateImage = doesImageExist - this._path = path - this._isBuiltin = isBuiltin + super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme"); + this._validateImage = doesImageExist; + this._path = path; + this._isBuiltin = isBuiltin; if (sharedTagRenderings) { - this._extractImages = new ExtractImages(this._isBuiltin, sharedTagRenderings) + this._extractImages = new ExtractImages(this._isBuiltin, sharedTagRenderings); } } @@ -166,11 +167,11 @@ class ValidateTheme extends DesugaringStep { json: LayoutConfigJson, context: string ): { result: LayoutConfigJson; errors: string[]; warnings: string[]; information: string[] } { - const errors = [] - const warnings = [] - const information = [] + const errors = []; + const warnings = []; + const information = []; - const theme = new LayoutConfig(json, this._isBuiltin) + const theme = new LayoutConfig(json, this._isBuiltin); { // Legacy format checks @@ -178,31 +179,31 @@ class ValidateTheme extends DesugaringStep { if (json["units"] !== undefined) { errors.push( "The theme " + - json.id + - " has units defined - these should be defined on the layer instead. (Hint: use overrideAll: { '+units': ... }) " - ) + json.id + + " has units defined - these should be defined on the layer instead. (Hint: use overrideAll: { '+units': ... }) " + ); } if (json["roamingRenderings"] !== undefined) { errors.push( "Theme " + - json.id + - " contains an old 'roamingRenderings'. Use an 'overrideAll' instead" - ) + json.id + + " contains an old 'roamingRenderings'. Use an 'overrideAll' instead" + ); } } } if (this._isBuiltin && this._extractImages !== undefined) { // Check images: are they local, are the licenses there, is the theme icon square, ... - const images = this._extractImages.convertStrict(json, "validation") - const remoteImages = images.filter((img) => img.path.indexOf("http") == 0) + const images = this._extractImages.convertStrict(json, "validation"); + const remoteImages = images.filter((img) => img.path.indexOf("http") == 0); for (const remoteImage of remoteImages) { errors.push( "Found a remote image: " + - remoteImage + - " in theme " + - json.id + - ", please download it." - ) + remoteImage + + " in theme " + + json.id + + ", please download it." + ); } for (const image of images) { this._validateImage.convertJoin( @@ -211,30 +212,30 @@ class ValidateTheme extends DesugaringStep { errors, warnings, information - ) + ); } } try { if (this._isBuiltin) { if (theme.id !== theme.id.toLowerCase()) { - errors.push("Theme ids should be in lowercase, but it is " + theme.id) + errors.push("Theme ids should be in lowercase, but it is " + theme.id); } const filename = this._path.substring( this._path.lastIndexOf("/") + 1, this._path.length - 5 - ) + ); if (theme.id !== filename) { errors.push( "Theme ids should be the same as the name.json, but we got id: " + - theme.id + - " and filename " + - filename + - " (" + - this._path + - ")" - ) + theme.id + + " and filename " + + filename + + " (" + + this._path + + ")" + ); } this._validateImage.convertJoin( theme.icon, @@ -242,44 +243,44 @@ class ValidateTheme extends DesugaringStep { errors, warnings, information - ) + ); } - const dups = Utils.Dupiclates(json.layers.map((layer) => layer["id"])) + const dups = Utils.Dupiclates(json.layers.map((layer) => layer["id"])); if (dups.length > 0) { errors.push( `The theme ${json.id} defines multiple layers with id ${dups.join(", ")}` - ) + ); } if (json["mustHaveLanguage"] !== undefined) { const checked = new ValidateLanguageCompleteness( ...json["mustHaveLanguage"] - ).convert(theme, theme.id) + ).convert(theme, theme.id); - errors.push(...checked.errors) + errors.push(...checked.errors); } if (!json.hideFromOverview && theme.id !== "personal" && this._isBuiltin) { // The first key in the the title-field must be english, otherwise the title in the loading page will be the different language - const targetLanguage = theme.title.SupportedLanguages()[0] + const targetLanguage = theme.title.SupportedLanguages()[0]; if (targetLanguage !== "en") { warnings.push( `TargetLanguage is not 'en' for public theme ${theme.id}, it is ${targetLanguage}. Move 'en' up in the title of the theme and set it as the first key` - ) + ); } // Official, public themes must have a full english translation - const checked = new ValidateLanguageCompleteness("en").convert(theme, theme.id) - errors.push(...checked.errors) + const checked = new ValidateLanguageCompleteness("en").convert(theme, theme.id); + errors.push(...checked.errors); } } catch (e) { - errors.push(e) + errors.push(e); } return { result: json, errors, warnings, - information, - } + information + }; } } @@ -294,7 +295,7 @@ export class ValidateThemeAndLayers extends Fuse { "Validates a theme and the contained layers", new ValidateTheme(doesImageExist, path, isBuiltin, sharedTagRenderings), new On("layers", new Each(new ValidateLayer(undefined, isBuiltin, doesImageExist))) - ) + ); } } @@ -304,26 +305,26 @@ class OverrideShadowingCheck extends DesugaringStep { "Checks that an 'overrideAll' does not override a single override", [], "OverrideShadowingCheck" - ) + ); } convert( json: LayoutConfigJson, _: string ): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } { - const overrideAll = json.overrideAll + const overrideAll = json.overrideAll; if (overrideAll === undefined) { - return { result: json } + return { result: json }; } - const errors = [] - const withOverride = json.layers.filter((l) => l["override"] !== undefined) + const errors = []; + const withOverride = json.layers.filter((l) => l["override"] !== undefined); for (const layer of withOverride) { for (const key in overrideAll) { if (key.endsWith("+") || key.startsWith("+")) { // This key will _add_ to the list, not overwrite it - so no warning is needed - continue + continue; } if ( layer["override"][key] !== undefined || @@ -334,19 +335,19 @@ class OverrideShadowingCheck extends DesugaringStep { JSON.stringify(layer["builtin"]) + " has a shadowed property: " + key + - " is overriden by overrideAll of the theme" - errors.push(w) + " is overriden by overrideAll of the theme"; + errors.push(w); } } } - return { result: json, errors } + return { result: json, errors }; } } class MiscThemeChecks extends DesugaringStep { constructor() { - super("Miscelleanous checks on the theme", [], "MiscThemesChecks") + super("Miscelleanous checks on the theme", [], "MiscThemesChecks"); } convert( @@ -358,19 +359,19 @@ class MiscThemeChecks extends DesugaringStep { warnings?: string[] information?: string[] } { - const warnings = [] - const errors = [] + const warnings = []; + const errors = []; if (json.id !== "personal" && (json.layers === undefined || json.layers.length === 0)) { - errors.push("The theme " + json.id + " has no 'layers' defined (" + context + ")") + errors.push("The theme " + json.id + " has no 'layers' defined (" + context + ")"); } if (json.socialImage === "") { - warnings.push("Social image for theme " + json.id + " is the emtpy string") + warnings.push("Social image for theme " + json.id + " is the emtpy string"); } return { result: json, warnings, - errors, - } + errors + }; } } @@ -380,7 +381,7 @@ export class PrevalidateTheme extends Fuse { "Various consistency checks on the raw JSON", new MiscThemeChecks(), new OverrideShadowingCheck() - ) + ); } } @@ -390,7 +391,7 @@ export class DetectConflictingAddExtraTags extends DesugaringStep 0)) { - return { result: json } + return { result: json }; } - const tagRendering = new TagRenderingConfig(json) + const tagRendering = new TagRenderingConfig(json); - const errors = [] + const errors = []; for (let i = 0; i < tagRendering.mappings.length; i++) { - const mapping = tagRendering.mappings[i] + const mapping = tagRendering.mappings[i]; if (!mapping.addExtraTags) { - continue + continue; } - const keysInMapping = new Set(mapping.if.usedKeys()) + const keysInMapping = new Set(mapping.if.usedKeys()); - const keysInAddExtraTags = mapping.addExtraTags.map((t) => t.key) + const keysInAddExtraTags = mapping.addExtraTags.map((t) => t.key); - const duplicateKeys = keysInAddExtraTags.filter((k) => keysInMapping.has(k)) + const duplicateKeys = keysInAddExtraTags.filter((k) => keysInMapping.has(k)); if (duplicateKeys.length > 0) { errors.push( "At " + - context + - ".mappings[" + - i + - "]: AddExtraTags overrides a key that is set in the `if`-clause of this mapping. Selecting this answer might thus first set one value (needed to match as answer) and then override it with a different value, resulting in an unsaveable question. The offending `addExtraTags` is " + - duplicateKeys.join(", ") - ) + context + + ".mappings[" + + i + + "]: AddExtraTags overrides a key that is set in the `if`-clause of this mapping. Selecting this answer might thus first set one value (needed to match as answer) and then override it with a different value, resulting in an unsaveable question. The offending `addExtraTags` is " + + duplicateKeys.join(", ") + ); } } return { result: json, - errors, - } + errors + }; } } export class DetectShadowedMappings extends DesugaringStep { - private readonly _calculatedTagNames: string[] + private readonly _calculatedTagNames: string[]; constructor(layerConfig?: LayerConfigJson) { - super("Checks that the mappings don't shadow each other", [], "DetectShadowedMappings") - this._calculatedTagNames = DetectShadowedMappings.extractCalculatedTagNames(layerConfig) + super("Checks that the mappings don't shadow each other", [], "DetectShadowedMappings"); + this._calculatedTagNames = DetectShadowedMappings.extractCalculatedTagNames(layerConfig); } /** @@ -457,11 +458,11 @@ export class DetectShadowedMappings extends DesugaringStep { if (ct.indexOf(":=") >= 0) { - return ct.split(":=")[0] + return ct.split(":=")[0]; } - return ct.split("=")[0] + return ct.split("=")[0]; }) ?? [] - ) + ); } /** @@ -501,40 +502,40 @@ export class DetectShadowedMappings extends DesugaringStep { - const ctx = `${context}.mappings[${i}]` - const ifTags = TagUtils.Tag(m.if, ctx) - const hideInAnswer = m["hideInAnswer"] + const ctx = `${context}.mappings[${i}]`; + const ifTags = TagUtils.Tag(m.if, ctx); + const hideInAnswer = m["hideInAnswer"]; if (hideInAnswer !== undefined && hideInAnswer !== false && hideInAnswer !== true) { - let conditionTags = TagUtils.Tag(hideInAnswer) + let conditionTags = TagUtils.Tag(hideInAnswer); // Merge the condition too! - return new And([conditionTags, ifTags]) + return new And([conditionTags, ifTags]); } - return ifTags - }) + return ifTags; + }); for (let i = 0; i < json.mappings.length; i++) { if (!parsedConditions[i].isUsableAsAnswer()) { // There is no straightforward way to convert this mapping.if into a properties-object, so we simply skip this one // Yes, it might be shadowed, but running this check is to difficult right now - continue + continue; } - const keyValues = parsedConditions[i].asChange(defaultProperties) - const properties = {} + const keyValues = parsedConditions[i].asChange(defaultProperties); + const properties = {}; keyValues.forEach(({ k, v }) => { - properties[k] = v - }) + properties[k] = v; + }); for (let j = 0; j < i; j++) { - const doesMatch = parsedConditions[j].matchesProperties(properties) + const doesMatch = parsedConditions[j].matchesProperties(properties); if ( doesMatch && json.mappings[j]["hideInAnswer"] === true && @@ -542,15 +543,15 @@ export class DetectShadowedMappings extends DesugaringStep= 0 - const images = Utils.Dedup(Translations.T(mapping.then)?.ExtractImages() ?? []) - const ctx = `${context}.mappings[${i}]` + const mapping = json.mappings[i]; + const ignore = mapping["#"]?.indexOf(ignoreToken) >= 0; + const images = Utils.Dedup(Translations.T(mapping.then)?.ExtractImages() ?? []); + const ctx = `${context}.mappings[${i}]`; if (images.length > 0) { if (!ignore) { errors.push( `${ctx}: A mapping has an image in the 'then'-clause. Remove the image there and use \`"icon": \` instead. The images found are ${images.join( ", " )}. (This check can be turned of by adding "#": "${ignoreToken}" in the mapping, but this is discouraged` - ) + ); } else { information.push( `${ctx}: Ignored image ${images.join( ", " )} in 'then'-clause of a mapping as this check has been disabled` - ) + ); for (const image of images) { - this._doesImageExist.convertJoin(image, ctx, errors, warnings, information) + this._doesImageExist.convertJoin(image, ctx, errors, warnings, information); } } } else if (ignore) { - warnings.push(`${ctx}: unused '${ignoreToken}' - please remove this`) + warnings.push(`${ctx}: unused '${ignoreToken}' - please remove this`); } } @@ -654,17 +655,72 @@ export class DetectMappingsWithImages extends DesugaringStep> { + constructor() { + super("Given a possible set of translations, validates that does have `rel='noopener'` set", [], "ValidatePossibleLinks"); + } + + public isTabnabbingProne(str: string): boolean { + const p = parse_html(str); + const links = Array.from(p.getElementsByTagName("a")); + if (links.length == 0) { + return false; } + for (const link of Array.from(links)) { + if (link.getAttribute("target") !== "_blank") { + continue; + } + const rel = new Set(link.getAttribute("rel")?.split(" ") ?? []); + if (rel.has("noopener")) { + continue; + } + const source = link.getAttribute("href"); + if (source.startsWith("http")) { + // No variable part - we assume the link is safe + continue; + } + return true; + } + return false; + } + + convert(json: string | Record, context: string): { + result: string | Record; + errors?: string[]; + warnings?: string[]; + information?: string[] + } { + + const errors = []; + if (typeof json === "string") { + if (this.isTabnabbingProne(json)) { + errors.push("At " + context + ": the string " + json + " has a link targeting `_blank`, but it doesn't have `rel='noopener'` set. This gives rise to reverse tabnapping"); + } + } else { + for (const k in json) { + if (this.isTabnabbingProne(json[k])) { + errors.push(`At ${context}: the translation for ${k} '${json[k]}' has a link targeting \`_blank\`, but it doesn't have \`rel='noopener'\` set. This gives rise to reverse tabnapping`); + } + } + } + return { + errors, + result: json + }; } } class MiscTagRenderingChecks extends DesugaringStep { - private _options: { noQuestionHintCheck: boolean } + private _options: { noQuestionHintCheck: boolean }; constructor(options: { noQuestionHintCheck: boolean }) { - super("Miscellaneous checks on the tagrendering", ["special"], "MiscTagRenderingChecks") - this._options = options + super("Miscellaneous checks on the tagrendering", ["special"], "MiscTagRenderingChecks"); + this._options = options; } convert( @@ -676,25 +732,26 @@ class MiscTagRenderingChecks extends DesugaringStep { warnings?: string[] information?: string[] } { - const warnings = [] - const errors = [] + const warnings = []; + const errors = []; if (json["special"] !== undefined) { errors.push( "At " + - context + - ': detected `special` on the top level. Did you mean `{"render":{ "special": ... }}`' - ) + context + + ": detected `special` on the top level. Did you mean `{\"render\":{ \"special\": ... }}`" + ); } if (json["group"]) { errors.push( "At " + - context + - ': groups are deprecated, use `"label": ["' + - json["group"] + - '"]` instead' - ) + context + + ": groups are deprecated, use `\"label\": [\"" + + json["group"] + + "\"]` instead" + ); } - const freeformType = json["freeform"]?.["type"] + + const freeformType = json["freeform"]?.["type"]; if (freeformType) { if (Validators.availableTypes.indexOf(freeformType) < 0) { throw ( @@ -704,14 +761,14 @@ class MiscTagRenderingChecks extends DesugaringStep { freeformType + "; try one of " + Validators.availableTypes.join(", ") - ) + ); } } return { result: json, errors, - warnings, - } + warnings + }; } } @@ -726,8 +783,16 @@ export class ValidateTagRenderings extends Fuse { new DetectShadowedMappings(layerConfig), new DetectConflictingAddExtraTags(), new DetectMappingsWithImages(doesImageExist), + new On("render", + new ValidatePossibleLinks()), + new On("question", + new ValidatePossibleLinks()), + new On("questionHint", + new ValidatePossibleLinks()), + new On("mappings", + new Each(new On("then", new ValidatePossibleLinks()))), new MiscTagRenderingChecks(options) - ) + ); } } @@ -736,41 +801,41 @@ export class ValidateLayer extends DesugaringStep { * The paths where this layer is originally saved. Triggers some extra checks * @private */ - private readonly _path?: string - private readonly _isBuiltin: boolean - private readonly _doesImageExist: DoesImageExist + private readonly _path?: string; + private readonly _isBuiltin: boolean; + private readonly _doesImageExist: DoesImageExist; constructor(path: string, isBuiltin: boolean, doesImageExist: DoesImageExist) { - super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer") - this._path = path - this._isBuiltin = isBuiltin - this._doesImageExist = doesImageExist + super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer"); + this._path = path; + this._isBuiltin = isBuiltin; + this._doesImageExist = doesImageExist; } convert( json: LayerConfigJson, context: string ): { result: LayerConfigJson; errors: string[]; warnings?: string[]; information?: string[] } { - const errors = [] - const warnings = [] - const information = [] - context = "While validating a layer: " + context + const errors = []; + const warnings = []; + const information = []; + context = "While validating a layer: " + context; if (typeof json === "string") { - errors.push(context + ": This layer hasn't been expanded: " + json) + errors.push(context + ": This layer hasn't been expanded: " + json); return { result: null, - errors, - } + errors + }; } if (json.source === "special") { if (!Constants.priviliged_layers.find((x) => x == json.id)) { errors.push( context + - ": layer " + - json.id + - " uses 'special' as source.osmTags. However, this layer is not a priviliged layer" - ) + ": layer " + + json.id + + " uses 'special' as source.osmTags. However, this layer is not a priviliged layer" + ); } } @@ -778,49 +843,49 @@ export class ValidateLayer extends DesugaringStep { if (json.title === undefined && json.source !== "special:library") { errors.push( context + - ": this layer does not have a title defined but it does have tagRenderings. Not having a title will disable the popups, resulting in an unclickable element. Please add a title. If not having a popup is intended and the tagrenderings need to be kept (e.g. in a library layer), set `title: null` to disable this error." - ) + ": this layer does not have a title defined but it does have tagRenderings. Not having a title will disable the popups, resulting in an unclickable element. Please add a title. If not having a popup is intended and the tagrenderings need to be kept (e.g. in a library layer), set `title: null` to disable this error." + ); } if (json.title === null) { information.push( context + - ": title is `null`. This results in an element that cannot be clicked - even though tagRenderings is set." - ) + ": title is `null`. This results in an element that cannot be clicked - even though tagRenderings is set." + ); } } if (json["builtin"] !== undefined) { - errors.push(context + ": This layer hasn't been expanded: " + json) + errors.push(context + ": This layer hasn't been expanded: " + json); return { result: null, - errors, - } + errors + }; } if (json.minzoom > Constants.minZoomLevelToAddNewPoint) { ;(json.presets?.length > 0 ? errors : warnings).push( `At ${context}: minzoom is ${json.minzoom}, this should be at most ${Constants.minZoomLevelToAddNewPoint} as a preset is set. Why? Selecting the pin for a new item will zoom in to level before adding the point. Having a greater minzoom will hide the points, resulting in possible duplicates` - ) + ); } { // duplicate ids in tagrenderings check const duplicates = Utils.Dedup( Utils.Dupiclates(Utils.NoNull((json.tagRenderings ?? []).map((tr) => tr["id"]))) - ) + ); if (duplicates.length > 0) { - console.log(json.tagRenderings) + console.log(json.tagRenderings); errors.push( "At " + - context + - ": some tagrenderings have a duplicate id: " + - duplicates.join(", ") - ) + context + + ": some tagrenderings have a duplicate id: " + + duplicates.join(", ") + ); } } if (json.deletion !== undefined && json.deletion instanceof DeleteConfig) { if (json.deletion.softDeletionTags === undefined) { - warnings.push("No soft-deletion tags in deletion block for layer " + json.id) + warnings.push("No soft-deletion tags in deletion block for layer " + json.id); } } @@ -831,9 +896,9 @@ export class ValidateLayer extends DesugaringStep { if (json["overpassTags"] !== undefined) { errors.push( "Layer " + - json.id + - 'still uses the old \'overpassTags\'-format. Please use "source": {"osmTags": }\' instead of "overpassTags": (note: this isn\'t your fault, the custom theme generator still spits out the old format)' - ) + json.id + + "still uses the old 'overpassTags'-format. Please use \"source\": {\"osmTags\": }' instead of \"overpassTags\": (note: this isn't your fault, the custom theme generator still spits out the old format)" + ); } const forbiddenTopLevel = [ "icon", @@ -844,88 +909,88 @@ export class ValidateLayer extends DesugaringStep { "width", "color", "colour", - "iconOverlays", - ] + "iconOverlays" + ]; for (const forbiddenKey of forbiddenTopLevel) { if (json[forbiddenKey] !== undefined) errors.push( context + - ": layer " + - json.id + - " still has a forbidden key " + - forbiddenKey - ) + ": layer " + + json.id + + " still has a forbidden key " + + forbiddenKey + ); } if (json["hideUnderlayingFeaturesMinPercentage"] !== undefined) { errors.push( context + - ": layer " + - json.id + - " contains an old 'hideUnderlayingFeaturesMinPercentage'" - ) + ": layer " + + json.id + + " contains an old 'hideUnderlayingFeaturesMinPercentage'" + ); } if ( json.isShown !== undefined && (json.isShown["render"] !== undefined || json.isShown["mappings"] !== undefined) ) { - warnings.push(context + " has a tagRendering as `isShown`") + warnings.push(context + " has a tagRendering as `isShown`"); } } if (this._isBuiltin) { // Check location of layer file - const expected: string = `assets/layers/${json.id}/${json.id}.json` + const expected: string = `assets/layers/${json.id}/${json.id}.json`; if (this._path != undefined && this._path.indexOf(expected) < 0) { errors.push( "Layer is in an incorrect place. The path is " + - this._path + - ", but expected " + - expected - ) + this._path + + ", but expected " + + expected + ); } } if (this._isBuiltin) { // Check for correct IDs if (json.tagRenderings?.some((tr) => tr["id"] === "")) { - const emptyIndexes: number[] = [] + const emptyIndexes: number[] = []; for (let i = 0; i < json.tagRenderings.length; i++) { - const tagRendering = json.tagRenderings[i] + const tagRendering = json.tagRenderings[i]; if (tagRendering["id"] === "") { - emptyIndexes.push(i) + emptyIndexes.push(i); } } errors.push( `Some tagrendering-ids are empty or have an emtpy string; this is not allowed (at ${context}.tagRenderings.[${emptyIndexes.join( "," )}])` - ) + ); } const duplicateIds = Utils.Dupiclates( (json.tagRenderings ?? []) ?.map((f) => f["id"]) .filter((id) => id !== "questions") - ) + ); if (duplicateIds.length > 0 && !Utils.runningFromConsole) { errors.push( `Some tagRenderings have a duplicate id: ${duplicateIds} (at ${context}.tagRenderings)` - ) + ); } if (json.description === undefined) { if (typeof json.source === null) { - errors.push(context + ": A priviliged layer must have a description") + errors.push(context + ": A priviliged layer must have a description"); } else { - warnings.push(context + ": A builtin layer should have a description") + warnings.push(context + ": A builtin layer should have a description"); } } } if (json.filter) { - const r = new On("filter", new Each(new ValidateFilter())).convert(json, context) - warnings.push(...(r.warnings ?? [])) - errors.push(...(r.errors ?? [])) - information.push(...(r.information ?? [])) + const r = new On("filter", new Each(new ValidateFilter())).convert(json, context); + warnings.push(...(r.warnings ?? [])); + errors.push(...(r.errors ?? [])); + information.push(...(r.information ?? [])); } if (json.tagRenderings !== undefined) { @@ -933,74 +998,74 @@ export class ValidateLayer extends DesugaringStep { "tagRenderings", new Each( new ValidateTagRenderings(json, this._doesImageExist, { - noQuestionHintCheck: json["#"]?.indexOf("no-question-hint-check") >= 0, + noQuestionHintCheck: json["#"]?.indexOf("no-question-hint-check") >= 0 }) ) - ).convert(json, context) - warnings.push(...(r.warnings ?? [])) - errors.push(...(r.errors ?? [])) - information.push(...(r.information ?? [])) + ).convert(json, context); + warnings.push(...(r.warnings ?? [])); + errors.push(...(r.errors ?? [])); + information.push(...(r.information ?? [])); } { const hasCondition = json.mapRendering?.filter( (mr) => mr["icon"] !== undefined && mr["icon"]["condition"] !== undefined - ) + ); if (hasCondition?.length > 0) { errors.push( "At " + - context + - ":\n One or more icons in the mapRenderings have a condition set. Don't do this, as this will result in an invisible but clickable element. Use extra filters in the source instead. The offending mapRenderings are:\n" + - JSON.stringify(hasCondition, null, " ") - ) + context + + ":\n One or more icons in the mapRenderings have a condition set. Don't do this, as this will result in an invisible but clickable element. Use extra filters in the source instead. The offending mapRenderings are:\n" + + JSON.stringify(hasCondition, null, " ") + ); } } if (json.presets !== undefined) { if (typeof json.source === "string") { - throw "A special layer cannot have presets" + throw "A special layer cannot have presets"; } // Check that a preset will be picked up by the layer itself - const baseTags = TagUtils.Tag(json.source["osmTags"]) + const baseTags = TagUtils.Tag(json.source["osmTags"]); for (let i = 0; i < json.presets.length; i++) { - const preset = json.presets[i] + const preset = json.presets[i]; const tags: { k: string; v: string }[] = new And( preset.tags.map((t) => TagUtils.Tag(t)) - ).asChange({ id: "node/-1" }) - const properties = {} + ).asChange({ id: "node/-1" }); + const properties = {}; for (const tag of tags) { - properties[tag.k] = tag.v + properties[tag.k] = tag.v; } - const doMatch = baseTags.matchesProperties(properties) + const doMatch = baseTags.matchesProperties(properties); if (!doMatch) { errors.push( context + - ".presets[" + - i + - "]: This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " + - JSON.stringify(properties) + - "\n The required tags are: " + - baseTags.asHumanString(false, false, {}) - ) + ".presets[" + + i + + "]: This preset does not match the required tags of this layer. This implies that a newly added point will not show up.\n A newly created point will have properties: " + + JSON.stringify(properties) + + "\n The required tags are: " + + baseTags.asHumanString(false, false, {}) + ); } } } } catch (e) { - errors.push(e) + errors.push(e); } return { result: json, errors, warnings, - information, - } + information + }; } } export class ValidateFilter extends DesugaringStep { constructor() { - super("Detect common errors in the filters", [], "ValidateFilter") + super("Detect common errors in the filters", [], "ValidateFilter"); } convert( @@ -1014,22 +1079,22 @@ export class ValidateFilter extends DesugaringStep { } { if (typeof filter === "string") { // Calling another filter, we skip - return { result: filter } + return { result: filter }; } - const errors = [] + const errors = []; for (const option of filter.options) { for (let i = 0; i < option.fields?.length ?? 0; i++) { - const field = option.fields[i] - const type = field.type ?? "string" + const field = option.fields[i]; + const type = field.type ?? "string"; if (Validators.availableTypes.find((t) => t === type) === undefined) { const err = `Invalid filter: ${type} is not a valid textfield type (at ${context}.fields[${i}])\n\tTry one of ${Array.from( Validators.availableTypes - ).join(",")}` - errors.push(err) + ).join(",")}`; + errors.push(err); } } } - return { result: filter, errors } + return { result: filter, errors }; } } @@ -1042,7 +1107,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{ "Tries to detect layers where a shared filter can be used (or where similar filters occur)", [], "DetectDuplicateFilters" - ) + ); } convert( @@ -1054,11 +1119,11 @@ export class DetectDuplicateFilters extends DesugaringStep<{ warnings?: string[] information?: string[] } { - const errors: string[] = [] - const warnings: string[] = [] - const information: string[] = [] + const errors: string[] = []; + const warnings: string[] = []; + const information: string[] = []; - const { layers, themes } = json + const { layers, themes } = json; const perOsmTag = new Map< string, { @@ -1066,24 +1131,24 @@ export class DetectDuplicateFilters extends DesugaringStep<{ layout: LayoutConfigJson | undefined filter: FilterConfigJson }[] - >() + >(); for (const layer of layers) { - this.addLayerFilters(layer, perOsmTag) + this.addLayerFilters(layer, perOsmTag); } for (const theme of themes) { if (theme.id === "personal") { - continue + continue; } for (const layer of theme.layers) { if (typeof layer === "string") { - continue + continue; } if (layer["builtin"] !== undefined) { - continue + continue; } - this.addLayerFilters(layer, perOsmTag, theme) + this.addLayerFilters(layer, perOsmTag, theme); } } @@ -1091,25 +1156,25 @@ export class DetectDuplicateFilters extends DesugaringStep<{ perOsmTag.forEach((value, key) => { if (value.length <= 1) { // Seen this key just once, it is unique - return + return; } - let msg = "Possible duplicate filter: " + key + let msg = "Possible duplicate filter: " + key; for (const { filter, layer, layout } of value) { - let id = "" + let id = ""; if (layout !== undefined) { - id = layout.id + ":" + id = layout.id + ":"; } - msg += `\n - ${id}${layer.id}.${filter.id}` + msg += `\n - ${id}${layer.id}.${filter.id}`; } - warnings.push(msg) - }) + warnings.push(msg); + }); return { result: json, errors, warnings, - information, - } + information + }; } /** @@ -1128,33 +1193,33 @@ export class DetectDuplicateFilters extends DesugaringStep<{ layout?: LayoutConfigJson | undefined ): void { if (layer.filter === undefined || layer.filter === null) { - return + return; } if (layer.filter["sameAs"] !== undefined) { - return + return; } for (const filter of <(string | FilterConfigJson)[]>layer.filter) { if (typeof filter === "string") { - continue + continue; } if (filter["#"]?.indexOf("ignore-possible-duplicate") >= 0) { - continue + continue; } for (const option of filter.options) { if (option.osmTags === undefined) { - continue + continue; } - const key = JSON.stringify(option.osmTags) + const key = JSON.stringify(option.osmTags); if (!perOsmTag.has(key)) { - perOsmTag.set(key, []) + perOsmTag.set(key, []); } perOsmTag.get(key).push({ layer, filter, - layout, - }) + layout + }); } } } diff --git a/src/Models/ThemeConfig/TagRenderingConfig.ts b/src/Models/ThemeConfig/TagRenderingConfig.ts index 5fe5c7ca9..2039022e8 100644 --- a/src/Models/ThemeConfig/TagRenderingConfig.ts +++ b/src/Models/ThemeConfig/TagRenderingConfig.ts @@ -243,7 +243,7 @@ export default class TagRenderingConfig { if (txt === "") { throw context + " Rendering for language " + ln + " is empty" } - if (txt.indexOf("{" + this.freeform.key + "}") >= 0) { + if (txt.indexOf("{" + this.freeform.key + "}") >= 0 || txt.indexOf("&LBRACE" + this.freeform.key + "&RBRACE") ) { continue } if (txt.indexOf("{" + this.freeform.key + ":") >= 0) { diff --git a/src/UI/Base/SubtleLink.svelte b/src/UI/Base/SubtleLink.svelte index 401c34a24..5a3d9f505 100644 --- a/src/UI/Base/SubtleLink.svelte +++ b/src/UI/Base/SubtleLink.svelte @@ -34,6 +34,7 @@ class={twMerge(options.extraClasses, "button text-ellipsis")} {href} target={newTab ? "_blank" : undefined} + rel={newTab ? "noopener" : undefined} > {#if imageUrl !== undefined} diff --git a/src/UI/Base/Table.ts b/src/UI/Base/Table.ts index e27dbff89..c400b9129 100644 --- a/src/UI/Base/Table.ts +++ b/src/UI/Base/Table.ts @@ -29,7 +29,7 @@ export default class Table extends BaseUIElement { const header = Utils.NoNull(headerMarkdownParts).join(" | ") const headerSep = headerMarkdownParts.map((part) => "-".repeat(part.length + 2)).join(" | ") const table = this._contents - .map((row) => row.map((el) => el?.AsMarkdown()?.replace("|", "\\|") ?? " ").join(" | ")) + .map((row) => row.map((el) => el?.AsMarkdown()?.replaceAll("\\","\\\\")?.replaceAll("|", "\\|") ?? " ").join(" | ")) .join("\n") return "\n\n" + [header, headerSep, table, ""].join("\n") diff --git a/src/UI/BigComponents/ContactLink.svelte b/src/UI/BigComponents/ContactLink.svelte index f3ccac9e2..7cebd2c0d 100644 --- a/src/UI/BigComponents/ContactLink.svelte +++ b/src/UI/BigComponents/ContactLink.svelte @@ -35,7 +35,7 @@ src={`https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/community_index/${resource.type}.svg`} />
- + {resource.resolved.name ?? resource.resolved.url} {resource.resolved?.description} diff --git a/src/UI/BigComponents/CopyrightPanel.ts b/src/UI/BigComponents/CopyrightPanel.ts index 988a802ca..d066a4d00 100644 --- a/src/UI/BigComponents/CopyrightPanel.ts +++ b/src/UI/BigComponents/CopyrightPanel.ts @@ -102,7 +102,7 @@ export default class CopyrightPanel extends Combine { let bgAttr: BaseUIElement | string = undefined if (attrText && attrUrl) { bgAttr = - "" + attrText + "" + "" + attrText + "" } else if (attrUrl) { bgAttr = attrUrl } else { diff --git a/src/UI/BigComponents/OpenJosm.ts b/src/UI/BigComponents/OpenJosm.ts index 352082a7c..8f86f6d98 100644 --- a/src/UI/BigComponents/OpenJosm.ts +++ b/src/UI/BigComponents/OpenJosm.ts @@ -16,7 +16,7 @@ export class OpenJosm extends Combine { const josmState = new UIEventSource(undefined) // Reset after 15s - josmState.stabilized(15000).addCallbackD((_) => josmState.setData(undefined)) + josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined)) const stateIndication = new VariableUiElement( josmState.map((state) => { @@ -45,7 +45,7 @@ export class OpenJosm extends Combine { const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}` Utils.download(josmLink) .then((answer) => josmState.setData(answer.replace(/\n/g, "").trim())) - .catch((_) => josmState.setData("ERROR")) + .catch(() => josmState.setData("ERROR")) }) .SetClass("w-full"), undefined, diff --git a/src/UI/BigComponents/UserProfile.svelte b/src/UI/BigComponents/UserProfile.svelte index 5ade85a15..5cb514a4d 100644 --- a/src/UI/BigComponents/UserProfile.svelte +++ b/src/UI/BigComponents/UserProfile.svelte @@ -37,6 +37,7 @@ diff --git a/src/UI/DownloadFlow/DownloadPanel.svelte b/src/UI/DownloadFlow/DownloadPanel.svelte index c9b912958..220f94c3d 100644 --- a/src/UI/DownloadFlow/DownloadPanel.svelte +++ b/src/UI/DownloadFlow/DownloadPanel.svelte @@ -81,7 +81,7 @@ mimetype="image/png" mainText={t.downloadAsPng} helperText={t.downloadAsPngHelper} - construct={(_) => state.mapProperties.exportAsPng(4)} + construct={() => state.mapProperties.exportAsPng(4)} />
diff --git a/src/UI/Image/ImageUploadFlow.ts b/src/UI/Image/ImageUploadFlow.ts index 250df538d..f5ce9772d 100644 --- a/src/UI/Image/ImageUploadFlow.ts +++ b/src/UI/Image/ImageUploadFlow.ts @@ -73,7 +73,7 @@ export class ImageUploadFlow extends Toggle { ]).SetClass("w-full flex justify-center items-center") const licenseStore = state?.osmConnection?.GetPreference( - Constants.OsmPreferenceKeyPicturesLicense, + "pictures-license", "CC0" ) diff --git a/src/UI/Map/MapLibreAdaptor.ts b/src/UI/Map/MapLibreAdaptor.ts index 6193ee7ca..75f2d54d4 100644 --- a/src/UI/Map/MapLibreAdaptor.ts +++ b/src/UI/Map/MapLibreAdaptor.ts @@ -172,7 +172,8 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { tileSize: layer["tile-size"] ?? 256, minzoom: layer["min_zoom"] ?? 1, maxzoom: layer["max_zoom"] ?? 25, - // scheme: background["type"] === "tms" ? "tms" : "xyz", + // Bit of a hack, but seems to work + scheme: layer.url.includes("{-y}") ? "tms" : "xyz", } } @@ -203,6 +204,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { "{width}": "" + size, "{height}": "" + size, "{zoom}": "{z}", + "{-y}": "{y}", } for (const key in toReplace) { diff --git a/src/UI/Popup/LinkableImage.svelte b/src/UI/Popup/LinkableImage.svelte new file mode 100644 index 000000000..798bebb09 --- /dev/null +++ b/src/UI/Popup/LinkableImage.svelte @@ -0,0 +1,73 @@ + +
+ + {#if linkable} + + {/if} +
diff --git a/src/UI/Popup/NearbyImages.svelte b/src/UI/Popup/NearbyImages.svelte new file mode 100644 index 000000000..30c886914 --- /dev/null +++ b/src/UI/Popup/NearbyImages.svelte @@ -0,0 +1,54 @@ + + +
+
+ +

+ +

+ +
+ {#if $images.length === 0} + + {:else} +
+ {#each $images as image (image.pictureUrl)} + + + + {/each} +
+ {/if} +
diff --git a/src/UI/Popup/NearbyImages.ts b/src/UI/Popup/NearbyImages.ts deleted file mode 100644 index 6ddc1ab6f..000000000 --- a/src/UI/Popup/NearbyImages.ts +++ /dev/null @@ -1,316 +0,0 @@ -import Combine from "../Base/Combine" -import { Store, Stores, UIEventSource } from "../../Logic/UIEventSource" -import { SlideShow } from "../Image/SlideShow" -import { ClickableToggle } from "../Input/Toggle" -import Loading from "../Base/Loading" -import { AttributedImage } from "../Image/AttributedImage" -import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders" -import Svg from "../../Svg" -import BaseUIElement from "../BaseUIElement" -import { InputElement } from "../Input/InputElement" -import { VariableUiElement } from "../Base/VariableUIElement" -import Translations from "../i18n/Translations" -import { Mapillary } from "../../Logic/ImageProviders/Mapillary" -import { SubtleButton } from "../Base/SubtleButton" -import { GeoOperations } from "../../Logic/GeoOperations" -import Lazy from "../Base/Lazy" -import P4C from "pic4carto" -import { IndexedFeatureSource } from "../../Logic/FeatureSource/FeatureSource" - -export interface P4CPicture { - pictureUrl: string - date?: number - coordinates: { lat: number; lng: number } - provider: "Mapillary" | string - author? - license? - detailsUrl?: string - direction? - osmTags?: object /*To copy straight into OSM!*/ - thumbUrl: string - details: { - isSpherical: boolean - } -} - -export interface NearbyImageOptions { - lon: number - lat: number - // Radius of the upstream search - searchRadius?: 500 | number - maxDaysOld?: 1095 | number - blacklist: Store<{ url: string }[]> - shownImagesCount?: UIEventSource - towardscenter?: UIEventSource - allowSpherical?: UIEventSource - // Radius of what is shown. Useless to select a value > searchRadius; defaults to searchRadius - shownRadius?: UIEventSource -} - -class ImagesInLoadedDataFetcher { - private indexedFeatures: IndexedFeatureSource - - constructor(indexedFeatures: IndexedFeatureSource) { - this.indexedFeatures = indexedFeatures - } - - public fetchAround(loc: { lon: number; lat: number; searchRadius?: number }): P4CPicture[] { - const foundImages: P4CPicture[] = [] - this.indexedFeatures.features.data.forEach((feature) => { - const props = feature.properties - const images = [] - if (props.image) { - images.push(props.image) - } - for (let i = 0; i < 10; i++) { - if (props["image:" + i]) { - images.push(props["image:" + i]) - } - } - if (images.length == 0) { - return - } - const centerpoint = GeoOperations.centerpointCoordinates(feature) - const d = GeoOperations.distanceBetween(centerpoint, [loc.lon, loc.lat]) - if (loc.searchRadius !== undefined && d > loc.searchRadius) { - return - } - for (const image of images) { - foundImages.push({ - pictureUrl: image, - thumbUrl: image, - coordinates: { lng: centerpoint[0], lat: centerpoint[1] }, - provider: "OpenStreetMap", - details: { - isSpherical: false, - }, - }) - } - }) - const cleaned: P4CPicture[] = [] - const seen = new Set() - for (const foundImage of foundImages) { - if (seen.has(foundImage.pictureUrl)) { - continue - } - seen.add(foundImage.pictureUrl) - cleaned.push(foundImage) - } - return cleaned - } -} - -export default class NearbyImages extends Lazy { - constructor(options: NearbyImageOptions, state?: IndexedFeatureSource) { - super(() => { - const t = Translations.t.image.nearbyPictures - const shownImages = options.shownImagesCount ?? new UIEventSource(25) - - const loadedPictures = NearbyImages.buildPictureFetcher(options, state) - - const loadMoreButton = new Combine([ - new SubtleButton(Svg.add_svg(), t.loadMore).onClick(() => { - shownImages.setData(shownImages.data + 25) - }), - ]).SetClass("flex flex-col justify-center") - - const imageElements = loadedPictures.map( - (imgs) => { - if (imgs === undefined) { - return [] - } - const elements = (imgs.images ?? []) - .slice(0, shownImages.data) - .map((i) => this.prepareElement(i)) - if (imgs.images !== undefined && elements.length < imgs.images.length) { - // We effectively sliced some items, so we can increase the count - elements.push(loadMoreButton) - } - return elements - }, - [shownImages] - ) - - return new VariableUiElement( - loadedPictures.map((loaded) => { - if (loaded?.images === undefined) { - return NearbyImages.NoImagesView(new Loading(t.loading)).SetClass( - "animate-pulse" - ) - } - const images = loaded.images - const beforeFilter = loaded?.beforeFilter - if (beforeFilter === 0) { - return NearbyImages.NoImagesView(t.nothingFound.SetClass("alert block")) - } else if (images.length === 0) { - const removeFiltersButton = new SubtleButton( - Svg.filter_disable_svg(), - t.removeFilters - ).onClick(() => { - options.shownRadius.setData(options.searchRadius) - options.allowSpherical.setData(true) - options.towardscenter.setData(false) - }) - - return NearbyImages.NoImagesView( - t.allFiltered.SetClass("font-bold"), - removeFiltersButton - ) - } - - return new SlideShow(imageElements) - }) - ) - }) - } - - private static NoImagesView(...elems: BaseUIElement[]) { - return new Combine(elems) - .SetClass("flex flex-col justify-center items-center bg-gray-200 mb-2 rounded-lg") - .SetStyle( - "height: calc( var(--image-carousel-height) - 0.5rem ) ; max-height: calc( var(--image-carousel-height) - 0.5rem );" - ) - } - - private static buildPictureFetcher(options: NearbyImageOptions, state?: IndexedFeatureSource) { - const picManager = new P4C.PicturesManager({}) - const searchRadius = options.searchRadius ?? 500 - - const nearbyImages = - state !== undefined ? new ImagesInLoadedDataFetcher(state).fetchAround(options) : [] - - return Stores.FromPromise( - picManager.startPicsRetrievalAround( - new P4C.LatLng(options.lat, options.lon), - options.searchRadius ?? 500, - { - mindate: - new Date().getTime() - - (options.maxDaysOld ?? 3 * 365) * 24 * 60 * 60 * 1000, - towardscenter: false, - } - ) - ).map( - (images) => { - if (images === undefined) { - return undefined - } - images = (images ?? []).concat(nearbyImages) - const blacklisted = options.blacklist?.data - images = images?.filter( - (i) => - !blacklisted?.some((notAllowed) => - Mapillary.sameUrl(i.pictureUrl, notAllowed.url) - ) - ) - - const beforeFilterCount = images.length - - if (!options?.allowSpherical?.data) { - images = images?.filter((i) => i.details.isSpherical !== true) - } - - const shownRadius = options?.shownRadius?.data ?? searchRadius - if (shownRadius !== searchRadius) { - images = images.filter((i) => { - const d = GeoOperations.distanceBetween( - [i.coordinates.lng, i.coordinates.lat], - [options.lon, options.lat] - ) - return d <= shownRadius - }) - } - if (options.towardscenter?.data) { - images = images.filter((i) => { - if (i.direction === undefined || isNaN(i.direction)) { - return false - } - const bearing = GeoOperations.bearing( - [i.coordinates.lng, i.coordinates.lat], - [options.lon, options.lat] - ) - const diff = Math.abs((i.direction - bearing) % 360) - return diff < 40 - }) - } - - images?.sort((a, b) => { - const distanceA = GeoOperations.distanceBetween( - [a.coordinates.lng, a.coordinates.lat], - [options.lon, options.lat] - ) - const distanceB = GeoOperations.distanceBetween( - [b.coordinates.lng, b.coordinates.lat], - [options.lon, options.lat] - ) - return distanceA - distanceB - }) - - return { images, beforeFilter: beforeFilterCount } - }, - [options.blacklist, options.allowSpherical, options.towardscenter, options.shownRadius] - ) - } - - protected prepareElement(info: P4CPicture): BaseUIElement { - const provider = AllImageProviders.byName(info.provider) - return new AttributedImage({ url: info.pictureUrl, provider }) - } - - private static asAttributedImage(info: P4CPicture): AttributedImage { - const provider = AllImageProviders.byName(info.provider) - return new AttributedImage({ url: info.thumbUrl, provider, date: new Date(info.date) }) - } - - protected asToggle(info: P4CPicture): ClickableToggle { - const imgNonSelected = NearbyImages.asAttributedImage(info) - const imageSelected = NearbyImages.asAttributedImage(info) - - const nonSelected = new Combine([imgNonSelected]).SetClass("relative block") - const hoveringCheckmark = new Combine([ - Svg.confirm_svg().SetClass("block w-24 h-24 -ml-12 -mt-12"), - ]).SetClass("absolute left-1/2 top-1/2 w-0") - const selected = new Combine([imageSelected, hoveringCheckmark]).SetClass("relative block") - - return new ClickableToggle(selected, nonSelected).SetClass("").ToggleOnClick() - } -} - -export class SelectOneNearbyImage extends NearbyImages implements InputElement { - private readonly value: UIEventSource - - constructor( - options: NearbyImageOptions & { value?: UIEventSource }, - state?: IndexedFeatureSource - ) { - super(options, state) - this.value = options.value ?? new UIEventSource(undefined) - } - - GetValue(): UIEventSource { - return this.value - } - - IsValid(t: P4CPicture): boolean { - return false - } - - protected prepareElement(info: P4CPicture): BaseUIElement { - const toggle = super.asToggle(info) - toggle.isEnabled.addCallback((enabled) => { - if (enabled) { - this.value.setData(info) - } else if (this.value.data === info) { - this.value.setData(undefined) - } - }) - - this.value.addCallback((inf) => { - if (inf !== info) { - toggle.isEnabled.setData(false) - } - }) - - return toggle - } -} diff --git a/src/UI/Popup/NearbyImagesCollapsed.svelte b/src/UI/Popup/NearbyImagesCollapsed.svelte new file mode 100644 index 000000000..e1679bff9 --- /dev/null +++ b/src/UI/Popup/NearbyImagesCollapsed.svelte @@ -0,0 +1,36 @@ + + +{#if expanded} + + {expanded = false}}/> + +{:else} + +{/if} diff --git a/src/UI/Popup/SendEmail.svelte b/src/UI/Popup/SendEmail.svelte new file mode 100644 index 000000000..32a04f5f1 --- /dev/null +++ b/src/UI/Popup/SendEmail.svelte @@ -0,0 +1,22 @@ + +
+ + {button_text} + diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index 66e700e4c..213451e97 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -58,18 +58,6 @@ import LanguagePicker from "./LanguagePicker" import Link from "./Base/Link" import LayerConfig from "../Models/ThemeConfig/LayerConfig" import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig" -import NearbyImages, { - NearbyImageOptions, - P4CPicture, - SelectOneNearbyImage, -} from "./Popup/NearbyImages" -import { Tag } from "../Logic/Tags/Tag" -import ChangeTagAction from "../Logic/Osm/Actions/ChangeTagAction" -import { And } from "../Logic/Tags/And" -import { SaveButton } from "./Popup/SaveButton" -import Lazy from "./Base/Lazy" -import { CheckBox } from "./Input/Checkboxes" -import Slider from "./Input/Slider" import { OsmTags, WayId } from "../Models/OsmFeature" import MoveWizard from "./Popup/MoveWizard" import SplitRoadWizard from "./Popup/SplitRoadWizard" @@ -83,19 +71,17 @@ import DeleteWizard from "./Popup/DeleteFlow/DeleteWizard.svelte" import { OpenJosm } from "./BigComponents/OpenJosm" import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte" import FediverseValidator from "./InputElement/Validators/FediverseValidator" +import SendEmail from "./Popup/SendEmail.svelte" +import NearbyImages from "./Popup/NearbyImages.svelte" +import NearbyImagesCollapsed from "./Popup/NearbyImagesCollapsed.svelte" class NearbyImageVis implements SpecialVisualization { // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests args: { name: string; defaultValue?: string; doc: string; required?: boolean }[] = [ { name: "mode", - defaultValue: "expandable", - doc: "Indicates how this component is initialized. Options are: \n\n- `open`: always show and load the pictures\n- `collapsable`: show the pictures, but a user can collapse them\n- `expandable`: shown by default; but a user can collapse them.", - }, - { - name: "mapillary", - defaultValue: "true", - doc: "If 'true', includes a link to mapillary on this location.", + defaultValue: "closed", + doc: "Either `open` or `closed`. If `open`, then the image carousel will always be shown", }, ] docs = @@ -104,110 +90,21 @@ class NearbyImageVis implements SpecialVisualization { constr( state: SpecialVisualizationState, - tagSource: UIEventSource>, + tags: UIEventSource>, args: string[], feature: Feature, layer: LayerConfig ): BaseUIElement { - const t = Translations.t.image.nearbyPictures - const mode: "open" | "expandable" | "collapsable" = args[0] + const isOpen = args[0] === "open" const [lon, lat] = GeoOperations.centerpointCoordinates(feature) - const id: string = tagSource.data["id"] - const canBeEdited: boolean = !!id?.match("(node|way|relation)/-?[0-9]+") - const selectedImage = new UIEventSource(undefined) - - let saveButton: BaseUIElement = undefined - if (canBeEdited) { - const confirmText: BaseUIElement = new SubstitutedTranslation( - t.confirm, - tagSource, - state - ) - - const onSave = async () => { - console.log("Selected a picture...", selectedImage.data) - const osmTags = selectedImage.data.osmTags - const tags: Tag[] = [] - for (const key in osmTags) { - tags.push(new Tag(key, osmTags[key])) - } - await state?.changes?.applyAction( - new ChangeTagAction(id, new And(tags), tagSource.data, { - theme: state?.layout.id, - changeType: "link-image", - }) - ) - } - saveButton = new SaveButton(selectedImage, state, confirmText, t.noImageSelected) - .onClick(onSave) - .SetClass("flex justify-end") - } - - const nearby = new Lazy(() => { - const towardsCenter = new CheckBox(t.onlyTowards, false) - - const maxSearchRadius = 100 - const stepSize = 10 - const defaultValue = Math.floor(maxSearchRadius / (2 * stepSize)) * stepSize - const fromOsmPreferences = state?.osmConnection - ?.GetPreference("nearby-images-radius", "" + defaultValue) - .sync( - (s) => Number(s), - [], - (i) => "" + i - ) - const radiusValue = new UIEventSource(fromOsmPreferences.data) - radiusValue.addCallbackAndRunD((v) => fromOsmPreferences.setData(v)) - - const radius = new Slider(stepSize, maxSearchRadius, { - value: radiusValue, - step: 10, - }) - const alreadyInTheImage = AllImageProviders.LoadImagesFor(tagSource) - const options: NearbyImageOptions & { value } = { - lon, - lat, - searchRadius: maxSearchRadius, - shownRadius: radius.GetValue(), - value: selectedImage, - blacklist: alreadyInTheImage, - towardscenter: towardsCenter.GetValue(), - maxDaysOld: 365 * 3, - } - const slideshow = canBeEdited - ? new SelectOneNearbyImage(options, state.indexedFeatures) - : new NearbyImages(options, state.indexedFeatures) - const controls = new Combine([ - towardsCenter, - new Combine([ - new VariableUiElement( - radius.GetValue().map((radius) => t.withinRadius.Subs({ radius })) - ), - radius, - ]).SetClass("flex justify-between"), - ]).SetClass("flex flex-col") - return new Combine([ - slideshow, - controls, - saveButton, - new MapillaryLinkVis().constr(state, tagSource, [], feature).SetClass("mt-6"), - ]) + return new SvelteUIElement(isOpen ? NearbyImages : NearbyImagesCollapsed, { + tags, + state, + lon, + lat, + feature, + layer, }) - - let withEdit: BaseUIElement = nearby - if (canBeEdited) { - withEdit = new Combine([t.hasMatchingPicture, nearby]).SetClass("flex flex-col") - } - - if (mode === "open") { - return withEdit - } - const toggleState = new UIEventSource(mode === "collapsable") - return new Toggle( - new Combine([new Title(t.title), withEdit]), - new Title(t.browseNearby).onClick(() => toggleState.setData(true)), - toggleState - ) } } @@ -1237,28 +1134,12 @@ export default class SpecialVisualizations { }, ], constr(__, tags, args) { - return new VariableUiElement( - tags.map((tags) => { - const [to, subject, body, button_text] = args.map((str) => - Utils.SubstituteKeys(str, tags) - ) - const url = - "mailto:" + - to + - "?subject=" + - encodeURIComponent(subject) + - "&body=" + - encodeURIComponent(body) - return new SubtleButton(Svg.envelope_svg(), button_text, { - url, - }) - }) - ) + return new SvelteUIElement(SendEmail, { args, tags }) }, }, { funcName: "link", - docs: "Construct a link. By using the 'special' visualisation notation, translation should be easier", + docs: "Construct a link. By using the 'special' visualisation notation, translations should be easier", args: [ { name: "text", diff --git a/src/UI/StylesheetTestGui.svelte b/src/UI/StylesheetTestGui.svelte index 9a0705c00..4ad143006 100644 --- a/src/UI/StylesheetTestGui.svelte +++ b/src/UI/StylesheetTestGui.svelte @@ -1,7 +1,7 @@
@@ -38,6 +38,13 @@ Main action (disabled) + + +