Fix #640: generate an icon with a white background automatically
This commit is contained in:
parent
508ef8a970
commit
278fce8726
4 changed files with 103 additions and 83 deletions
|
@ -277,8 +277,6 @@
|
||||||
],
|
],
|
||||||
"id": "bike_repair_station-opening_hours"
|
"id": "bike_repair_station-opening_hours"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
"question": {
|
"question": {
|
||||||
"en": "Who maintains this cycle pump?",
|
"en": "Who maintains this cycle pump?",
|
||||||
|
@ -331,7 +329,6 @@
|
||||||
"render": "<a href='tel:{phone}'>{phone}</a>",
|
"render": "<a href='tel:{phone}'>{phone}</a>",
|
||||||
"id": "bike_repair_station-phone"
|
"id": "bike_repair_station-phone"
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"id": "bike_repair_station-bike-chain-tool",
|
"id": "bike_repair_station-bike-chain-tool",
|
||||||
"question": {
|
"question": {
|
||||||
|
|
|
@ -9,52 +9,52 @@
|
||||||
"orientation": "portrait-primary, landscape-primary",
|
"orientation": "portrait-primary, landscape-primary",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo72.png",
|
"src": "./assets/generated/svg_mapcomplete_logo72.png",
|
||||||
"sizes": "72x72",
|
"sizes": "72x72",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo96.png",
|
"src": "./assets/generated/svg_mapcomplete_logo96.png",
|
||||||
"sizes": "96x96",
|
"sizes": "96x96",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo120.png",
|
"src": "./assets/generated/svg_mapcomplete_logo120.png",
|
||||||
"sizes": "120x120",
|
"sizes": "120x120",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo128.png",
|
"src": "./assets/generated/svg_mapcomplete_logo128.png",
|
||||||
"sizes": "128x128",
|
"sizes": "128x128",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo144.png",
|
"src": "./assets/generated/svg_mapcomplete_logo144.png",
|
||||||
"sizes": "144x144",
|
"sizes": "144x144",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo152.png",
|
"src": "./assets/generated/svg_mapcomplete_logo152.png",
|
||||||
"sizes": "152x152",
|
"sizes": "152x152",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo180.png",
|
"src": "./assets/generated/svg_mapcomplete_logo180.png",
|
||||||
"sizes": "180x180",
|
"sizes": "180x180",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo192.png",
|
"src": "./assets/generated/svg_mapcomplete_logo192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo384.png",
|
"src": "./assets/generated/svg_mapcomplete_logo384.png",
|
||||||
"sizes": "384x384",
|
"sizes": "384x384",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "assets/generated/svg_mapcomplete_logo512.png",
|
"src": "./assets/generated/svg_mapcomplete_logo512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,6 @@ import * as all_known_layouts from "../assets/generated/known_layers_and_themes.
|
||||||
import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson";
|
import {LayoutConfigJson} from "../Models/ThemeConfig/Json/LayoutConfigJson";
|
||||||
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
|
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
|
||||||
import xml2js from 'xml2js';
|
import xml2js from 'xml2js';
|
||||||
import {exec} from "child_process";
|
|
||||||
|
|
||||||
const sharp = require('sharp');
|
const sharp = require('sharp');
|
||||||
const template = readFileSync("theme.html", "utf8");
|
const template = readFileSync("theme.html", "utf8");
|
||||||
|
@ -18,9 +17,7 @@ function enc(str: string): string {
|
||||||
return encodeURIComponent(str.toLowerCase());
|
return encodeURIComponent(str.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
const alreadyWritten = []
|
async function createIcon(iconPath: string, size: number, alreadyWritten: string[]) {
|
||||||
|
|
||||||
async function createIcon(iconPath: string, size: number) {
|
|
||||||
let name = iconPath.split(".").slice(0, -1).join(".");
|
let name = iconPath.split(".").slice(0, -1).join(".");
|
||||||
if (name.startsWith("./")) {
|
if (name.startsWith("./")) {
|
||||||
name = name.substr(2)
|
name = name.substr(2)
|
||||||
|
@ -53,7 +50,7 @@ async function createIcon(iconPath: string, size: number) {
|
||||||
return newname;
|
return newname;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createManifest(layout: LayoutConfig) {
|
async function createManifest(layout: LayoutConfig, alreadyWritten: string[]) {
|
||||||
const name = layout.id;
|
const name = layout.id;
|
||||||
|
|
||||||
Translation.forcedLanguage = "en"
|
Translation.forcedLanguage = "en"
|
||||||
|
@ -64,6 +61,7 @@ async function createManifest(layout: LayoutConfig) {
|
||||||
if (icon.endsWith(".svg") || icon.startsWith("<svg") || icon.startsWith("<?xml")) {
|
if (icon.endsWith(".svg") || icon.startsWith("<svg") || icon.startsWith("<?xml")) {
|
||||||
// This is an svg. Lets create the needed pngs and do some checkes!
|
// This is an svg. Lets create the needed pngs and do some checkes!
|
||||||
|
|
||||||
|
const whiteBackgroundPath = "./assets/generated/theme_"+layout.id+"_white_background.svg"
|
||||||
{
|
{
|
||||||
const svgResult = await xml2js.parseStringPromise(readFileSync(icon, "UTF8"))
|
const svgResult = await xml2js.parseStringPromise(readFileSync(icon, "UTF8"))
|
||||||
const svg = svgResult.svg
|
const svg = svgResult.svg
|
||||||
|
@ -82,7 +80,11 @@ async function createManifest(layout: LayoutConfig) {
|
||||||
}))//*/
|
}))//*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const builder = new xml2js.Builder();
|
||||||
|
const withRect = {rect: {"$":{width, height, style: "fill:#ffffff;"}}, ...svg}
|
||||||
|
const xml = builder.buildObject({svg: withRect});
|
||||||
|
writeFileSync(whiteBackgroundPath, xml)
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = layout.icon;
|
let path = layout.icon;
|
||||||
|
@ -94,9 +96,10 @@ async function createManifest(layout: LayoutConfig) {
|
||||||
|
|
||||||
const sizes = [72, 96, 120, 128, 144, 152, 180, 192, 384, 512];
|
const sizes = [72, 96, 120, 128, 144, 152, 180, 192, 384, 512];
|
||||||
for (const size of sizes) {
|
for (const size of sizes) {
|
||||||
const name = await createIcon(path, size);
|
const name = await createIcon(path, size, alreadyWritten);
|
||||||
|
createIcon(whiteBackgroundPath, size, alreadyWritten)
|
||||||
icons.push({
|
icons.push({
|
||||||
src: name,
|
src: "./"+name,
|
||||||
sizes: size + "x" + size,
|
sizes: size + "x" + size,
|
||||||
type: "image/png"
|
type: "image/png"
|
||||||
})
|
})
|
||||||
|
@ -133,7 +136,6 @@ async function createManifest(layout: LayoutConfig) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function createLandingPage(layout: LayoutConfig, manifest) {
|
async function createLandingPage(layout: LayoutConfig, manifest) {
|
||||||
|
|
||||||
Locale.language.setData(layout.language[0]);
|
Locale.language.setData(layout.language[0]);
|
||||||
|
@ -176,7 +178,7 @@ async function createLandingPage(layout: LayoutConfig, manifest) {
|
||||||
if (icon.type !== "image/png") {
|
if (icon.type !== "image/png") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
apple_icons.push(`<link rel="apple-touch-icon" sizes="${icon.sizes}" href="${icon.src}">`)
|
apple_icons.push(`<link rel="apple-touch-icon" sizes="${icon.sizes}" href="./assets/generated/generated_theme_${layout.id}_white_background${icon.sizes.substr(icon.sizes.indexOf("x")+ 1)}.png">`)
|
||||||
}
|
}
|
||||||
|
|
||||||
let themeSpecific = [
|
let themeSpecific = [
|
||||||
|
@ -211,65 +213,78 @@ async function createIndexFor(theme: LayoutConfig) {
|
||||||
appendFileSync(filename, codeTemplate)
|
appendFileSync(filename, codeTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
const generatedDir = "./assets/generated";
|
function createDir(path){
|
||||||
if (!existsSync(generatedDir)) {
|
if (!existsSync(path)) {
|
||||||
mkdirSync(generatedDir)
|
mkdirSync(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap", "custom", "theme"]
|
async function main(): Promise<void>{
|
||||||
// @ts-ignore
|
|
||||||
const all: LayoutConfigJson[] = all_known_layouts.themes;
|
|
||||||
const args = process.argv
|
const alreadyWritten = []
|
||||||
const theme = args[2]
|
createDir("./assets/generated")
|
||||||
if(theme !== undefined){
|
createDir("./assets/generated/layers")
|
||||||
console.warn("Only generating layout "+theme)
|
createDir("./assets/generated/themes")
|
||||||
}
|
createDir("./assets/generated/white_background")
|
||||||
for (const i in all) {
|
|
||||||
const layoutConfigJson: LayoutConfigJson = all[i]
|
const blacklist = ["", "test", ".", "..", "manifest", "index", "land", "preferences", "account", "openstreetmap", "custom", "theme"]
|
||||||
if(theme !== undefined && layoutConfigJson.id !== theme){
|
// @ts-ignore
|
||||||
continue
|
const all: LayoutConfigJson[] = all_known_layouts.themes;
|
||||||
|
const args = process.argv
|
||||||
|
const theme = args[2]
|
||||||
|
if(theme !== undefined){
|
||||||
|
console.warn("Only generating layout "+theme)
|
||||||
}
|
}
|
||||||
const layout = new LayoutConfig(layoutConfigJson, true, "generating layouts")
|
for (const i in all) {
|
||||||
const layoutName = layout.id
|
const layoutConfigJson: LayoutConfigJson = all[i]
|
||||||
if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) {
|
if(theme !== undefined && layoutConfigJson.id !== theme){
|
||||||
console.log(`Skipping a layout with name${layoutName}, it is on the blacklist`);
|
continue
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const err = err => {
|
|
||||||
if (err !== null) {
|
|
||||||
console.log("Could not write manifest for ", layoutName, " because ", err)
|
|
||||||
}
|
}
|
||||||
};
|
const layout = new LayoutConfig(layoutConfigJson, true, "generating layouts")
|
||||||
createManifest(layout).then(manifObj => {
|
const layoutName = layout.id
|
||||||
|
if (blacklist.indexOf(layoutName.toLowerCase()) >= 0) {
|
||||||
|
console.log(`Skipping a layout with name${layoutName}, it is on the blacklist`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const err = err => {
|
||||||
|
if (err !== null) {
|
||||||
|
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))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
await createManifest(new LayoutConfig({
|
||||||
|
icon: "assets/svg/mapcomplete_logo.svg",
|
||||||
|
id: "index",
|
||||||
|
layers: [],
|
||||||
|
maintainer: "Pieter Vander Vennet",
|
||||||
|
socialImage: "assets/SocialImage.png",
|
||||||
|
startLat: 0,
|
||||||
|
startLon: 0,
|
||||||
|
startZoom: 0,
|
||||||
|
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);
|
const manif = JSON.stringify(manifObj, undefined, 2);
|
||||||
const manifestLocation = encodeURIComponent(layout.id.toLowerCase()) + ".webmanifest";
|
writeFileSync("index.manifest", manif)
|
||||||
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))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createManifest(new LayoutConfig({
|
main().then(() => {
|
||||||
icon: "assets/svg/mapcomplete_logo.svg",
|
console.log("All done!")
|
||||||
id: "index",
|
})
|
||||||
layers: [],
|
|
||||||
maintainer: "Pieter Vander Vennet",
|
|
||||||
socialImage: "assets/SocialImage.png",
|
|
||||||
startLat: 0,
|
|
||||||
startLon: 0,
|
|
||||||
startZoom: 0,
|
|
||||||
title: {en: "MapComplete"},
|
|
||||||
version: Constants.vNumber,
|
|
||||||
description: {en: "A thematic map viewer and editor based on OpenStreetMap"}
|
|
||||||
})).then(manifObj => {
|
|
||||||
const manif = JSON.stringify(manifObj, undefined, 2);
|
|
||||||
writeFileSync("index.manifest", manif)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
console.log("All done!");
|
|
20
test.ts
20
test.ts
|
@ -1,7 +1,15 @@
|
||||||
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
import xml2js from 'xml2js';
|
||||||
import List from "./UI/Base/List";
|
import {readFileSync} from "fs";
|
||||||
import Link from "./UI/Base/Link";
|
|
||||||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
|
||||||
|
|
||||||
const allHidden = AllKnownLayouts.layoutsList.filter(l => l.hideFromOverview)
|
const xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
|
||||||
new List(allHidden.map(th => new Link(new FixedUiElement(th.id), "theme.html?layout=" + th.id))).AttachTo("maindiv")
|
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"375px\" height=\"375px\" viewBox=\"0 0 375 375\" version=\"1.1\">\n" +
|
||||||
|
" <g id=\"surface1\">\n" +
|
||||||
|
" <path style=\" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;\" d=\"M 54.046875 233.558594 C 75.683594 233.558594 93.1875 215.566406 93.1875 193.296875 C 93.1875 171.148438 75.683594 153.148438 54.046875 153.148438 C 32.496094 153.148438 15 171.148438 15 193.296875 C 15 215.558594 32.496094 233.558594 54.046875 233.558594 Z M 273.269531 302.675781 C 275.09375 301.386719 277.5 301.777344 278.828125 303.554688 L 286.066406 313.84375 C 287.296875 315.628906 286.921875 318.195312 285.195312 319.589844 L 232.09375 359.242188 C 230.378906 360.53125 227.878906 360.128906 226.523438 358.359375 L 219.308594 348.066406 C 218.070312 346.28125 218.460938 343.726562 220.175781 342.335938 Z M 213.246094 251.550781 L 192.1875 213.578125 L 181.132812 221.878906 L 202.191406 260.054688 Z M 164.113281 162.847656 L 82.214844 15 L 66.546875 15.105469 L 152.960938 171.253906 Z M 241.222656 241.074219 C 245.851562 237.613281 256.441406 232.5 262.5 232.5 L 337.5 232.5 C 352.304688 232.5 360 247.394531 360 262.53125 C 360 277.753906 352.304688 285 337.5 285 L 270 285 L 188.730469 348.765625 C 160.171875 369.90625 142.859375 346.679688 142.859375 346.679688 L 79.238281 281.210938 C 68.566406 268.066406 70.875 243.046875 83.671875 231.96875 L 171.710938 167.488281 C 180.457031 159.988281 193.441406 161.167969 200.851562 170.0625 C 208.171875 179.0625 207.015625 192.515625 198.253906 200.03125 L 141.890625 242.460938 L 182.386719 283.589844 Z M 241.222656 241.074219 \"/>\n" +
|
||||||
|
" </g>\n" +
|
||||||
|
"</svg>"
|
||||||
|
|
||||||
|
xml2js.parseStringPromise(xml).then(svgResult => {
|
||||||
|
const svg = svgResult.svg
|
||||||
|
const builder = new xml2js.Builder();
|
||||||
|
console.log(builder.buildObject(svg))
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in a new issue