Better social images
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
21
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)
|
||||
}
|
||||
if (json.map !== undefined) {
|
||||
} else {
|
||||
return json
|
||||
}
|
||||
}else if (jtp === "boolean" || jtp === "string" || jtp === "number") {
|
||||
return f(json)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
|
2930
assets/SocialImageTemplate.svg
Normal file
After Width: | Height: | Size: 3.1 MiB |
2629
assets/SocialImageTemplateWide.svg
Normal file
After Width: | Height: | Size: 3.1 MiB |
|
@ -1 +1,55 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 141.73 141.73"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#3c3d3c;}</style></defs><g id="Laag_1" data-name="Laag 1"><circle class="cls-1" cx="70.87" cy="70.87" r="70.87"/></g><g id="Laag_2" data-name="Laag 2"><path class="cls-2" d="M102.39,75a18.18,18.18,0,0,0-3.92.43L92.87,57a7,7,0,0,0-6.77-5H80.67v2.59H86.1a4.45,4.45,0,0,1,4.29,3.19l1.72,5.66H55.54l-2-4.89h3.72S62,57.77,62,54.14H46.39v4.33h4.35l2.55,6.25L47.67,76.27A18.31,18.31,0,1,0,59,96.27h8l1-.43L93.33,67.37,96,76.15a18.28,18.28,0,1,0,6.4-1.17ZM41,109a15.72,15.72,0,1,1,5.58-30.4l-7.69,15.8L40,96.27H56.38A15.74,15.74,0,0,1,41,109Zm15.7-15.33H42.07l6.8-14a15.71,15.71,0,0,1,7.8,13.56C56.67,93.42,56.66,93.55,56.65,93.68ZM50,77.39l4.61-9.45,10.5,25.74H59.24c0-.13,0-.26,0-.39A18.33,18.33,0,0,0,50,77.39ZM67.45,92.56,56.59,66H91.13ZM102.39,109a15.71,15.71,0,0,1-5.65-30.38l4.56,15,2.48-.76-4.56-15A15.72,15.72,0,1,1,102.39,109Z"/><path class="cls-2" d="M78.72,40.26a13.89,13.89,0,0,1-5.58,1.25,9.86,9.86,0,0,1-5.6-1.61,9,9,0,0,1-3.39-4.41h9.4l1.07-2.89-.13-.36h-11a2.91,2.91,0,0,1,0-.4v-.57c0-.4,0-.79.05-1.17h12l1.08-2.93L76.36,27H64.13a8.69,8.69,0,0,1,3.48-4.43A10.82,10.82,0,0,1,73.55,21a16.47,16.47,0,0,1,4.55.68l.13,0,1.08-3-.15-.05a16.56,16.56,0,0,0-5.3-.81,14.91,14.91,0,0,0-8.42,2.35A11.73,11.73,0,0,0,60.66,27h-2.3l-1.08,2.93.19.19h2.69c0,.16,0,.32,0,.49v1.23c0,.14,0,.29,0,.42h-1.8L57.28,35.3l.19.19h3.21a12.2,12.2,0,0,0,4.48,6.72,12.47,12.47,0,0,0,7.64,2.46A16.44,16.44,0,0,0,79,43.39l.09,0v-3l-.28-.16Z"/></g></svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 141.73 141.73"
|
||||
version="1.1"
|
||||
id="svg14"
|
||||
sodipodi:docname="rental.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">
|
||||
<sodipodi:namedview
|
||||
id="namedview16"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.6516417"
|
||||
inkscape:cx="41.10661"
|
||||
inkscape:cy="42.615109"
|
||||
inkscape:current-layer="svg14" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<style
|
||||
id="style2">.cls-1{fill:#fff;}.cls-2{fill:#3c3d3c;}</style>
|
||||
</defs>
|
||||
<g
|
||||
id="g838">
|
||||
<g
|
||||
id="Laag_1"
|
||||
data-name="Laag 1">
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="70.87"
|
||||
cy="70.87"
|
||||
r="70.87"
|
||||
id="circle6" />
|
||||
</g>
|
||||
<g
|
||||
id="Laag_2"
|
||||
data-name="Laag 2">
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M102.39,75a18.18,18.18,0,0,0-3.92.43L92.87,57a7,7,0,0,0-6.77-5H80.67v2.59H86.1a4.45,4.45,0,0,1,4.29,3.19l1.72,5.66H55.54l-2-4.89h3.72S62,57.77,62,54.14H46.39v4.33h4.35l2.55,6.25L47.67,76.27A18.31,18.31,0,1,0,59,96.27h8l1-.43L93.33,67.37,96,76.15a18.28,18.28,0,1,0,6.4-1.17ZM41,109a15.72,15.72,0,1,1,5.58-30.4l-7.69,15.8L40,96.27H56.38A15.74,15.74,0,0,1,41,109Zm15.7-15.33H42.07l6.8-14a15.71,15.71,0,0,1,7.8,13.56C56.67,93.42,56.66,93.55,56.65,93.68ZM50,77.39l4.61-9.45,10.5,25.74H59.24c0-.13,0-.26,0-.39A18.33,18.33,0,0,0,50,77.39ZM67.45,92.56,56.59,66H91.13ZM102.39,109a15.71,15.71,0,0,1-5.65-30.38l4.56,15,2.48-.76-4.56-15A15.72,15.72,0,1,1,102.39,109Z"
|
||||
id="path9" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="M78.72,40.26a13.89,13.89,0,0,1-5.58,1.25,9.86,9.86,0,0,1-5.6-1.61,9,9,0,0,1-3.39-4.41h9.4l1.07-2.89-.13-.36h-11a2.91,2.91,0,0,1,0-.4v-.57c0-.4,0-.79.05-1.17h12l1.08-2.93L76.36,27H64.13a8.69,8.69,0,0,1,3.48-4.43A10.82,10.82,0,0,1,73.55,21a16.47,16.47,0,0,1,4.55.68l.13,0,1.08-3-.15-.05a16.56,16.56,0,0,0-5.3-.81,14.91,14.91,0,0,0-8.42,2.35A11.73,11.73,0,0,0,60.66,27h-2.3l-1.08,2.93.19.19h2.69c0,.16,0,.32,0,.49v1.23c0,.14,0,.29,0,.42h-1.8L57.28,35.3l.19.19h3.21a12.2,12.2,0,0,0,4.48,6.72,12.47,12.47,0,0,0,7.64,2.46A16.44,16.44,0,0,0,79,43.39l.09,0v-3l-.28-.16Z"
|
||||
id="path11" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
@ -2,16 +2,34 @@
|
|||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width="100%"
|
||||
height="100%"
|
||||
width="14px"
|
||||
height="14px"
|
||||
viewBox="0 0 14 14"
|
||||
id="svg2">
|
||||
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/">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:zoom="60.071429"
|
||||
inkscape:cx="6.9916766"
|
||||
inkscape:cy="7.0083234"
|
||||
inkscape:current-layer="svg2" />
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
|
@ -20,7 +38,6 @@
|
|||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
|
@ -32,9 +49,9 @@
|
|||
x="0"
|
||||
y="0"
|
||||
id="canvas"
|
||||
style="fill:none;stroke:none;visibility:hidden" />
|
||||
style="visibility:hidden;fill:none;stroke:none" />
|
||||
<path
|
||||
d="M 5.111113,8.690628 3.513352,5.804047 0.3,5.804047 1.60621,6.5880837 0.798678,8.031102 c -0.06887,0.130859 -0.103304,0.267511 -0.103301,0.409961 -3e-6,0.142456 0.03443,0.27911 0.103301,0.40996 l 1.271077,2.298282 c 0.05733,-0.166376 0.11466,-0.309011 0.171995,-0.427902 L 3.82273,7.906591 5.111113,8.690628 z m -2.38799,2.316224 c -0.09194,0.154416 -0.137914,0.320611 -0.13791,0.498585 -4e-6,0.273307 0.09456,0.504931 0.283685,0.694868 0.189119,0.189939 0.415298,0.284906 0.678537,0.284906 l 3.161963,0 0,-2.654413 -3.333432,0 C 3.352886,9.878288 3.266892,10.0327 3.117975,10.294041 l -0.394852,0.712811 z m 4.278351,-6.5745954 3.196047,0 L 11.812587,1.54622 10.506901,2.3302555 9.698844,0.8866933 C 9.549912,0.6137609 9.320934,0.4772893 9.011916,0.4772767 l -2.543205,0 c 0.10312,0.1185426 0.189116,0.2372528 0.257992,0.3561331 L 8.289856,3.6482199 8.032389,3.8086154 7.001474,4.4322566 z M 5.437797,0.6197306 C 5.07108,0.6197421 4.796134,0.7859374 4.61296,1.1183163 L 3.015198,3.9690109 C 3.622066,4.3372941 4.360906,4.7767964 5.231719,5.2875185 5.746994,4.372999 6.302478,3.3752843 6.898173,2.2943703 L 6.262635,1.1183163 C 6.079446,0.7859374 5.804501,0.6197421 5.437797,0.6197306 l 0,0 z m 4.106882,9.1751824 0,-0.320793 0,-1.228795 L 7.946393,11.131363 9.544679,14 l 0,-1.55013 1.597761,0 c 0.309366,0 0.54411,-0.136653 0.704231,-0.409962 l 1.271602,-2.298279 c -0.171656,0.04749 -0.314811,0.07123 -0.42946,0.07123 L 9.544679,9.794909 z m 2.37121,-4.88147 c -0.05735,0.035533 -0.79636,0.4750321 -2.217045,1.3185066 0.710337,1.2708484 1.271764,2.2745434 1.684282,3.0110934 l 1.288383,0 c 0.378233,2e-6 0.658946,-0.166373 0.842142,-0.499132 0.171629,-0.320788 0.165862,-0.647379 -0.01731,-0.979774 l -1.58045,-2.850694 z"
|
||||
d="M 5.111113,8.690628 3.513352,5.804047 H 0.3 L 1.60621,6.5880837 0.798678,8.031102 c -0.06887,0.130859 -0.103304,0.267511 -0.103301,0.409961 -3e-6,0.142456 0.03443,0.27911 0.103301,0.40996 l 1.271077,2.298282 c 0.05733,-0.166376 0.11466,-0.309011 0.171995,-0.427902 L 3.82273,7.906591 Z m -2.38799,2.316224 c -0.09194,0.154416 -0.137914,0.320611 -0.13791,0.498585 -4e-6,0.273307 0.09456,0.504931 0.283685,0.694868 0.189119,0.189939 0.415298,0.284906 0.678537,0.284906 H 6.709398 V 9.830798 H 3.375966 C 3.352886,9.878288 3.266892,10.0327 3.117975,10.294041 Z M 7.001474,4.4322566 h 3.196047 L 11.812587,1.54622 10.506901,2.3302555 9.698844,0.8866933 C 9.549912,0.6137609 9.320934,0.4772893 9.011916,0.4772767 H 6.468711 c 0.10312,0.1185426 0.189116,0.2372528 0.257992,0.3561331 L 8.289856,3.6482199 8.032389,3.8086154 Z M 5.437797,0.6197306 C 5.07108,0.6197421 4.796134,0.7859374 4.61296,1.1183163 L 3.015198,3.9690109 C 3.622066,4.3372941 4.360906,4.7767964 5.231719,5.2875185 5.746994,4.372999 6.302478,3.3752843 6.898173,2.2943703 L 6.262635,1.1183163 C 6.079446,0.7859374 5.804501,0.6197421 5.437797,0.6197306 Z M 9.544679,9.794913 V 9.47412 8.245325 L 7.946393,11.131363 9.544679,14 v -1.55013 h 1.597761 c 0.309366,0 0.54411,-0.136653 0.704231,-0.409962 l 1.271602,-2.298279 c -0.171656,0.04749 -0.314811,0.07123 -0.42946,0.07123 L 9.544679,9.794909 Z m 2.37121,-4.88147 c -0.05735,0.035533 -0.79636,0.4750321 -2.217045,1.3185066 0.710337,1.2708484 1.271764,2.2745434 1.684282,3.0110934 h 1.288383 c 0.378233,2e-6 0.658946,-0.166373 0.842142,-0.499132 0.171629,-0.320788 0.165862,-0.647379 -0.01731,-0.979774 l -1.58045,-2.850694 z"
|
||||
id="recycling"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none" />
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.1 KiB |
|
@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1,8 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="375px" height="375px" viewBox="0 0 375 375" version="1.1">
|
||||
<g id="surface1">
|
||||
<rect x="0" y="0" width="375" height="375" style="fill:rgb(0%,53.333336%,33.333334%);fill-opacity:1;stroke:none;"/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 279.210938 32.8125 L 309.375 32.8125 L 309.375 63.179688 L 339.742188 63.179688 L 339.742188 93.34375 L 309.375 93.34375 L 309.375 123.710938 L 279.210938 123.710938 L 279.210938 93.34375 L 248.84375 93.34375 L 248.84375 63.179688 L 279.210938 63.179688 Z M 279.210938 32.8125 "/>
|
||||
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 96.808594 114.742188 C 57.675781 115.148438 22.621094 154.074219 33.21875 205.433594 C 41.167969 244.769531 82.949219 295.71875 155.707031 345.039062 C 228.464844 295.515625 270.246094 244.566406 278.191406 205.433594 C 288.789062 153.871094 253.941406 115.148438 214.605469 114.742188 C 194.429688 114.335938 169.15625 125.136719 155.707031 150.816406 C 142.253906 125.136719 116.984375 114.335938 96.808594 114.742188 Z M 187.09375 145.925781 L 152.851562 216.238281 L 196.261719 216.238281 L 120.246094 304.6875 L 149.59375 235.394531 L 107.40625 235.394531 Z M 187.09375 145.925781 "/>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="375px"
|
||||
height="375px"
|
||||
viewBox="0 0 375 375"
|
||||
version="1.1"
|
||||
id="svg9"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs13" />
|
||||
<g
|
||||
id="surface1">
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="375"
|
||||
height="375"
|
||||
style="fill:rgb(0%,53.333336%,33.333334%);fill-opacity:1;stroke:none;"
|
||||
id="rect2" />
|
||||
<path
|
||||
style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;"
|
||||
d="M 279.210938 32.8125 L 309.375 32.8125 L 309.375 63.179688 L 339.742188 63.179688 L 339.742188 93.34375 L 309.375 93.34375 L 309.375 123.710938 L 279.210938 123.710938 L 279.210938 93.34375 L 248.84375 93.34375 L 248.84375 63.179688 L 279.210938 63.179688 Z M 279.210938 32.8125 "
|
||||
id="path4" />
|
||||
<path
|
||||
style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;"
|
||||
d="M 96.808594 114.742188 C 57.675781 115.148438 22.621094 154.074219 33.21875 205.433594 C 41.167969 244.769531 82.949219 295.71875 155.707031 345.039062 C 228.464844 295.515625 270.246094 244.566406 278.191406 205.433594 C 288.789062 153.871094 253.941406 115.148438 214.605469 114.742188 C 194.429688 114.335938 169.15625 125.136719 155.707031 150.816406 C 142.253906 125.136719 116.984375 114.335938 96.808594 114.742188 Z M 187.09375 145.925781 L 152.851562 216.238281 L 196.261719 216.238281 L 120.246094 304.6875 L 149.59375 235.394531 L 107.40625 235.394531 Z M 187.09375 145.925781 "
|
||||
id="path6" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.6 KiB |
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
Before Width: | Height: | Size: 54 KiB |
|
@ -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.",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1 +1,56 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 141.73 141.73"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#3c3d3c;}</style></defs><g id="Laag_1" data-name="Laag 1"><circle class="cls-1" cx="70.87" cy="70.87" r="70.87"/></g><g id="Laag_2" data-name="Laag 2"><path class="cls-2" d="M102.39,75a18.18,18.18,0,0,0-3.92.43L92.87,57a7,7,0,0,0-6.77-5H80.67v2.59H86.1a4.45,4.45,0,0,1,4.29,3.19l1.72,5.66H55.54l-2-4.89h3.72S62,57.77,62,54.14H46.39v4.33h4.35l2.55,6.25L47.67,76.27A18.31,18.31,0,1,0,59,96.27h8l1-.43L93.33,67.37,96,76.15a18.28,18.28,0,1,0,6.4-1.17ZM41,109a15.72,15.72,0,1,1,5.58-30.4l-7.69,15.8L40,96.27H56.38A15.74,15.74,0,0,1,41,109Zm15.7-15.33H42.07l6.8-14a15.71,15.71,0,0,1,7.8,13.56C56.67,93.42,56.66,93.55,56.65,93.68ZM50,77.39l4.61-9.45,10.5,25.74H59.24c0-.13,0-.26,0-.39A18.33,18.33,0,0,0,50,77.39ZM67.45,92.56,56.59,66H91.13ZM102.39,109a15.71,15.71,0,0,1-5.65-30.38l4.56,15,2.48-.76-4.56-15A15.72,15.72,0,1,1,102.39,109Z"/><path class="cls-2" d="M78.72,40.26a13.89,13.89,0,0,1-5.58,1.25,9.86,9.86,0,0,1-5.6-1.61,9,9,0,0,1-3.39-4.41h9.4l1.07-2.89-.13-.36h-11a2.91,2.91,0,0,1,0-.4v-.57c0-.4,0-.79.05-1.17h12l1.08-2.93L76.36,27H64.13a8.69,8.69,0,0,1,3.48-4.43A10.82,10.82,0,0,1,73.55,21a16.47,16.47,0,0,1,4.55.68l.13,0,1.08-3-.15-.05a16.56,16.56,0,0,0-5.3-.81,14.91,14.91,0,0,0-8.42,2.35A11.73,11.73,0,0,0,60.66,27h-2.3l-1.08,2.93.19.19h2.69c0,.16,0,.32,0,.49v1.23c0,.14,0,.29,0,.42h-1.8L57.28,35.3l.19.19h3.21a12.2,12.2,0,0,0,4.48,6.72,12.47,12.47,0,0,0,7.64,2.46A16.44,16.44,0,0,0,79,43.39l.09,0v-3l-.28-.16Z"/></g></svg>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg14"
|
||||
sodipodi:docname="logo.svg"
|
||||
width="150"
|
||||
height="150"
|
||||
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">
|
||||
<sodipodi:namedview
|
||||
id="namedview16"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.78212"
|
||||
inkscape:cx="65.661254"
|
||||
inkscape:cy="75.280419"
|
||||
inkscape:current-layer="svg14" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<style
|
||||
id="style2">.cls-1{fill:#fff;}.cls-2{fill:#3c3d3c;}</style>
|
||||
</defs>
|
||||
<g
|
||||
id="Laag_1"
|
||||
data-name="Laag 1"
|
||||
transform="scale(1.0573395)">
|
||||
<circle
|
||||
class="cls-1"
|
||||
cx="70.870003"
|
||||
cy="70.870003"
|
||||
r="70.870003"
|
||||
id="circle6" />
|
||||
</g>
|
||||
<g
|
||||
id="Laag_2"
|
||||
data-name="Laag 2"
|
||||
transform="scale(1.0573395)">
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 102.39,75 a 18.18,18.18 0 0 0 -3.92,0.43 L 92.87,57 A 7,7 0 0 0 86.1,52 h -5.43 v 2.59 h 5.43 a 4.45,4.45 0 0 1 4.29,3.19 l 1.72,5.66 H 55.54 l -2,-4.89 h 3.72 c 0,0 4.74,-0.78 4.74,-4.41 H 46.39 v 4.33 h 4.35 l 2.55,6.25 -5.62,11.55 a 18.31,18.31 0 1 0 11.33,20 h 8 L 68,95.84 93.33,67.37 96,76.15 a 18.28,18.28 0 1 0 6.4,-1.17 z M 41,109 A 15.72,15.72 0 1 1 46.58,78.6 L 38.89,94.4 40,96.27 H 56.38 A 15.74,15.74 0 0 1 41,109 Z M 56.7,93.67 H 42.07 l 6.8,-14 a 15.71,15.71 0 0 1 7.8,13.56 c 0,0.19 -0.01,0.32 -0.02,0.45 z M 50,77.39 l 4.61,-9.45 10.5,25.74 h -5.87 c 0,-0.13 0,-0.26 0,-0.39 A 18.33,18.33 0 0 0 50,77.39 Z M 67.45,92.56 56.59,66 H 91.13 Z M 102.39,109 A 15.71,15.71 0 0 1 96.74,78.62 l 4.56,15 2.48,-0.76 -4.56,-15 a 15.72,15.72 0 1 1 3.17,31.14 z"
|
||||
id="path9" />
|
||||
<path
|
||||
class="cls-2"
|
||||
d="m 78.72,40.26 a 13.89,13.89 0 0 1 -5.58,1.25 9.86,9.86 0 0 1 -5.6,-1.61 9,9 0 0 1 -3.39,-4.41 h 9.4 l 1.07,-2.89 -0.13,-0.36 h -11 a 2.91,2.91 0 0 1 0,-0.4 v -0.57 c 0,-0.4 0,-0.79 0.05,-1.17 h 12 L 76.62,27.17 76.36,27 H 64.13 a 8.69,8.69 0 0 1 3.48,-4.43 10.82,10.82 0 0 1 5.94,-1.57 16.47,16.47 0 0 1 4.55,0.68 h 0.13 l 1.08,-3 -0.15,-0.05 a 16.56,16.56 0 0 0 -5.3,-0.81 14.91,14.91 0 0 0 -8.42,2.35 11.73,11.73 0 0 0 -4.78,6.83 h -2.3 l -1.08,2.93 0.19,0.19 h 2.69 c 0,0.16 0,0.32 0,0.49 v 1.23 c 0,0.14 0,0.29 0,0.42 h -1.8 l -1.08,3.04 0.19,0.19 h 3.21 a 12.2,12.2 0 0 0 4.48,6.72 12.47,12.47 0 0 0 7.64,2.46 16.44,16.44 0 0 0 6.2,-1.28 h 0.09 v -3 l -0.28,-0.16 z"
|
||||
id="path11" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2.7 KiB |
|
@ -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.",
|
||||
|
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
|
@ -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 <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
|
||||
"de": "Änderungssatz <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
|
||||
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "contributor",
|
||||
"render": {
|
||||
"en": "Change made by <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>",
|
||||
"de": "Geändert von <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>"
|
||||
"en": "Change made by <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "theme",
|
||||
"render": {
|
||||
"en": "Change with theme <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>",
|
||||
"de": "Änderung mit Thema <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
|
||||
"en": "Change with theme <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
|
||||
},
|
||||
"mappings": [
|
||||
{
|
||||
"if": "theme~http.*",
|
||||
"then": {
|
||||
"en": "Change with <b>unofficial</b> theme <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>",
|
||||
"de": "Änderung mit <b>inoffiziellem</b> Thema <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>"
|
||||
"en": "Change with <b>unofficial</b> theme <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -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": "<b>Not</b> made by contributor {search}",
|
||||
"de": "<b> Nicht</b> erstellt von Mitwirkendem {search}"
|
||||
"en": "<b>Not</b> made by contributor {search}"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -388,8 +375,7 @@
|
|||
{
|
||||
"id": "link_to_more",
|
||||
"render": {
|
||||
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>",
|
||||
"de": "Weitere Statistiken finden Sie <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a>"
|
||||
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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<any>{
|
||||
if(!existsSync(path)){
|
||||
throw "File not found: "+path
|
||||
}
|
||||
const root = await xml2js.parseStringPromise(readFileSync(path, "UTF8"))
|
||||
return root.svg
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,50 +20,103 @@ 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<string> {
|
||||
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("<svg") || icon.startsWith("<?xml")) {
|
||||
// This is an svg. Lets create the needed pngs and do some checkes!
|
||||
|
||||
const whiteBackgroundPath = "./assets/generated/theme_"+layout.id+"_white_background.svg"
|
||||
const whiteBackgroundPath = "./assets/generated/images/theme_" + layout.id + "_white_background.svg"
|
||||
{
|
||||
const svg = await ScriptUtils.ReadSvg(icon)
|
||||
const width: string = svg.$.width;
|
||||
|
@ -77,14 +131,15 @@ async function createManifest(layout: LayoutConfig, alreadyWritten: string[]) {
|
|||
let path = layout.icon;
|
||||
if (layout.icon.startsWith("<")) {
|
||||
// THis is already the svg
|
||||
path = "./assets/generated/" + layout.id + "_logo.svg"
|
||||
path = "./assets/generated/images/" + layout.id + "_logo.svg"
|
||||
writeFileSync(path, layout.icon)
|
||||
}
|
||||
|
||||
const sizes = [72, 96, 120, 128, 144, 152, 180, 192, 384, 512];
|
||||
for (const size of sizes) {
|
||||
const name = await createIcon(path, size, alreadyWritten);
|
||||
await createIcon(whiteBackgroundPath, size, alreadyWritten)
|
||||
const whiteIcon = await createIcon(whiteBackgroundPath, size, alreadyWritten)
|
||||
whiteIcons.push(whiteIcon)
|
||||
icons.push({
|
||||
src: name,
|
||||
sizes: size + "x" + size,
|
||||
|
@ -109,7 +164,7 @@ async function createManifest(layout: LayoutConfig, alreadyWritten: string[]) {
|
|||
const ogTitle = Translations.WT(layout.title).txt;
|
||||
const ogDescr = Translations.WT(layout.description ?? "").txt;
|
||||
|
||||
return {
|
||||
const manifest = {
|
||||
name: name,
|
||||
short_name: ogTitle,
|
||||
start_url: `${layout.id.toLowerCase()}.html`,
|
||||
|
@ -121,15 +176,32 @@ async function createManifest(layout: LayoutConfig, alreadyWritten: string[]) {
|
|||
icons: icons,
|
||||
categories: ["map", "navigation"]
|
||||
};
|
||||
return {
|
||||
manifest,
|
||||
whiteIcons
|
||||
}
|
||||
}
|
||||
|
||||
async function createLandingPage(layout: LayoutConfig, manifest) {
|
||||
async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alreadyWritten) {
|
||||
|
||||
Locale.language.setData(layout.language[0]);
|
||||
const targetLanguage = layout.language[0]
|
||||
const ogTitle = Translations.WT(layout.title).textFor(targetLanguage).replace(/"/g, '\\"');
|
||||
const ogDescr = Translations.WT(layout.shortDescription ?? "Easily add and edit geodata with OpenStreetMap").textFor(targetLanguage).replace(/"/g, '\\"');
|
||||
const ogImage = layout.socialImage;
|
||||
let ogImage = layout.socialImage;
|
||||
let twitterImage = ogImage
|
||||
if (ogImage === LayoutConfig.defaultSocialImage && layout.official) {
|
||||
ogImage = await createSocialImage(layout, "") ?? layout.socialImage
|
||||
twitterImage = await createSocialImage(layout, "Wide") ?? layout.socialImage
|
||||
}
|
||||
if (twitterImage.endsWith(".svg")) {
|
||||
// svgs are badly supported as social image, we use a generated svg instead
|
||||
twitterImage = await createIcon(twitterImage, 512, alreadyWritten);
|
||||
}
|
||||
|
||||
if(ogImage.endsWith(".svg")){
|
||||
ogImage = await createIcon(ogImage, 512, alreadyWritten)
|
||||
}
|
||||
|
||||
let customCss = "";
|
||||
if (layout.customCss !== undefined && layout.customCss !== "") {
|
||||
|
@ -147,29 +219,26 @@ async function createLandingPage(layout: LayoutConfig, manifest) {
|
|||
<meta property="og:title" content="${ogTitle}">
|
||||
<meta property="og:description" content="${ogDescr}">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:site" content="@mapcomplete.osm;be">
|
||||
<meta name="twitter:site" content="@mapcomplete.osm.be">
|
||||
<meta name="twitter:creator" content="@pietervdvn">
|
||||
<meta name="twitter:title" content="${ogTitle}">
|
||||
<meta name="twitter:description" content="${ogDescr}">
|
||||
<meta name="twitter:image" content="${ogImage}">`
|
||||
<meta name="twitter:image" content="${twitterImage}">`
|
||||
|
||||
let icon = layout.icon;
|
||||
if (icon.startsWith("<?xml") || icon.startsWith("<svg")) {
|
||||
// This already is an svg
|
||||
icon = `./assets/generated/${layout.id}_icon.svg`
|
||||
icon = `./assets/generated/images/${layout.id}_icon.svg`
|
||||
writeFileSync(icon, layout.icon);
|
||||
}
|
||||
|
||||
const apple_icons = []
|
||||
for (const icon of manifest.icons) {
|
||||
if (icon.type !== "image/png") {
|
||||
continue;
|
||||
}
|
||||
const whiteBgPath = `./assets/generated/generated_theme_${layout.id}_white_background${icon.sizes.substr(icon.sizes.indexOf("x")+ 1)}.png`
|
||||
if(!existsSync(whiteBgPath)){
|
||||
for (const icon of whiteIcons) {
|
||||
if (!existsSync(icon)) {
|
||||
continue
|
||||
}
|
||||
apple_icons.push(`<link rel="apple-touch-icon" sizes="${icon.sizes}" href="${whiteBgPath}">`)
|
||||
const size = icon.replace(/[^0-9]/g, "")
|
||||
apple_icons.push(`<link rel="apple-touch-icon" sizes="${size}x${size}" href="${icon}">`)
|
||||
}
|
||||
|
||||
let themeSpecific = [
|
||||
|
@ -219,6 +288,7 @@ async function main(): Promise<void>{
|
|||
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
|
||||
|
@ -244,21 +314,20 @@ async function main(): Promise<void>{
|
|||
console.log("Could not write manifest for ", layoutName, " because ", err)
|
||||
}
|
||||
};
|
||||
await createManifest(layout, alreadyWritten).then(manifObj => {
|
||||
const manif = JSON.stringify(manifObj, undefined, 2);
|
||||
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, manifObj).then(landing => {
|
||||
createLandingPage(layout, manifest, whiteIcons, alreadyWritten).then(landing => {
|
||||
writeFile(enc(layout.id) + ".html", landing, err)
|
||||
});
|
||||
createIndexFor(layout)
|
||||
}).catch(e => console.log("Could not generate the manifest: ", e))
|
||||
|
||||
}
|
||||
|
||||
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<void>{
|
|||
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);
|
||||
}), alreadyWritten);
|
||||
|
||||
const manif = JSON.stringify(manifest, undefined, 2);
|
||||
writeFileSync("index.manifest", manif)
|
||||
})
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
|
|