Linting themes, fix userbadges

This commit is contained in:
pietervdvn 2021-10-21 21:41:45 +02:00
parent 9336e19757
commit b9b8a5c71a
27 changed files with 4074 additions and 3903 deletions

View file

@ -124,15 +124,6 @@ export interface LayerConfigJson {
mapRendering: (PointRenderingConfigJson | LineRenderingConfigJson)[] mapRendering: (PointRenderingConfigJson | LineRenderingConfigJson)[]
/**
* Wayhandling: should a way/area be displayed as:
* 0) The way itself
* 1) Only the centerpoint
* 2) The centerpoint and the way
*/
wayHandling?: number;
/** /**
* If set, this layer will pass all the features it receives onto the next layer. * If set, this layer will pass all the features it receives onto the next layer.
* This is ideal for decoration, e.g. directionss on cameras * This is ideal for decoration, e.g. directionss on cameras

View file

@ -31,14 +31,12 @@ export default interface PointRenderingConfigJson {
icon?: string | TagRenderingConfigJson; icon?: string | TagRenderingConfigJson;
/** /**
* IconsOverlays are a list of extra icons/badges to overlay over the icon. * A list of extra badges to show next to the icon as small badge
* The 'badge'-toggle changes their behaviour. * They will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.
* If badge is set, it will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout.
* If badges is false, it'll be a simple overlay
* *
* Note: strings are interpreted as icons, so layering and substituting is supported * Note: strings are interpreted as icons, so layering and substituting is supported. You can use `circle:white;./my_icon.svg` to add a background circle
*/ */
iconOverlays?: { if: string | AndOrTagConfigJson, then: string | TagRenderingConfigJson, badge?: boolean }[] iconBadges?: { if: string | AndOrTagConfigJson, then: string | TagRenderingConfigJson }[]
/** /**

View file

@ -20,9 +20,6 @@ import PointRenderingConfigJson from "./Json/PointRenderingConfigJson";
import LineRenderingConfigJson from "./Json/LineRenderingConfigJson"; import LineRenderingConfigJson from "./Json/LineRenderingConfigJson";
export default class LayerConfig extends WithContextLoader{ export default class LayerConfig extends WithContextLoader{
static WAYHANDLING_DEFAULT = 0;
static WAYHANDLING_CENTER_ONLY = 1;
static WAYHANDLING_CENTER_AND_WAY = 2;
id: string; id: string;
name: Translation; name: Translation;
@ -41,7 +38,6 @@ export default class LayerConfig extends WithContextLoader{
public readonly mapRendering: PointRenderingConfig[] public readonly mapRendering: PointRenderingConfig[]
public readonly lineRendering: LineRenderingConfig[] public readonly lineRendering: LineRenderingConfig[]
wayHandling: number;
public readonly units: Unit[]; public readonly units: Unit[];
public readonly deletion: DeleteConfig | null; public readonly deletion: DeleteConfig | null;
public readonly allowMove: MoveConfig | null public readonly allowMove: MoveConfig | null
@ -153,7 +149,6 @@ export default class LayerConfig extends WithContextLoader{
this.passAllFeatures = json.passAllFeatures ?? false; this.passAllFeatures = json.passAllFeatures ?? false;
this.minzoom = json.minzoom ?? 0; this.minzoom = json.minzoom ?? 0;
this.minzoomVisible = json.minzoomVisible ?? this.minzoom; this.minzoomVisible = json.minzoomVisible ?? this.minzoom;
this.wayHandling = json.wayHandling ?? 0;
if (json.presets !== undefined && json.presets?.map === undefined) { if (json.presets !== undefined && json.presets?.map === undefined) {
throw "Presets should be a list of items (at " + context + ")" throw "Presets should be a list of items (at " + context + ")"
} }

View file

@ -16,7 +16,7 @@ import {VariableUiElement} from "../../UI/Base/VariableUIElement";
export default class PointRenderingConfig extends WithContextLoader { export default class PointRenderingConfig extends WithContextLoader {
public readonly icon: TagRenderingConfig; public readonly icon: TagRenderingConfig;
public readonly iconOverlays: { if: TagsFilter; then: TagRenderingConfig; badge: boolean }[]; public readonly iconBadges: { if: TagsFilter; then: TagRenderingConfig }[];
public readonly iconSize: TagRenderingConfig; public readonly iconSize: TagRenderingConfig;
public readonly label: TagRenderingConfig; public readonly label: TagRenderingConfig;
public readonly rotation: TagRenderingConfig; public readonly rotation: TagRenderingConfig;
@ -24,21 +24,20 @@ export default class PointRenderingConfig extends WithContextLoader {
constructor(json: PointRenderingConfigJson, context: string) { constructor(json: PointRenderingConfigJson, context: string) {
super(json, context) super(json, context)
this.icon = this.tr("icon", ""); this.icon = this.tr("icon", "");
this.iconOverlays = (json.iconOverlays ?? []).map((overlay, i) => { this.iconBadges = (json.iconBadges ?? []).map((overlay, i) => {
let tr = new TagRenderingConfig( let tr : TagRenderingConfig;
overlay.then, if (typeof overlay.then === "string" &&
`iconoverlays.${i}` SharedTagRenderings.SharedIcons.get(overlay.then) !== undefined) {
);
if (
typeof overlay.then === "string" &&
SharedTagRenderings.SharedIcons.get(overlay.then) !== undefined
) {
tr = SharedTagRenderings.SharedIcons.get(overlay.then); tr = SharedTagRenderings.SharedIcons.get(overlay.then);
}else{
tr = new TagRenderingConfig(
overlay.then,
`iconBadges.${i}`
);
} }
return { return {
if: TagUtils.Tag(overlay.if), if: TagUtils.Tag(overlay.if),
then: tr, then: tr
badge: overlay.badge ?? false,
}; };
}); });
@ -50,7 +49,7 @@ export default class PointRenderingConfig extends WithContextLoader {
} }
} }
this.iconSize = this.tr("iconSize", "40,40,center"); this.iconSize = this.tr("iconSize", "40,40,center");
this.label = this.tr("label", ""); this.label = this.tr("label", undefined);
this.rotation = this.tr("rotation", "0"); this.rotation = this.tr("rotation", "0");
} }
@ -59,7 +58,7 @@ export default class PointRenderingConfig extends WithContextLoader {
const parts: Set<string>[] = []; const parts: Set<string>[] = [];
parts.push(this.icon?.ExtractImages(true)); parts.push(this.icon?.ExtractImages(true));
parts.push( parts.push(
...this.iconOverlays?.map((overlay) => overlay.then.ExtractImages(true)) ...this.iconBadges?.map((overlay) => overlay.then.ExtractImages(true))
); );
const allIcons = new Set<string>(); const allIcons = new Set<string>();
@ -69,21 +68,115 @@ export default class PointRenderingConfig extends WithContextLoader {
return allIcons; return allIcons;
} }
/**
* Given a single HTML spec (either a single image path OR "image_path_to_known_svg:fill-colour", returns a fixedUIElement containing that
* The element will fill 100% and be positioned absolutely with top:0 and left: 0
*/
private static FromHtmlSpec(htmlSpec: string, style: string, isBadge = false): BaseUIElement {
if (htmlSpec === undefined) {
return undefined;
}
const match = htmlSpec.match(/([a-zA-Z0-9_]*):([^;]*)/);
if (match !== null && Svg.All[match[1] + ".svg"] !== undefined) {
const svg = (Svg.All[match[1] + ".svg"] as string)
const targetColor = match[2]
const img = new Img(svg.replace(/#000000/g, targetColor), true)
.SetStyle(style)
if(isBadge){
img.SetClass("badge")
}
return img
} else {
return new FixedUiElement(`<img src="${htmlSpec}" style="${style}" />`);
}
}
private static FromHtmlMulti(multiSpec: string, rotation: string , isBadge: boolean, defaultElement: BaseUIElement = undefined){
if(multiSpec === undefined){
return defaultElement
}
const style = `width:100%;height:100%;transform: rotate( ${rotation} );display:block;position: absolute; top: 0; left: 0`;
const htmlDefs = multiSpec.trim()?.split(";") ?? []
const elements = Utils.NoEmpty(htmlDefs).map(def => PointRenderingConfig.FromHtmlSpec(def, style, isBadge))
if (elements.length === 0) {
return defaultElement
} else {
return new Combine(elements).SetClass("relative block w-full h-full")
}
}
public GetSimpleIcon(tags: UIEventSource<any>): BaseUIElement {
const self = this;
if (this.icon === undefined) {
return undefined;
}
return new VariableUiElement(tags.map(tags => {
const rotation = self.rotation?.GetRenderValue(tags)?.txt ?? "0deg"
const htmlDefs = self.icon.GetRenderValue(tags)?.txt
let defaultPin : BaseUIElement = undefined
if(self.label === undefined){
defaultPin = Svg.teardrop_with_hole_green_svg()
}
return PointRenderingConfig.FromHtmlMulti(htmlDefs, rotation,false, defaultPin)
})).SetClass("w-full h-full block")
}
private GetBadges(tags: UIEventSource<any>): BaseUIElement {
if (this.iconBadges.length === 0) {
return undefined
}
return new VariableUiElement(
tags.map(tags => {
const badgeElements = this.iconBadges.map(badge => {
if (!badge.if.matchesProperties(tags)) {
// Doesn't match...
return undefined
}
const htmlDefs = badge.then.GetRenderValue(tags)?.txt
const badgeElement= PointRenderingConfig.FromHtmlMulti(htmlDefs, "0", true)?.SetClass("block relative")
if(badgeElement === undefined){
return undefined;
}
return new Combine([badgeElement]).SetStyle("width: 1.5rem").SetClass("block")
})
return new Combine(badgeElements).SetClass("inline-flex h-full")
})).SetClass("absolute bottom-0 right-1/3 h-1/2 w-0")
}
private GetLabel(tags: UIEventSource<any>): BaseUIElement {
if (this.label === undefined) {
return undefined;
}
const self = this;
return new VariableUiElement(tags.map(tags => {
const label = self.label
?.GetRenderValue(tags)
?.Subs(tags)
?.SetClass("block text-center")
return new Combine([label]).SetClass("flex flex-col items-center mt-1")
}))
}
public GenerateLeafletStyle( public GenerateLeafletStyle(
tags: UIEventSource<any>, tags: UIEventSource<any>,
clickable: boolean clickable: boolean
): ):
{ {
html: BaseUIElement; html: BaseUIElement;
iconSize: [number, number]; iconSize: [number, number];
iconAnchor: [number, number]; iconAnchor: [number, number];
popupAnchor: [number, number]; popupAnchor: [number, number];
iconUrl: string; iconUrl: string;
className: string; className: string;
} } {
{
function num(str, deflt = 40) { function num(str, deflt = 40) {
const n = Number(str); const n = Number(str);
if (isNaN(n)) { if (isNaN(n)) {
@ -122,113 +215,22 @@ export default class PointRenderingConfig extends WithContextLoader {
anchorH = iconH; anchorH = iconH;
} }
const iconUrlStatic = render(this.icon);
const self = this;
function genHtmlFromString(sourcePart: string, rotation: string): BaseUIElement { const iconAndBadges = new Combine([this.GetSimpleIcon(tags), this.GetBadges(tags)])
const style = `width:100%;height:100%;transform: rotate( ${rotation} );display:block;position: absolute; top: 0; left: 0`; .SetStyle(`width: ${iconW}px; height: ${iconH}px`)
let html: BaseUIElement = new FixedUiElement( .SetClass("block relative")
`<img src="${sourcePart}" style="${style}" />`
);
const match = sourcePart.match(/([a-zA-Z0-9_]*):([^;]*)/);
if (match !== null && Svg.All[match[1] + ".svg"] !== undefined) {
html = new Img(
(Svg.All[match[1] + ".svg"] as string).replace(
/#000000/g,
match[2]
),
true
).SetStyle(style);
}
return html;
}
const mappedHtml = tags?.map((tgs) => {
// What do you mean, 'tgs' is never read?
// It is read implicitly in the 'render' method
const iconUrl = render(self.icon);
const rotation = render(self.rotation, "0deg");
let htmlParts: BaseUIElement[] = [];
let sourceParts = Utils.NoNull(
iconUrl.split(";").filter((prt) => prt != "")
);
for (const sourcePart of sourceParts) {
htmlParts.push(genHtmlFromString(sourcePart, rotation));
}
let badges = [];
for (const iconOverlay of self.iconOverlays) {
if (!iconOverlay.if.matchesProperties(tgs)) {
continue;
}
if (iconOverlay.badge) {
const badgeParts: BaseUIElement[] = [];
const renderValue = iconOverlay
.then
.GetRenderValue(tgs)
if (renderValue === undefined) {
continue;
}
const partDefs = renderValue.txt.split(";")
.filter((prt) => prt != "");
for (const badgePartStr of partDefs) {
badgeParts.push(genHtmlFromString(badgePartStr, "0"));
}
const badgeCompound = new Combine(badgeParts).SetStyle(
"display:flex;position:relative;width:100%;height:100%;"
);
badges.push(badgeCompound);
} else {
htmlParts.push(
genHtmlFromString(iconOverlay.then.GetRenderValue(tgs).txt, "0")
);
}
}
if (badges.length > 0) {
const badgesComponent = new Combine(badges).SetStyle(
"display:flex;height:50%;width:100%;position:absolute;top:50%;left:50%;"
);
htmlParts.push(badgesComponent);
}
if (sourceParts.length == 0) {
iconH = 0;
}
try {
const label = self.label
?.GetRenderValue(tgs)
?.Subs(tgs)
?.SetClass("block text-center")
?.SetStyle("margin-top: " + (iconH + 2) + "px");
if (label !== undefined) {
htmlParts.push(
new Combine([label]).SetClass("flex flex-col items-center")
);
}
} catch (e) {
console.error(e, tgs);
}
return new Combine(htmlParts);
});
return { return {
html: mappedHtml === undefined ? new FixedUiElement(self.icon.render.txt) : new VariableUiElement(mappedHtml), html: new Combine([iconAndBadges, this.GetLabel(tags)]).SetStyle("flex flex-col"),
iconSize: [iconW, iconH], iconSize: [iconW, iconH],
iconAnchor: [anchorW, anchorH], iconAnchor: [anchorW, anchorH],
popupAnchor: [0, 3 - anchorH], popupAnchor: [0, 3 - anchorH],
iconUrl: iconUrlStatic, iconUrl: undefined,
className: clickable className: clickable
? "leaflet-div-icon" ? "leaflet-div-icon"
: "leaflet-div-icon unclickable", : "leaflet-div-icon unclickable",
}; };
} }
} }

View file

@ -246,11 +246,6 @@ export default class TagRenderingConfig {
return false; return false;
} }
public IsQuestionBoxElement(): boolean {
return this.question === null && this.condition === null;
}
/** /**
* Gets all the render values. Will return multiple render values if 'multianswer' is enabled. * Gets all the render values. Will return multiple render values if 'multianswer' is enabled.
* The result will equal [GetRenderValue] if not 'multiAnswer' * The result will equal [GetRenderValue] if not 'multiAnswer'
@ -295,7 +290,7 @@ export default class TagRenderingConfig {
* Not compatible with multiAnswer - use GetRenderValueS instead in that case * Not compatible with multiAnswer - use GetRenderValueS instead in that case
* @constructor * @constructor
*/ */
public GetRenderValue(tags: any): Translation { public GetRenderValue(tags: any, defltValue: any = undefined): Translation {
if (this.mappings !== undefined && !this.multiAnswer) { if (this.mappings !== undefined && !this.multiAnswer) {
for (const mapping of this.mappings) { for (const mapping of this.mappings) {
if (mapping.if === undefined) { if (mapping.if === undefined) {
@ -315,7 +310,7 @@ export default class TagRenderingConfig {
if (tags[this.freeform.key] !== undefined) { if (tags[this.freeform.key] !== undefined) {
return this.render; return this.render;
} }
return undefined; return defltValue;
} }
public ExtractImages(isIcon: boolean): Set<string> { public ExtractImages(isIcon: boolean): Set<string> {

View file

@ -269,13 +269,11 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": "service:bicycle:pump=yes", "if": "service:bicycle:pump=yes",
"then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg", "then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg"
"badge": true
} }
], ],
"width": { "width": {
@ -293,16 +291,14 @@
"icon": { "icon": {
"render": "pin:#22ff55;./assets/layers/bicycle_library/bicycle_library.svg" "render": "pin:#22ff55;./assets/layers/bicycle_library/bicycle_library.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": "service:bicycle:pump=yes", "if": "service:bicycle:pump=yes",
"then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg", "then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -48,8 +48,7 @@
"operational_status=closed" "operational_status=closed"
] ]
}, },
"then": "close:#c33", "then": "close:#c33"
"badge": true
} }
], ],
"iconSize": "50,50,bottom", "iconSize": "50,50,bottom",
@ -282,7 +281,7 @@
"icon": { "icon": {
"render": "pin:#ffffff;./assets/layers/bicycle_tube_vending_machine/pinIcon.svg" "render": "pin:#ffffff;./assets/layers/bicycle_tube_vending_machine/pinIcon.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": { "if": {
"or": [ "or": [
@ -290,8 +289,7 @@
"operational_status=closed" "operational_status=closed"
] ]
}, },
"then": "close:#c33", "then": "close:#c33"
"badge": true
} }
], ],
"iconSize": "50,50,bottom", "iconSize": "50,50,bottom",

View file

@ -81,8 +81,7 @@
"then": { "then": {
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg", "render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg",
"roaming": true "roaming": true
}, }
"badge": true
} }
], ],
"titleIcons": [ "titleIcons": [
@ -168,7 +167,7 @@
"icon": { "icon": {
"render": "./assets/layers/bike_cleaning/bike_cleaning.svg" "render": "./assets/layers/bike_cleaning/bike_cleaning.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": { "if": {
"and": [ "and": [
@ -179,8 +178,7 @@
"then": { "then": {
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg", "render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg",
"roaming": true "roaming": true
}, }
"badge": true
} }
], ],
"iconSize": "50,50,bottom", "iconSize": "50,50,bottom",

View file

@ -673,8 +673,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "operator=De Fietsambassade Gent", "if": "operator=De Fietsambassade Gent",
"then": "./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg", "then": "./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg"
"badge": true
} }
], ],
"iconSize": { "iconSize": {
@ -826,11 +825,10 @@
} }
] ]
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "operator=De Fietsambassade Gent", "if": "operator=De Fietsambassade Gent",
"then": "./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg", "then": "./assets/themes/cyclofix/fietsambassade_gent_logo_small.svg"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -723,13 +723,11 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": "service:bicycle:pump=yes", "if": "service:bicycle:pump=yes",
"then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg", "then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg"
"badge": true
}, },
{ {
"if": { "if": {
@ -739,8 +737,7 @@
}, },
"then": { "then": {
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg" "render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg"
}, }
"badge": true
} }
], ],
"width": { "width": {
@ -768,16 +765,14 @@
} }
] ]
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": "service:bicycle:pump=yes", "if": "service:bicycle:pump=yes",
"then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg", "then": "circle:#e2783d;./assets/layers/bike_repair_station/pump.svg"
"badge": true
}, },
{ {
"if": { "if": {
@ -787,8 +782,7 @@
}, },
"then": { "then": {
"render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg" "render": "./assets/layers/bike_cleaning/bike_cleaning_icon.svg"
}, }
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -28,8 +28,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"label": { "label": {
@ -215,11 +214,10 @@
} }
] ]
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"label": { "label": {

File diff suppressed because it is too large Load diff

View file

@ -33,8 +33,7 @@
"operational_status=closed" "operational_status=closed"
] ]
}, },
"then": "close:#c33", "then": "close:#c33"
"badge": true
} }
], ],
"iconSize": "40,40,bottom", "iconSize": "40,40,bottom",
@ -185,7 +184,7 @@
"icon": { "icon": {
"render": "pin:#6BC4F7;./assets/layers/drinking_water/drips.svg" "render": "pin:#6BC4F7;./assets/layers/drinking_water/drips.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": { "if": {
"or": [ "or": [
@ -193,8 +192,7 @@
"operational_status=closed" "operational_status=closed"
] ]
}, },
"then": "close:#c33", "then": "close:#c33"
"badge": true
} }
], ],
"iconSize": "40,40,bottom", "iconSize": "40,40,bottom",

