From 135d8644daf874ef134f1701de2c15dd949e84af Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Tue, 8 Mar 2022 04:09:03 +0100 Subject: [PATCH] Better social images --- Models/ThemeConfig/LayoutConfig.ts | 9 +- Utils.ts | 21 +- assets/SocialImageTemplate.svg | 2930 +++++++++++++++++ assets/SocialImageTemplateWide.svg | 2629 +++++++++++++++ assets/layers/bicycle_rental/rental.svg | 56 +- assets/layers/recycling/recycling-14.svg | 39 +- assets/tagRenderings/questions.json | 18 +- assets/themes/aed/aed.json | 2 +- assets/themes/aed/aed.svg | 36 +- assets/themes/aed/aed_brugge.json | 2 +- assets/themes/aed/license_info.json | 10 - assets/themes/aed/logo.svg | 392 --- assets/themes/benches/benches.json | 3 +- .../themes/bicycle_rental/bicycle_rental.json | 6 +- assets/themes/bicycle_rental/logo.svg | 57 +- assets/themes/bicyclelib/bicyclelib.json | 3 +- assets/themes/cyclestreets/logo.svg | 194 +- .../mapcomplete-changes.json | 46 +- index.manifest | 20 +- langs/id.json | 8 +- langs/shared-questions/id.json | 12 +- langs/themes/id.json | 20 +- scripts/ScriptUtils.ts | 5 +- scripts/generateLayerOverview.ts | 3 + scripts/generateLayouts.ts | 179 +- 25 files changed, 6032 insertions(+), 668 deletions(-) create mode 100644 assets/SocialImageTemplate.svg create mode 100644 assets/SocialImageTemplateWide.svg delete mode 100644 assets/themes/aed/logo.svg diff --git a/Models/ThemeConfig/LayoutConfig.ts b/Models/ThemeConfig/LayoutConfig.ts index eb22b8443..be970107a 100644 --- a/Models/ThemeConfig/LayoutConfig.ts +++ b/Models/ThemeConfig/LayoutConfig.ts @@ -8,6 +8,7 @@ import {ExtractImages} from "./Conversion/FixImages"; import ExtraLinkConfig from "./ExtraLinkConfig"; export default class LayoutConfig { + public static readonly defaultSocialImage = "assets/SocialImage.png" public readonly id: string; public readonly maintainer: string; public readonly credits?: string; @@ -54,7 +55,7 @@ export default class LayoutConfig { public readonly usedImages: string[] public readonly extraLink?: ExtraLinkConfig - + constructor(json: LayoutConfigJson, official = true, context?: string) { this.official = official; this.id = json.id; @@ -103,10 +104,10 @@ export default class LayoutConfig { this.shortDescription = json.shortDescription === undefined ? this.description.FirstSentence() : new Translation(json.shortDescription, context + ".shortdescription"); this.descriptionTail = json.descriptionTail === undefined ? undefined : new Translation(json.descriptionTail, context + ".descriptionTail"); this.icon = json.icon; - this.socialImage = json.socialImage; - if (this.socialImage === null || this.socialImage === "" || this.socialImage === undefined) { + this.socialImage = json.socialImage ?? LayoutConfig.defaultSocialImage; + if (this.socialImage === "") { if (official) { - throw "Theme " + json.id + " has no social image defined" + throw "Theme " + json.id + " has empty string as social image" } } this.startZoom = json.startZoom; diff --git a/Utils.ts b/Utils.ts index 1bb9292e3..630eab7c2 100644 --- a/Utils.ts +++ b/Utils.ts @@ -432,27 +432,32 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be /** * Apply a function on every leaf of the JSON; used to rewrite parts of the JSON - * @param json - * @param f - * @constructor */ - static WalkJson(json: any, f: (v: number | string | boolean | undefined) => any) { + static WalkJson(json: any, f: (v: number | string | boolean | undefined) => any, isLeaf: (object) => boolean = undefined) { if (json === undefined) { return f(undefined) } const jtp = typeof json - if (jtp === "boolean" || jtp === "string" || jtp === "number") { + if(isLeaf !== undefined) { + if(jtp === "object"){ + if(isLeaf(json)){ + return f(json) + } + } else { + return json + } + }else if (jtp === "boolean" || jtp === "string" || jtp === "number") { return f(json) } - if (json.map !== undefined) { + if (Array.isArray(json)) { return json.map(sub => { - return Utils.WalkJson(sub, f); + return Utils.WalkJson(sub, f, isLeaf); }) } const cp = {...json} for (const key in json) { - cp[key] = Utils.WalkJson(json[key], f) + cp[key] = Utils.WalkJson(json[key], f, isLeaf) } return cp } diff --git a/assets/SocialImageTemplate.svg b/assets/SocialImageTemplate.svg new file mode 100644 index 000000000..07be5d77f --- /dev/null +++ b/assets/SocialImageTemplate.svg @@ -0,0 +1,2930 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 01011001 00110101 10010011   + 01011001 00110101 10010011   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/SocialImageTemplateWide.svg b/assets/SocialImageTemplateWide.svg new file mode 100644 index 000000000..023adc72b --- /dev/null +++ b/assets/SocialImageTemplateWide.svg @@ -0,0 +1,2629 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 01011001 00110101 10010011   + 01011001 00110101 10010011   + + + + + + + + + + + + + + + diff --git a/assets/layers/bicycle_rental/rental.svg b/assets/layers/bicycle_rental/rental.svg index b66b2c214..07f27c2a1 100644 --- a/assets/layers/bicycle_rental/rental.svg +++ b/assets/layers/bicycle_rental/rental.svg @@ -1 +1,55 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + diff --git a/assets/layers/recycling/recycling-14.svg b/assets/layers/recycling/recycling-14.svg index 6244f4124..9778d136c 100644 --- a/assets/layers/recycling/recycling-14.svg +++ b/assets/layers/recycling/recycling-14.svg @@ -2,16 +2,34 @@ + id="svg2" + sodipodi:docname="recycling-14.svg" + inkscape:version="1.1.1 (1:1.1+202109281949+c3084ef5ed)" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + @@ -20,7 +38,6 @@ image/svg+xml - @@ -32,9 +49,9 @@ x="0" y="0" id="canvas" - style="fill:none;stroke:none;visibility:hidden" /> + style="visibility:hidden;fill:none;stroke:none" /> diff --git a/assets/tagRenderings/questions.json b/assets/tagRenderings/questions.json index dba3e5baa..807f12388 100644 --- a/assets/tagRenderings/questions.json +++ b/assets/tagRenderings/questions.json @@ -352,7 +352,8 @@ "zh_Hant": "這間商業空間是否允許犬隻?", "ru": "Впускают ли собак в это здание?", "pl": "Czy w tej firmie psy są dozwolone?", - "ja": "犬を飼うことができますか?" + "ja": "犬を飼うことができますか?", + "id": "Apakah anjing diperbolehkan dalam bisnis ini?" }, "mappings": [ { @@ -435,7 +436,8 @@ "zh_Hant": "允許犬隻而且可以自由跑動", "ru": "Собак свободно впускают", "pl": "Psy dozwolone i mogą biegać bez ograniczeń", - "ja": "犬同伴可能、自由に走り回れる" + "ja": "犬同伴可能、自由に走り回れる", + "id": "Anjing diperbolehkan dan dapat berkeliaran dengan bebas" } } ] @@ -754,7 +756,8 @@ "it": "Si trova sotto il livello stradale", "nb_NO": "Under bakken", "ca": "Situat a planta subterrani", - "ja": "地下にあります" + "ja": "地下にあります", + "id": "Terletak di bawah tanah" }, "hideInAnswer": true }, @@ -776,7 +779,8 @@ "it": "Si trova al pianoterra", "nb_NO": "På gateplan", "ca": "Situat a planta zero", - "ja": "1階にあります" + "ja": "1階にあります", + "id": "Terletak di lantai dasar" } }, { @@ -798,7 +802,8 @@ "it": "Si trova al pianoterra", "nb_NO": "På gateplan", "ca": "Situat a planta zero", - "ja": "1階にあります" + "ja": "1階にあります", + "id": "Terletak di lantai dasar" } }, { @@ -830,7 +835,8 @@ "nl": "Bevindt zich in de eerste kelderverdieping", "zh_Hant": "位於地下一樓", "de": "Ist im 1. Untergeschoss", - "hu": "Az első alagsori szinten" + "hu": "Az első alagsori szinten", + "id": "Terletak di lantai basement pertama" } } ] diff --git a/assets/themes/aed/aed.json b/assets/themes/aed/aed.json index 5c1a94ad6..8255a8705 100644 --- a/assets/themes/aed/aed.json +++ b/assets/themes/aed/aed.json @@ -19,7 +19,7 @@ "pt_BR": "Abrir mapa AED" }, "maintainer": "MapComplete", - "icon": "./assets/themes/aed/logo.svg", + "icon": "./assets/themes/aed/aed.svg", "description": { "en": "On this map, one can find and mark nearby defibrillators", "ca": "En aquest mapa , qualsevol pot trobar i marcar els desfibril·ladors externs automàtics més propers", diff --git a/assets/themes/aed/aed.svg b/assets/themes/aed/aed.svg index 3ab3f8840..0deeb8e51 100644 --- a/assets/themes/aed/aed.svg +++ b/assets/themes/aed/aed.svg @@ -1,8 +1,30 @@ - - - - - - + + + + + + + - \ No newline at end of file + diff --git a/assets/themes/aed/aed_brugge.json b/assets/themes/aed/aed_brugge.json index a0b5933e2..1fccbf9e3 100644 --- a/assets/themes/aed/aed_brugge.json +++ b/assets/themes/aed/aed_brugge.json @@ -4,7 +4,7 @@ "nl": "Open AED-kaart - Brugge edition" }, "maintainer": "MapComplete", - "icon": "./assets/themes/aed/logo.svg", + "icon": "./assets/themes/aed/aed.svg", "description": { "nl": "Op deze kaart kan je informatie over AEDs vinden en verbeteren + een export van de brugse defibrillatoren" }, diff --git a/assets/themes/aed/license_info.json b/assets/themes/aed/license_info.json index 0d0efe988..dac608205 100644 --- a/assets/themes/aed/license_info.json +++ b/assets/themes/aed/license_info.json @@ -8,15 +8,5 @@ "sources": [ "https://commons.wikimedia.org/wiki/File:ISO_7010_E010.svg" ] - }, - { - "path": "logo.svg", - "license": "CC-BY-SA 4.0", - "authors": [ - "M!dgard" - ], - "sources": [ - "https://commons.wikimedia.org/wiki/File:ISO_7010_E010.svg" - ] } ] \ No newline at end of file diff --git a/assets/themes/aed/logo.svg b/assets/themes/aed/logo.svg deleted file mode 100644 index 8510ff1b8..000000000 --- a/assets/themes/aed/logo.svg +++ /dev/null @@ -1,392 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/assets/themes/benches/benches.json b/assets/themes/benches/benches.json index 7ed0d305e..c088ca9a5 100644 --- a/assets/themes/benches/benches.json +++ b/assets/themes/benches/benches.json @@ -25,7 +25,8 @@ "zh_Hant": "長椅的地圖", "nb_NO": "Et benkekart", "pt_BR": "Um mapa de bancadas", - "hu": "Padtérkép" + "hu": "Padtérkép", + "id": "Peta bangku" }, "description": { "en": "This map shows all benches that are recorded in OpenStreetMap: Individual benches, and benches belonging to public transport stops or shelters. With an OpenStreetMap account, you can map new benches or edit details of existing benches.", diff --git a/assets/themes/bicycle_rental/bicycle_rental.json b/assets/themes/bicycle_rental/bicycle_rental.json index bcd0f5da5..efe22fc11 100644 --- a/assets/themes/bicycle_rental/bicycle_rental.json +++ b/assets/themes/bicycle_rental/bicycle_rental.json @@ -3,12 +3,14 @@ "title": { "en": "Bicycle rental", "nl": "Fietsverhuur", - "de": "Fahrradverleih" + "de": "Fahrradverleih", + "id": "Sewa sepeda" }, "shortDescription": { "en": "A map with bicycle rental stations and bicycle rental shops", "nl": "Een kaart met fietsverhuurpunten en fietsverhuurzaken", - "de": "Eine Karte mit Fahrradverleihstationen und Fahrradverleihern" + "de": "Eine Karte mit Fahrradverleihstationen und Fahrradverleihern", + "id": "Peta dengan stasiun persewaan sepeda dan toko penyewaan sepeda" }, "description": { "en": "On this map, you'll find the many bicycle rental stations as they are known by OpenStreetMap", diff --git a/assets/themes/bicycle_rental/logo.svg b/assets/themes/bicycle_rental/logo.svg index b66b2c214..910514d2f 100644 --- a/assets/themes/bicycle_rental/logo.svg +++ b/assets/themes/bicycle_rental/logo.svg @@ -1 +1,56 @@ - \ No newline at end of file + + + + + + + + + + + + + + diff --git a/assets/themes/bicyclelib/bicyclelib.json b/assets/themes/bicyclelib/bicyclelib.json index b3ee810bf..ff367b0d5 100644 --- a/assets/themes/bicyclelib/bicyclelib.json +++ b/assets/themes/bicyclelib/bicyclelib.json @@ -14,7 +14,8 @@ "de": "Fahrradbibliothek", "pt_BR": "Bibliotecas de bicicletas", "pl": "Wypożyczalnie rowerów", - "hu": "Kerékpárkönyvtárak" + "hu": "Kerékpárkönyvtárak", + "id": "Perpustakaan sepeda" }, "description": { "nl": "Een fietsbibliotheek is een plaats waar men een fiets kan lenen, vaak voor een klein bedrag per jaar. Een typisch voorbeeld zijn kinderfietsbibliotheken, waar men een fiets op maat van het kind kan lenen. Is het kind de fiets ontgroeid, dan kan het te kleine fietsje omgeruild worden voor een grotere.", diff --git a/assets/themes/cyclestreets/logo.svg b/assets/themes/cyclestreets/logo.svg index 0d6aa7490..d380b8535 100644 --- a/assets/themes/cyclestreets/logo.svg +++ b/assets/themes/cyclestreets/logo.svg @@ -11,10 +11,8 @@ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> - - - - + inkscape:zoom="1.682" + inkscape:cx="249.70273" + inkscape:cy="359.69084" + inkscape:current-layer="svg43" /> + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/assets/themes/mapcomplete-changes/mapcomplete-changes.json b/assets/themes/mapcomplete-changes/mapcomplete-changes.json index dc7fbecca..da73732b3 100644 --- a/assets/themes/mapcomplete-changes/mapcomplete-changes.json +++ b/assets/themes/mapcomplete-changes/mapcomplete-changes.json @@ -1,16 +1,13 @@ { "id": "mapcomplete-changes", "title": { - "en": "Changes made with MapComplete", - "de": "Änderungen mit MapComplete" + "en": "Changes made with MapComplete" }, "shortDescription": { - "en": "Shows changes made by MapComplete", - "de": "Zeigt Änderungen, die von MapComplete vorgenommen wurden" + "en": "Shows changes made by MapComplete" }, "description": { - "en": "This maps shows all the changes made with MapComplete", - "de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen" + "en": "This maps shows all the changes made with MapComplete" }, "maintainer": "", "icon": "./assets/svg/logo.svg", @@ -25,8 +22,7 @@ { "id": "mapcomplete-changes", "name": { - "en": "Changeset centers", - "de": "Schwerpunkte von Änderungssätzen" + "en": "Changeset centers" }, "minzoom": 0, "source": { @@ -40,41 +36,35 @@ ], "title": { "render": { - "en": "Changeset for {theme}", - "de": "Änderungssatz für {theme}" + "en": "Changeset for {theme}" } }, "description": { - "en": "Shows all MapComplete changes", - "de": "Zeigt alle MapComplete-Änderungen" + "en": "Shows all MapComplete changes" }, "tagRenderings": [ { "id": "render_id", "render": { - "en": "Changeset {id}", - "de": "Änderungssatz {id}" + "en": "Changeset {id}" } }, { "id": "contributor", "render": { - "en": "Change made by {_last_edit:contributor}", - "de": "Geändert von {_last_edit:contributor}" + "en": "Change made by {_last_edit:contributor}" } }, { "id": "theme", "render": { - "en": "Change with theme {theme}", - "de": "Änderung mit Thema {theme}" + "en": "Change with theme {theme}" }, "mappings": [ { "if": "theme~http.*", "then": { - "en": "Change with unofficial theme {theme}", - "de": "Änderung mit inoffiziellem Thema {theme}" + "en": "Change with unofficial theme {theme}" } } ] @@ -91,11 +81,11 @@ "mappings": [ { "if": "theme=aed", - "then": "./assets/themes/aed/logo.svg" + "then": "./assets/themes/aed/aed.svg" }, { "if": "theme=aed_brugge", - "then": "./assets/themes/aed/logo.svg" + "then": "./assets/themes/aed/aed.svg" }, { "if": "theme=artwork", @@ -338,8 +328,7 @@ } ], "question": { - "en": "Themename contains {search}", - "de": "Themenname enthält {search}" + "en": "Themename contains {search}" } } ] @@ -355,8 +344,7 @@ } ], "question": { - "en": "Made by contributor {search}", - "de": "Erstellt von Mitwirkendem {search}" + "en": "Made by contributor {search}" } } ] @@ -372,8 +360,7 @@ } ], "question": { - "en": "Not made by contributor {search}", - "de": " Nicht erstellt von Mitwirkendem {search}" + "en": "Not made by contributor {search}" } } ] @@ -388,8 +375,7 @@ { "id": "link_to_more", "render": { - "en": "More statistics can be found here", - "de": "Weitere Statistiken finden Sie hier" + "en": "More statistics can be found here" } }, { diff --git a/index.manifest b/index.manifest index 9109a8b09..d5dc9e014 100644 --- a/index.manifest +++ b/index.manifest @@ -9,52 +9,52 @@ "orientation": "portrait-primary, landscape-primary", "icons": [ { - "src": "assets/generated/svg_mapcomplete_logo72.png", + "src": "assets/generated/images/mapcomplete_logo72.png", "sizes": "72x72", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo96.png", + "src": "assets/generated/images/mapcomplete_logo96.png", "sizes": "96x96", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo120.png", + "src": "assets/generated/images/mapcomplete_logo120.png", "sizes": "120x120", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo128.png", + "src": "assets/generated/images/mapcomplete_logo128.png", "sizes": "128x128", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo144.png", + "src": "assets/generated/images/mapcomplete_logo144.png", "sizes": "144x144", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo152.png", + "src": "assets/generated/images/mapcomplete_logo152.png", "sizes": "152x152", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo180.png", + "src": "assets/generated/images/mapcomplete_logo180.png", "sizes": "180x180", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo192.png", + "src": "assets/generated/images/mapcomplete_logo192.png", "sizes": "192x192", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo384.png", + "src": "assets/generated/images/mapcomplete_logo384.png", "sizes": "384x384", "type": "image/png" }, { - "src": "assets/generated/svg_mapcomplete_logo512.png", + "src": "assets/generated/images/mapcomplete_logo512.png", "sizes": "512x512", "type": "image/png" }, diff --git a/langs/id.json b/langs/id.json index 45ef6bea2..bc6c86a08 100644 --- a/langs/id.json +++ b/langs/id.json @@ -8,12 +8,12 @@ "delete": { "cancel": "Batal", "cannotBeDeleted": "Fitur ini tidak dapat dihapus", + "delete": "Hapus", "explanations": { "selectReason": "Silahkan pilih mengapa fitur ini harus dihapus" }, - "isntAPoint": "Hanya titik yang dapat dihapus, fitur yang dipilih adalah jalan, area, atau relasi.", - "delete": "Hapus", - "isDeleted": "Fitur ini telah dihapus" + "isDeleted": "Fitur ini telah dihapus", + "isntAPoint": "Hanya titik yang dapat dihapus, fitur yang dipilih adalah jalan, area, atau relasi." }, "favourite": { "reload": "Muat ulang data" @@ -115,4 +115,4 @@ "split": { "cancel": "Batal" } -} +} \ No newline at end of file diff --git a/langs/shared-questions/id.json b/langs/shared-questions/id.json index 6cebfc7ad..b7a10a3ba 100644 --- a/langs/shared-questions/id.json +++ b/langs/shared-questions/id.json @@ -25,18 +25,18 @@ }, "level": { "mappings": { - "3": { - "then": "Berlokasi di lantai pertama" + "0": { + "then": "Terletak di bawah tanah" }, "1": { "then": "Terletak di lantai dasar" }, - "0": { - "then": "Terletak di bawah tanah" - }, "2": { "then": "Terletak di lantai dasar" }, + "3": { + "then": "Berlokasi di lantai pertama" + }, "4": { "then": "Terletak di lantai basement pertama" } @@ -61,4 +61,4 @@ "question": "Apa situs web dari {title()}?" } } -} +} \ No newline at end of file diff --git a/langs/themes/id.json b/langs/themes/id.json index efe1d30c2..f78f2a16e 100644 --- a/langs/themes/id.json +++ b/langs/themes/id.json @@ -8,8 +8,15 @@ "title": "Buka Peta Karya Seni" }, "benches": { - "title": "Bangku", - "shortDescription": "Peta bangku" + "shortDescription": "Peta bangku", + "title": "Bangku" + }, + "bicycle_rental": { + "shortDescription": "Peta dengan stasiun persewaan sepeda dan toko penyewaan sepeda", + "title": "Sewa sepeda" + }, + "bicyclelib": { + "title": "Perpustakaan sepeda" }, "cafes_and_pubs": { "title": "Kafe dan pub" @@ -283,12 +290,5 @@ }, "waste_basket": { "title": "Keranjang Sampah" - }, - "bicyclelib": { - "title": "Perpustakaan sepeda" - }, - "bicycle_rental": { - "title": "Sewa sepeda", - "shortDescription": "Peta dengan stasiun persewaan sepeda dan toko penyewaan sepeda" } -} +} \ No newline at end of file diff --git a/scripts/ScriptUtils.ts b/scripts/ScriptUtils.ts index 91abecce4..ae938d87b 100644 --- a/scripts/ScriptUtils.ts +++ b/scripts/ScriptUtils.ts @@ -1,5 +1,5 @@ import * as fs from "fs"; -import {lstatSync, readdirSync, readFileSync} from "fs"; +import {existsSync, lstatSync, readdirSync, readFileSync} from "fs"; import {Utils} from "../Utils"; import * as https from "https"; import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson"; @@ -146,6 +146,9 @@ export default class ScriptUtils { } public static async ReadSvg(path: string): Promise{ + if(!existsSync(path)){ + throw "File not found: "+path + } const root = await xml2js.parseStringPromise(readFileSync(path, "UTF8")) return root.svg } diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index a14a88623..5c8b4836b 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -102,6 +102,9 @@ class LayerOverviewUtils { .filter(path => !path.startsWith("./assets/generated")) let errCount = 0; for (const path of allSvgs) { + if(path.indexOf("assets/SocialImageTemplate") >= 0){ + continue + } const contents = readFileSync(path, "UTF8") if (contents.indexOf("data:image/png;") < 0) { continue; diff --git a/scripts/generateLayouts.ts b/scripts/generateLayouts.ts index f31565326..43a9029a1 100644 --- a/scripts/generateLayouts.ts +++ b/scripts/generateLayouts.ts @@ -8,6 +8,7 @@ import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson"; import LayoutConfig from "../Models/ThemeConfig/LayoutConfig"; import xml2js from 'xml2js'; import ScriptUtils from "./ScriptUtils"; +import {Utils} from "../Utils"; const sharp = require('sharp'); const template = readFileSync("theme.html", "utf8"); @@ -19,72 +20,126 @@ function enc(str: string): string { } async function createIcon(iconPath: string, size: number, alreadyWritten: string[]) { - let name = iconPath.split(".").slice(0, -1).join("."); + let name = iconPath.split(".").slice(0, -1).join("."); // drop svg suffix if (name.startsWith("./")) { name = name.substr(2) } - const newname = `${name}${size}.png` - .replace(/\//g, "_") - .replace("assets_", "assets/generated/"); + + const newname = `assets/generated/images${name.substring(name.lastIndexOf("/"))}${size}.png`; if (alreadyWritten.indexOf(newname) >= 0) { return newname; } alreadyWritten.push(newname); - try { - readFileSync(newname); - return newname; // File already exists - nothing to do - } catch (e) { - // Errors are normal here if this file does not exists + if (existsSync(newname)) { + return newname + } + + if (!existsSync(iconPath)) { + throw "No file at " + iconPath } try { // We already read to file, in order to crash here if the file is not found - readFileSync(iconPath); let img = await sharp(iconPath) let resized = await img.resize(size) await resized.toFile(newname) + console.log("Written", newname) } catch (e) { - console.error("Could not read icon", iconPath, "due to", e) + console.error("Could not read icon", iconPath, " to create a PNG due to", e) } return newname; } -async function createManifest(layout: LayoutConfig, alreadyWritten: string[]) { +async function createSocialImage(layout: LayoutConfig, template: "" | "Wide"): Promise { + if (!layout.icon.endsWith(".svg")) { + console.warn("Not creating a social image for " + layout.id + " as it is _not_ a .svg: " + layout.icon) + return undefined + } + const path = `./assets/generated/images/social_image_${layout.id}_${template}.svg` + if(existsSync(path)){ + // return path; + } + const svg = await ScriptUtils.ReadSvg(layout.icon) + let width: string = svg.$.width; + if (width === undefined) { + throw "The logo at " + layout.icon + " does not have a defined width" + } + if (width?.endsWith("px")) { + width = width.substring(0, width.length - 2) + } + if (width?.endsWith("%")) { + throw "The logo at " + layout.icon + " has a relative width; this is not supported" + } + delete svg["defs"] + delete svg["$"] + let templateSvg = await ScriptUtils.ReadSvg("./assets/SocialImageTemplate" + template + ".svg") + templateSvg = Utils.WalkJson(templateSvg, + (leaf) => { + const {cx, cy, r} = leaf["circle"][0].$ + return { + $: { + id: "icon", + transform: `translate(${cx - r},${cy - r}) scale(${(r * 2) / Number(width)}) ` + }, + g: [svg] + } + }, + (mightBeTokenToReplace) => { + if (mightBeTokenToReplace?.circle === undefined) { + return false + } + return mightBeTokenToReplace.circle[0]?.$?.style?.indexOf("fill:#ff00ff") >= 0 + } + ) + + + const builder = new xml2js.Builder(); + const xml = builder.buildObject({svg: templateSvg}); + writeFileSync(path, xml) + console.log("Written", path) + return path +} + +async function createManifest(layout: LayoutConfig, alreadyWritten: string[]): Promise<{ + manifest: any, + whiteIcons: string[] +}> { const name = layout.id; Translation.forcedLanguage = "en" const icons = []; - + const whiteIcons: string[] = [] let icon = layout.icon; if (icon.endsWith(".svg") || icon.startsWith(" - + - ` + ` let icon = layout.icon; if (icon.startsWith("`) + const size = icon.replace(/[^0-9]/g, "") + apple_icons.push(``) } let themeSpecific = [ @@ -206,31 +275,32 @@ async function createIndexFor(theme: LayoutConfig) { appendFileSync(filename, codeTemplate) } -function createDir(path){ +function createDir(path) { if (!existsSync(path)) { mkdirSync(path) } } -async function main(): Promise{ - +async function main(): Promise { + const alreadyWritten = [] createDir("./assets/generated") createDir("./assets/generated/layers") createDir("./assets/generated/themes") + createDir("./assets/generated/images") const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap", "custom", "theme"] // @ts-ignore const all: LayoutConfigJson[] = all_known_layouts.themes; const args = process.argv const theme = args[2] - if(theme !== undefined){ - console.warn("Only generating layout "+theme) + if (theme !== undefined) { + console.warn("Only generating layout " + theme) } for (const i in all) { const layoutConfigJson: LayoutConfigJson = all[i] - if(theme !== undefined && layoutConfigJson.id !== theme){ + if (theme !== undefined && layoutConfigJson.id !== theme) { continue } const layout = new LayoutConfig(layoutConfigJson, true, "generating layouts") @@ -244,21 +314,20 @@ async function main(): Promise{ console.log("Could not write manifest for ", layoutName, " because ", err) } }; - await createManifest(layout, alreadyWritten).then(manifObj => { - const manif = JSON.stringify(manifObj, undefined, 2); - const manifestLocation = encodeURIComponent(layout.id.toLowerCase()) + ".webmanifest"; - writeFile(manifestLocation, manif, err); - - // Create a landing page for the given theme - createLandingPage(layout, manifObj).then(landing => { - writeFile(enc(layout.id) + ".html", landing, err) - }); - createIndexFor(layout) - }).catch(e => console.log("Could not generate the manifest: ", e)) - + const {manifest, whiteIcons} = await createManifest(layout, alreadyWritten) + const manif = JSON.stringify(manifest, undefined, 2); + const manifestLocation = encodeURIComponent(layout.id.toLowerCase()) + ".webmanifest"; + writeFile(manifestLocation, manif, err); + + // Create a landing page for the given theme + createLandingPage(layout, manifest, whiteIcons, alreadyWritten).then(landing => { + writeFile(enc(layout.id) + ".html", landing, err) + }); + createIndexFor(layout) } - - await createManifest(new LayoutConfig({ + + + const {manifest, whiteIcons} = await createManifest(new LayoutConfig({ icon: "./assets/svg/mapcomplete_logo.svg", id: "index", layers: [], @@ -270,10 +339,10 @@ async function main(): Promise{ title: {en: "MapComplete"}, version: Constants.vNumber, description: {en: "A thematic map viewer and editor based on OpenStreetMap"} - }), alreadyWritten).then(manifObj => { - const manif = JSON.stringify(manifObj, undefined, 2); - writeFileSync("index.manifest", manif) - }) + }), alreadyWritten); + + const manif = JSON.stringify(manifest, undefined, 2); + writeFileSync("index.manifest", manif) } main().then(() => {