View file

@ -35,8 +35,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": { "if": {
@ -47,8 +46,7 @@
}, },
"then": { "then": {
"render": "circle:white;./assets/themes/fritures/Vegetarian-mark.svg" "render": "circle:white;./assets/themes/fritures/Vegetarian-mark.svg"
}, }
"badge": true
} }
], ],
"label": { "label": {
@ -656,11 +654,10 @@
} }
] ]
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": { "if": {
@ -671,8 +668,7 @@
}, },
"then": { "then": {
"render": "circle:white;./assets/themes/fritures/Vegetarian-mark.svg" "render": "circle:white;./assets/themes/fritures/Vegetarian-mark.svg"
}, }
"badge": true
} }
], ],
"label": { "label": {

View file

@ -482,8 +482,7 @@
"opening_hours~*" "opening_hours~*"
] ]
}, },
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"width": { "width": {
@ -541,7 +540,7 @@
"icon": { "icon": {
"render": "./assets/themes/playgrounds/playground.svg" "render": "./assets/themes/playgrounds/playground.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": { "if": {
"and": [ "and": [
@ -549,8 +548,7 @@
"opening_hours~*" "opening_hours~*"
] ]
}, },
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -45,7 +45,7 @@
] ]
}, },
"icon": { "icon": {
"render": "./assets/themes/bookcases/bookcase.svg;" "render": "./assets/themes/bookcases/bookcase.svg"
}, },
"label": { "label": {
"mappings": [ "mappings": [

View file

@ -279,8 +279,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"width": { "width": {
@ -328,11 +327,10 @@
"icon": { "icon": {
"render": "./assets/themes/shops/shop.svg" "render": "./assets/themes/shops/shop.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -420,8 +420,7 @@
"opening_hours~*" "opening_hours~*"
] ]
}, },
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": { "if": {
@ -431,8 +430,7 @@
"access=no" "access=no"
] ]
}, },
"then": "circle:white;./assets/layers/sport_pitch/lock.svg", "then": "circle:white;./assets/layers/sport_pitch/lock.svg"
"badge": true
} }
], ],
"width": { "width": {
@ -514,7 +512,7 @@
} }
] ]
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": { "if": {
"and": [ "and": [
@ -522,8 +520,7 @@
"opening_hours~*" "opening_hours~*"
] ]
}, },
"then": "isOpen", "then": "isOpen"
"badge": true
}, },
{ {
"if": { "if": {
@ -533,8 +530,7 @@
"access=no" "access=no"
] ]
}, },
"then": "circle:white;./assets/layers/sport_pitch/lock.svg", "then": "circle:white;./assets/layers/sport_pitch/lock.svg"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -1411,6 +1411,26 @@
"https://www.onlinewebfonts.com/icon/197818" "https://www.onlinewebfonts.com/icon/197818"
] ]
}, },
{
"path": "teardrop_with_hole_green.svg",
"license": "CC-BY-SA 3.0 Unported",
"authors": [
"Mono, derivated work User:Benoit Rochon"
],
"sources": [
"https://commons.wikimedia.org/wiki/File:Map_pin_icon_green.svg"
]
},
{
"path": "teardrop.svg",
"license": "CC-BY-SA 3.0 Unported",
"authors": [
"Mono, derivated work User:Benoit Rochon"
],
"sources": [
"https://commons.wikimedia.org/wiki/File:Map_pin_icon_green.svg"
]
},
{ {
"path": "translate.svg", "path": "translate.svg",
"license": "CC-BY-SA 3.0", "license": "CC-BY-SA 3.0",
@ -1503,4 +1523,4 @@
"https://www.wikipedia.org/" "https://www.wikipedia.org/"
] ]
} }
] ]

104
assets/svg/teardrop.svg Normal file
View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 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"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2816"
version="1.1"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
width="94"
height="128"
sodipodi:docname="teardrop.svg">
<metadata
id="metadata2822">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs2820">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective2824" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1003"
id="namedview2818"
showgrid="false"
inkscape:zoom="3.0991164"
inkscape:cx="-71.403124"
inkscape:cy="60.493358"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2816" />
<path
style="fill:#000000;fill-opacity:0.98823529"
d="M 46.977003,126.64334 C 46.693972,125.95584 40.813862,120.20567 36.603071,114.98067 11.655836,81.858372 -16.158365,51.082905 16.319943,13.682837 30.700637,-0.21083367 48.43303,-1.0034227 66.662563,5.4726973 117.9922,35.174601 80.828906,83.627914 56.427079,115.48067 l -9.450076,11.16267 z M 62.417383,75.872046 C 96.654166,51.387445 70.185413,4.2391813 32.569429,19.913013 21.585178,25.769872 16.134954,35.960547 15.944071,47.980664 c -0.524495,11.693153 5.685418,21.471037 15.526227,27.460808 7.055481,3.840074 10.157178,4.533661 18.145697,4.057654 5.177622,-0.308516 8.161127,-1.153847 12.801388,-3.62708 z"
id="path4127"
sodipodi:nodetypes="ccccccccccsc" />
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none"
id="path4129"
sodipodi:cx="52.363636"
sodipodi:cy="49.05526"
sodipodi:rx="51.222816"
sodipodi:ry="41.754009"
d="m 41.682107,89.891342 a 51.222816,41.754009 0 1 1 1.276617,0.208091"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="matrix(0.87829487,0,0,1.0519028,0.55474126,-6.9952658)" />
<path
sodipodi:type="arc"
style="opacity:0.34016395;fill:#000000;fill-opacity:0;fill-rule:nonzero;stroke:none"
id="path4131"
sodipodi:cx="49.05526"
sodipodi:cy="48.59893"
sodipodi:rx="26.010695"
sodipodi:ry="20.991087"
d="m 43.631232,69.128546 a 26.010695,20.991087 0 1 1 0.64826,0.104614"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="translate(0.64534523,0)" />
<path
sodipodi:type="arc"
style="fill:#000080;fill-opacity:0;fill-rule:nonzero;stroke:none"
id="path4135"
sodipodi:cx="35.365417"
sodipodi:cy="102.78788"
sodipodi:rx="16.655972"
sodipodi:ry="11.750445"
d="m 31.892136,114.28 a 16.655972,11.750445 0 1 1 0.415114,0.0586"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="translate(0.64534523,0)" />
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 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"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg2816"
version="1.1"
inkscape:version="0.91 r13725"
width="94"
height="128"
sodipodi:docname="Map_pin_icon_green.svg">
<metadata
id="metadata2822">
<rdf:RDF>
<cc:Work
rdf:about="">
<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>
<defs
id="defs2820">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
id="perspective2824" />
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview2818"
showgrid="false"
inkscape:zoom="3.0991164"
inkscape:cx="-5.0939007"
inkscape:cy="60.493358"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2816" />
<path
style="fill:#008000;fill-opacity:0.98823529"
d="M 46.977003,126.64334 C 46.693972,125.95584 40.813862,120.20567 36.603071,114.98067 11.655836,81.858372 -16.158365,51.082905 16.319943,13.682837 30.700637,-0.21083367 48.43303,-1.0034227 66.662563,5.4726973 117.9922,35.174601 80.828906,83.627914 56.427079,115.48067 l -9.450076,11.16267 z M 62.417383,75.872046 C 96.654166,51.387445 70.185413,4.2391813 32.569429,19.913013 21.585178,25.769872 16.134954,35.960547 15.944071,47.980664 c -0.524495,11.693153 5.685418,21.471037 15.526227,27.460808 7.055481,3.840074 10.157178,4.533661 18.145697,4.057654 5.177622,-0.308516 8.161127,-1.153847 12.801388,-3.62708 z"
id="path4127"
sodipodi:nodetypes="ccccccccccsc" />
<path
sodipodi:type="arc"
style="fill:#008000;fill-opacity:0.98823529;fill-rule:nonzero;stroke:none"
id="path4129"
sodipodi:cx="52.363636"
sodipodi:cy="49.05526"
sodipodi:rx="51.222816"
sodipodi:ry="41.754009"
d="m 41.682107,89.891342 a 51.222816,41.754009 0 1 1 1.276617,0.208091"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="matrix(0.87829487,0,0,1.0519028,0.55474126,-6.9952658)" />
<path
sodipodi:type="arc"
style="opacity:0.34016395;fill:#000000;fill-opacity:0;fill-rule:nonzero;stroke:none"
id="path4131"
sodipodi:cx="49.05526"
sodipodi:cy="48.59893"
sodipodi:rx="26.010695"
sodipodi:ry="20.991087"
d="m 43.631232,69.128546 a 26.010695,20.991087 0 1 1 0.64826,0.104614"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="translate(0.64534523,0)" />
<path
sodipodi:type="arc"
style="fill:#000080;fill-opacity:0;fill-rule:nonzero;stroke:none"
id="path4135"
sodipodi:cx="35.365417"
sodipodi:cy="102.78788"
sodipodi:rx="16.655972"
sodipodi:ry="11.750445"
d="m 31.892136,114.28 a 16.655972,11.750445 0 1 1 0.415114,0.0586"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="translate(0.64534523,0)" />
<path
sodipodi:type="arc"
style="fill:#009400;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path4149"
sodipodi:cx="52.705883"
sodipodi:cy="52.021389"
sodipodi:rx="34.452763"
sodipodi:ry="33.540108"
d="m 45.521425,84.824145 a 34.452763,33.540108 0 1 1 0.85866,0.167155"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="matrix(0.97020484,0,0,1.0272058,-4.0587829,-5.7503824)" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path4184"
sodipodi:cx="64.211853"
sodipodi:cy="68.789574"
sodipodi:rx="34.203297"
sodipodi:ry="36.623341"
d="m 57.079416,104.60778 a 34.203297,36.623341 0 1 1 0.852443,0.18252"
sodipodi:start="1.7808687"
sodipodi:end="8.0386371"
sodipodi:open="true"
transform="matrix(0.64629924,0,0,0.61681122,5.1261236,4.9013803)" />
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -156,8 +156,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"width": { "width": {
@ -221,11 +220,10 @@
"icon": { "icon": {
"render": "./assets/themes/climbing/club.svg" "render": "./assets/themes/climbing/club.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"iconSize": { "iconSize": {
@ -325,8 +323,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"width": "0", "width": "0",
@ -339,11 +336,10 @@
"icon": { "icon": {
"render": "./assets/themes/climbing/climbing_gym.svg" "render": "./assets/themes/climbing/climbing_gym.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -84,33 +84,27 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "plant~.*vine.*", "if": "plant~.*vine.*",
"then": "circle:white;./assets/themes/facadegardens/klimplant.svg", "then": "circle:white;./assets/themes/facadegardens/klimplant.svg"
"badge": true
}, },
{ {
"if": "plant~.*groundcover.*", "if": "plant~.*groundcover.*",
"then": "circle:white;./assets/themes/facadegardens/bodembedekker.svg", "then": "circle:white;./assets/themes/facadegardens/bodembedekker.svg"
"badge": true
}, },
{ {
"if": "edible=true", "if": "edible=true",
"then": "circle:white;./assets/themes/facadegardens/eetbaar.svg", "then": "circle:white;./assets/themes/facadegardens/eetbaar.svg"
"badge": true
}, },
{ {
"if": "rain_barel=yes", "if": "rain_barel=yes",
"then": "circle:white;./assets/themes/facadegardens/gevelton.svg", "then": "circle:white;./assets/themes/facadegardens/gevelton.svg"
"badge": true
}, },
{ {
"if": "plant~.*shrub.*", "if": "plant~.*shrub.*",
"then": "circle:white;./assets/themes/facadegardens/struik.svg", "then": "circle:white;./assets/themes/facadegardens/struik.svg"
"badge": true
}, },
{ {
"if": "plant~.*flower.*", "if": "plant~.*flower.*",
"then": "circle:white;./assets/themes/facadegardens/bloei.svg", "then": "circle:white;./assets/themes/facadegardens/bloei.svg"
"badge": true
} }
], ],
"tagRenderings": [ "tagRenderings": [
@ -486,36 +480,30 @@
} }
] ]
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "plant~.*vine.*", "if": "plant~.*vine.*",
"then": "circle:white;./assets/themes/facadegardens/klimplant.svg", "then": "circle:white;./assets/themes/facadegardens/klimplant.svg"
"badge": true
}, },
{ {
"if": "plant~.*groundcover.*", "if": "plant~.*groundcover.*",
"then": "circle:white;./assets/themes/facadegardens/bodembedekker.svg", "then": "circle:white;./assets/themes/facadegardens/bodembedekker.svg"
"badge": true
}, },
{ {
"if": "edible=true", "if": "edible=true",
"then": "circle:white;./assets/themes/facadegardens/eetbaar.svg", "then": "circle:white;./assets/themes/facadegardens/eetbaar.svg"
"badge": true
}, },
{ {
"if": "rain_barel=yes", "if": "rain_barel=yes",
"then": "circle:white;./assets/themes/facadegardens/gevelton.svg", "then": "circle:white;./assets/themes/facadegardens/gevelton.svg"
"badge": true
}, },
{ {
"if": "plant~.*shrub.*", "if": "plant~.*shrub.*",
"then": "circle:white;./assets/themes/facadegardens/struik.svg", "then": "circle:white;./assets/themes/facadegardens/struik.svg"
"badge": true
}, },
{ {
"if": "plant~.*flower.*", "if": "plant~.*flower.*",
"then": "circle:white;./assets/themes/facadegardens/bloei.svg", "then": "circle:white;./assets/themes/facadegardens/bloei.svg"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -154,8 +154,7 @@
"iconOverlays": [ "iconOverlays": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"width": { "width": {
@ -196,11 +195,10 @@
"icon": { "icon": {
"render": "square:white;./assets/themes/postboxes/post_office.svg" "render": "square:white;./assets/themes/postboxes/post_office.svg"
}, },
"iconOverlays": [ "iconBadges": [
{ {
"if": "opening_hours~*", "if": "opening_hours~*",
"then": "isOpen", "then": "isOpen"
"badge": true
} }
], ],
"iconSize": { "iconSize": {

View file

@ -748,6 +748,14 @@ video {
right: 0.75rem; right: 0.75rem;
} }
.bottom-0 {
bottom: 0px;
}
.right-1\/3 {
right: 33.333333%;
}
.top-0 { .top-0 {
top: 0px; top: 0px;
} }
@ -760,10 +768,6 @@ video {
right: 0px; right: 0px;
} }
.bottom-0 {
bottom: 0px;
}
.isolate { .isolate {
isolation: isolate; isolation: isolate;
} }
@ -856,6 +860,10 @@ video {
margin-left: 0.75rem; margin-left: 0.75rem;
} }
.mt-1 {
margin-top: 0.25rem;
}
.mb-2 { .mb-2 {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
@ -884,10 +892,6 @@ video {
margin-bottom: 2.5rem; margin-bottom: 2.5rem;
} }
.mt-1 {
margin-top: 0.25rem;
}
.mt-0 { .mt-0 {
margin-top: 0px; margin-top: 0px;
} }
@ -988,6 +992,10 @@ video {
height: 2rem; height: 2rem;
} }
.h-1\/2 {
height: 50%;
}
.h-12 { .h-12 {
height: 3rem; height: 3rem;
} }
@ -1048,6 +1056,10 @@ video {
width: 2rem; width: 2rem;
} }
.w-0 {
width: 0px;
}
.w-12 { .w-12 {
width: 3rem; width: 3rem;
} }
@ -1060,10 +1072,6 @@ video {
width: 2.75rem; width: 2.75rem;
} }
.w-0 {
width: 0px;
}
.w-16 { .w-16 {
width: 4rem; width: 4rem;
} }
@ -1810,6 +1818,15 @@ html, body {
display: block ruby; display: block ruby;
} }
.badge {
}
.badge svg {
/*Workaround for leaflet*/
width: unset !important;
height: 100% !important;
}
svg, img { svg, img {
box-sizing: content-box; box-sizing: content-box;
width: 100%; width: 100%;

View file

@ -91,6 +91,15 @@ html, body {
display: block ruby; display: block ruby;
} }
.badge {
}
.badge svg {
/*Workaround for leaflet*/
width: unset !important;
height: 100% !important;
}
svg, img { svg, img {
box-sizing: content-box; box-sizing: content-box;
width: 100%; width: 100%;

View file

@ -26,35 +26,37 @@ function fixLayerConfig(config: LayerConfigJson): void {
} }
} }
} }
if(config.mapRendering === undefined || true){ if (config.mapRendering === undefined || true) {
// This is a legacy format, lets create a pointRendering // This is a legacy format, lets create a pointRendering
let location: ("point"|"centroid")[] = ["point"] let location: ("point" | "centroid")[] = ["point"]
let wayHandling: number = config.wayHandling let wayHandling: number = config["wayHandling"] ?? 0
if(wayHandling === 2){ if (wayHandling === 2) {
location = ["point", "centroid"] location = ["point", "centroid"]
} }
config.mapRendering = [ config.mapRendering = [
{ {
icon: config["icon"], icon: config["icon"],
iconOverlays: config["iconOverlays"], iconBadges: config["iconOverlays"],
label: config["label"], label: config["label"],
iconSize: config["iconSize"], iconSize: config["iconSize"],
location, location,
rotation: config["rotation"] rotation: config["rotation"]
} }
] ]
if(wayHandling !== 1){ if (wayHandling !== 1) {
const lineRenderConfig = <LineRenderingConfigJson>{ const lineRenderConfig = <LineRenderingConfigJson>{
color: config["color"], color: config["color"],
width: config["width"], width: config["width"],
dashArray: config["dashArray"] dashArray: config["dashArray"]
} }
if(Object.keys(lineRenderConfig).length > 0){ if (Object.keys(lineRenderConfig).length > 0) {
config.mapRendering.push(lineRenderConfig) config.mapRendering.push(lineRenderConfig)
} }
} }
/*delete config["color"] /*delete config["color"]
delete config["width"] delete config["width"]
delete config["dashArray"] delete config["dashArray"]
@ -64,11 +66,23 @@ function fixLayerConfig(config: LayerConfigJson): void {
delete config["label"] delete config["label"]
delete config["iconSize"] delete config["iconSize"]
delete config["rotation"] delete config["rotation"]
delete config["wayHandling"]
*/ */
} }
for (const mapRenderingElement of config.mapRendering) {
if (mapRenderingElement["iconOverlays"] !== undefined) {
mapRenderingElement["iconBadges"] = mapRenderingElement["iconOverlays"]
}
for (const overlay of mapRenderingElement["iconBadges"] ?? []) {
if (overlay["badge"] !== true) {
console.log("Warning: non-overlay element for ", config.id)
}
delete overlay["badge"]
}
}
} }
const layerFiles = ScriptUtils.getLayerFiles(); const layerFiles = ScriptUtils.getLayerFiles();
@ -86,11 +100,11 @@ for (const themeFile of themeFiles) {
// @ts-ignore // @ts-ignore
fixLayerConfig(layerConfig) fixLayerConfig(layerConfig)
} }
if(themeFile.parsed["roamingRenderings"] !== undefined && themeFile.parsed["roamingRenderings"].length == 0){ if (themeFile.parsed["roamingRenderings"] !== undefined && themeFile.parsed["roamingRenderings"].length == 0) {
delete themeFile.parsed["roamingRenderings"] delete themeFile.parsed["roamingRenderings"]
} }
writeFileSync(themeFile.path, JSON.stringify(themeFile.parsed, null, " ")) writeFileSync(themeFile.path, JSON.stringify(themeFile.parsed, null, " "))
} }
//*/ //*/