diff --git a/Docs/Layers/bicycle_rental.md b/Docs/Layers/bicycle_rental.md
new file mode 100644
index 0000000000..5ea76a073b
--- /dev/null
+++ b/Docs/Layers/bicycle_rental.md
@@ -0,0 +1,286 @@
+bicycle_rental
+================
+
+
+
+
+
+Bicycle rental stations
+
+## Table of contents
+
+1. [bicycle_rental](#bicycle_rental)
+ * [Themes using this layer](#themes-using-this-layer)
+
+- [Basic tags for this layer](#basic-tags-for-this-layer)
+- [Supported attributes](#supported-attributes)
+ + [bicycle_rental_type](#bicycle_rental_type)
+ + [website](#website)
+ + [email](#email)
+ + [phone](#phone)
+ + [opening_hours](#opening_hours)
+ + [payment-options](#payment-options)
+ + [payment-options-advanced](#payment-options-advanced)
+ + [bicycle-types](#bicycle-types)
+ + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type)
+ + [questions](#questions)
+ + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type)
+ + [questions](#questions)
+ + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type)
+ + [questions](#questions)
+ + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type)
+ + [questions](#questions)
+ + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type)
+ + [questions](#questions)
+ + [rental-capacity-bicycle-type](#rental-capacity-bicycle-type)
+ + [questions](#questions)
+
+#### Themes using this layer
+
+- [bicycle_rental](https://mapcomplete.osm.be/bicycle_rental)
+- [personal](https://mapcomplete.osm.be/personal)
+
+[Go to the source code](../assets/layers/bicycle_rental/bicycle_rental.json)
+
+
+
+Basic tags for this layer
+---------------------------
+
+
+
+Elements must have the all of following tags to be shown on this layer:
+
+- amenity
+ =bicycle_rental
+ |bicycle_rental~^..*$|
+ service:bicycle:rental
+ =yes|rental~^.*
+ bicycle.*$
+
+Supported attributes
+----------------------
+
+
+
+**Warning** This quick overview is incomplete
+
+attribute | type | values which are supported by this layer
+----------- | ------ | ------------------------------------------
+[
](https://taginfo.openstreetmap.org/keys/website#values) [website](https://wiki.openstreetmap.org/wiki/Key:website) | [url](../SpecialInputElements.md#url) |
+[
](https://taginfo.openstreetmap.org/keys/email#values) [email](https://wiki.openstreetmap.org/wiki/Key:email) | [email](../SpecialInputElements.md#email) |
+[
](https://taginfo.openstreetmap.org/keys/phone#values) [phone](https://wiki.openstreetmap.org/wiki/Key:phone) | [phone](../SpecialInputElements.md#phone) |
+[
](https://taginfo.openstreetmap.org/keys/opening_hours#values) [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours) | [opening_hours](../SpecialInputElements.md#opening_hours) |
+[
](https://taginfo.openstreetmap.org/keys/rental#values) [rental](https://wiki.openstreetmap.org/wiki/Key:rental) | [string](../SpecialInputElements.md#string) | [city_bike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dcity_bike) [ebike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Debike) [bmx](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dbmx) [mtb](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dmtb) [kid_bike](https://wiki.openstreetmap.org/wiki/Tag:rental%3Dkid_bike)
+[
](https://taginfo.openstreetmap.org/keys/capacity:city_bike#values) [capacity:city_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:city_bike) | [pnat](../SpecialInputElements.md#pnat) |
+[
](https://taginfo.openstreetmap.org/keys/capacity:ebike#values) [capacity:ebike](https://wiki.openstreetmap.org/wiki/Key:capacity:ebike) | [pnat](../SpecialInputElements.md#pnat) |
+[
](https://taginfo.openstreetmap.org/keys/capacity:kid_bike#values) [capacity:kid_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:kid_bike) | [pnat](../SpecialInputElements.md#pnat) |
+[
](https://taginfo.openstreetmap.org/keys/capacity:bmx#values) [capacity:bmx](https://wiki.openstreetmap.org/wiki/Key:capacity:bmx) | [pnat](../SpecialInputElements.md#pnat) |
+[
](https://taginfo.openstreetmap.org/keys/capacity:mtb#values) [capacity:mtb](https://wiki.openstreetmap.org/wiki/Key:capacity:mtb) | [pnat](../SpecialInputElements.md#pnat) |
+[
](https://taginfo.openstreetmap.org/keys/capacity:bicycle_pannier#values) [capacity:bicycle_pannier](https://wiki.openstreetmap.org/wiki/Key:capacity:bicycle_pannier) | [pnat](../SpecialInputElements.md#pnat) |
+
+### bicycle_rental_type
+
+The question is **What kind of bicycle rental is this?**
+
+- **This is a shop whose main focus is bicycle rental** corresponds
+ with shop
+ =bicycle_rental
+ &bicycle_rental
+ =shop
+- **This is a rental buisiness which rents out various objects and/or vehicles. It rents out bicycles too, but this is
+ not the main focus** corresponds with shop
+ =rental_This option cannot be
+ chosen as answer_
+- **This is a shop which sells or repairs bicycles, but also rents out bicycles** corresponds
+ with service:bicycle:
+ rental=yes
+ &shop
+ =bicycle
+- **This is an automated docking station, where a bicycle is mechanically locked into a structure** corresponds
+ with bicycle_rental
+ =
+ docking_station
+- **A machine is present which dispenses and accepts keys, eventually after authentication and/or payment. The bicycles
+ are parked nearby** corresponds with
+ bicycle_rental
+ =
+ key_dispensing_machine
+- **This is a dropoff point: a designated bicycle parking for this cycle rental** corresponds
+ with bicycle_rental
+ =dropoff_point
+
+### website
+
+The question is **What is the website of {name}?**
+
+This rendering asks information about the property [website](https://wiki.openstreetmap.org/wiki/Key:website)
+This is rendered with `{website}`
+
+- **{contact:website}** corresponds with contact:website~^..*$_This
+ option cannot be chosen as answer_
+
+### email
+
+The question is **What is the email address of {name}?**
+
+This rendering asks information about the property [email](https://wiki.openstreetmap.org/wiki/Key:email)
+This is rendered with `{email}`
+
+- **{contact:email}** corresponds with contact:email~^..*$_This
+ option cannot be chosen as answer_
+
+### phone
+
+The question is **What is the phone number of {name}?**
+
+This rendering asks information about the property [phone](https://wiki.openstreetmap.org/wiki/Key:phone)
+This is rendered with `{phone}`
+
+- **{contact:phone}** corresponds with contact:phone~^..*$_This option cannot be
+ chosen as answer_
+
+### opening_hours
+
+The question is **What are the opening hours of {name}?**
+
+This rendering asks information about the
+property [opening_hours](https://wiki.openstreetmap.org/wiki/Key:opening_hours)
+This is rendered with `
Opening hours
{opening_hours_table(opening_hours)}`
+
+### payment-options
+
+The question is **Which methods of payment are accepted here?**
+
+- **Cash is accepted here** corresponds
+ with payment:cash
+ =yesUnselecting this answer
+ will add payment:cash
+ =no
+- **Payment cards are accepted here** corresponds
+ with payment:cards
+ =yesUnselecting this answer
+ will add payment:cards
+ =no
+
+### payment-options-advanced
+
+The question is **Which methods of payment are accepted here?**
+
+- **Cash is accepted here** corresponds
+ with payment:cash
+ =yesUnselecting this answer
+ will add payment:cash
+ =no
+- **Payment cards are accepted here** corresponds
+ with payment:cards
+ =yesUnselecting this answer
+ will add payment:cards
+ =no
+- **Payment is done using a dedicated app** corresponds
+ with payment:app
+ =yesUnselecting this answer
+ will add payment:app
+ =no
+- **Payment is done using a membership card** corresponds
+ with payment:
+ membership_card=
+ yesUnselecting this answer will
+ add payment:
+ membership_card=
+ no
+
+### bicycle-types
+
+The question is **What kind of bicycles and accessories are rented here?**
+
+This rendering asks information about the property [rental](https://wiki.openstreetmap.org/wiki/Key:rental)
+This is rendered with `{rental} is rented here`
+
+- **Normal city bikes can be rented here** corresponds
+ with rental
+ =city_bike
+- **Electrical bikes can be rented here** corresponds
+ with rental
+ =ebike
+- **BMX bikes can be rented here** corresponds
+ with rental
+ =bmx
+- **Mountainbikes can be rented here** corresponds
+ with rental
+ =mtb
+- **Bikes for childs can be rented here** corresponds
+ with rental
+ =kid_bike
+
+### rental-capacity-bicycle-type
+
+The question is **How much city bikes can be rented here? **
+
+This rendering asks information about the
+property [capacity:city_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:city_bike)
+This is rendered with `{capacity:city_bike} city bikes can be rented here`
+
+### questions
+
+_This tagrendering has no question and is thus read-only_
+
+### rental-capacity-bicycle-type
+
+The question is **How much electrical bikes can be rented here? **
+
+This rendering asks information about the
+property [capacity:ebike](https://wiki.openstreetmap.org/wiki/Key:capacity:ebike)
+This is rendered with `{capacity:ebike} electrical bikes can be rented here`
+
+### questions
+
+_This tagrendering has no question and is thus read-only_
+
+### rental-capacity-bicycle-type
+
+The question is **How much bikes for children can be rented here? **
+
+This rendering asks information about the
+property [capacity:kid_bike](https://wiki.openstreetmap.org/wiki/Key:capacity:kid_bike)
+This is rendered with `{capacity:kid_bike} bikes for children can be rented here`
+
+### questions
+
+_This tagrendering has no question and is thus read-only_
+
+### rental-capacity-bicycle-type
+
+The question is **How much BMX bikes can be rented here? **
+
+This rendering asks information about the property [capacity:bmx](https://wiki.openstreetmap.org/wiki/Key:capacity:bmx)
+This is rendered with `{capacity:bmx} BMX bikes can be rented here`
+
+### questions
+
+_This tagrendering has no question and is thus read-only_
+
+### rental-capacity-bicycle-type
+
+The question is **How much mountainbike can be rented here? **
+
+This rendering asks information about the property [capacity:mtb](https://wiki.openstreetmap.org/wiki/Key:capacity:mtb)
+This is rendered with `{capacity:mtb} mountainbike can be rented here`
+
+### questions
+
+_This tagrendering has no question and is thus read-only_
+
+### rental-capacity-bicycle-type
+
+The question is **How much bicycle panniers can be rented here? **
+
+This rendering asks information about the
+property [capacity:bicycle_pannier](https://wiki.openstreetmap.org/wiki/Key:capacity:bicycle_pannier)
+This is rendered with `{capacity:bicycle_pannier} bicycle panniers can be rented here`
+
+### questions
+
+_This tagrendering has no question and is thus read-only_
+
+This document is autogenerated from assets/layers/bicycle_rental/bicycle_rental.json
\ No newline at end of file
diff --git a/Models/ThemeConfig/Conversion/Conversion.ts b/Models/ThemeConfig/Conversion/Conversion.ts
index 589af96768..15b5153438 100644
--- a/Models/ThemeConfig/Conversion/Conversion.ts
+++ b/Models/ThemeConfig/Conversion/Conversion.ts
@@ -26,14 +26,14 @@ export abstract class Conversion {
return fixed.result;
}
- public convertStrict(state: DesugaringContext, json: TIn, context: string): TOut {
- const fixed = this.convert(state, json, context)
+ public convertStrict(json: TIn, context: string): TOut {
+ const fixed = this.convert(json, context)
return DesugaringStep.strict(fixed)
}
- abstract convert(state: DesugaringContext, json: TIn, context: string): { result: TOut, errors?: string[], warnings?: string[] }
+ abstract convert(json: TIn, context: string): { result: TOut, errors?: string[], warnings?: string[] }
- public convertAll(state: DesugaringContext, jsons: TIn[], context: string): { result: TOut[], errors: string[], warnings: string[] } {
+ public convertAll(jsons: TIn[], context: string): { result: TOut[], errors: string[], warnings: string[] } {
if(jsons === undefined){
throw "convertAll received undefined - don't do this (at "+context+")"
}
@@ -42,7 +42,7 @@ export abstract class Conversion {
const warnings = []
for (let i = 0; i < jsons.length; i++) {
const json = jsons[i];
- const r = this.convert(state, json, context + "[" + i + "]")
+ const r = this.convert(json, context + "[" + i + "]")
result.push(r.result)
errors.push(...r.errors ?? [])
warnings.push(...r.warnings ?? [])
@@ -69,11 +69,11 @@ export class OnEvery extends DesugaringStep {
this.key = key;
}
- convert(state: DesugaringContext, json: T, context: string): { result: T; errors?: string[]; warnings?: string[] } {
+ convert(json: T, context: string): { result: T; errors?: string[]; warnings?: string[] } {
json = {...json}
const step = this.step
const key = this.key;
- const r = step.convertAll(state, (json[key]), context + "." + key)
+ const r = step.convertAll((json[key]), context + "." + key)
json[key] = r.result
return {
result: json,
@@ -94,7 +94,7 @@ export class OnEveryConcat extends DesugaringStep {
this.key = key;
}
- convert(state: DesugaringContext, json: T, context: string): { result: T; errors: string[]; warnings: string[] } {
+ convert(json: T, context: string): { result: T; errors: string[]; warnings: string[] } {
json = {...json}
const step = this.step
const key = this.key;
@@ -107,7 +107,7 @@ export class OnEveryConcat extends DesugaringStep {
warnings: []
}
}
- const r = step.convertAll(state, (values), context + "." + key)
+ const r = step.convertAll((values), context + "." + key)
const vals: X[][] = r.result
json[key] = [].concat(...vals)
return {
@@ -129,12 +129,12 @@ export class Fuse extends DesugaringStep {
this.steps = steps;
}
- convert(state: DesugaringContext, json: T, context: string): { result: T; errors: string[]; warnings: string[] } {
+ convert(json: T, context: string): { result: T; errors: string[]; warnings: string[] } {
const errors = []
const warnings = []
for (let i = 0; i < this.steps.length; i++) {
const step = this.steps[i];
- let r = step.convert(state, json, "While running step " +step.name + ": " + context)
+ let r = step.convert(json, "While running step " +step.name + ": " + context)
errors.push(...r.errors ?? [])
warnings.push(...r.warnings ?? [])
json = r.result
@@ -163,7 +163,7 @@ export class SetDefault extends DesugaringStep {
this._overrideEmptyString = overrideEmptyString;
}
- convert(state: DesugaringContext, json: T, context: string): { result: T; errors: string[]; warnings: string[] } {
+ convert(json: T, context: string): { result: T; errors: string[]; warnings: string[] } {
if (json[this.key] === undefined || (json[this.key] === "" && this._overrideEmptyString)) {
json = {...json}
json[this.key] = this.value
diff --git a/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts b/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts
index 5f244d2787..2343b27549 100644
--- a/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts
+++ b/Models/ThemeConfig/Conversion/CreateNoteImportLayer.ts
@@ -1,4 +1,4 @@
-import {Conversion, DesugaringContext} from "./Conversion";
+import {Conversion} from "./Conversion";
import LayerConfig from "../LayerConfig";
import {LayerConfigJson} from "../Json/LayerConfigJson";
import Translations from "../../../UI/i18n/Translations";
@@ -20,7 +20,7 @@ export default class CreateNoteImportLayer extends Conversion {
super("Small fixes in the theme config", ["roamingRenderings"]);
}
- convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
const oldThemeConfig = {...json}
if (oldThemeConfig["roamingRenderings"] !== undefined) {
diff --git a/Models/ThemeConfig/Conversion/PrepareLayer.ts b/Models/ThemeConfig/Conversion/PrepareLayer.ts
index a637fffbee..a362172e40 100644
--- a/Models/ThemeConfig/Conversion/PrepareLayer.ts
+++ b/Models/ThemeConfig/Conversion/PrepareLayer.ts
@@ -6,21 +6,24 @@ import Translations from "../../../UI/i18n/Translations";
import {Translation} from "../../../UI/i18n/Translation";
class ExpandTagRendering extends Conversion {
- constructor() {
+ private readonly _state: DesugaringContext;
+ constructor(state: DesugaringContext) {
super("Converts a tagRenderingSpec into the full tagRendering", []);
+ this._state = state;
}
- convert(state: DesugaringContext, json: string | TagRenderingConfigJson | { builtin: string | string[]; override: any }, context: string): { result: TagRenderingConfigJson[]; errors: string[]; warnings: string[] } {
+ convert(json: string | TagRenderingConfigJson | { builtin: string | string[]; override: any }, context: string): { result: TagRenderingConfigJson[]; errors: string[]; warnings: string[] } {
const errors = []
const warnings = []
return {
- result: this.convertUntilStable(state, json, warnings, errors, context),
+ result: this.convertUntilStable(json, warnings, errors, context),
errors, warnings
};
}
- private lookup(state: DesugaringContext, name: string): TagRenderingConfigJson[] {
+ private lookup(name: string): TagRenderingConfigJson[] {
+ const state = this._state;
if (state.tagRenderings.has(name)) {
return [state.tagRenderings.get(name)]
}
@@ -61,7 +64,8 @@ class ExpandTagRendering extends Conversion {
- private static expandSubTagRenderings = new ExpandTagRendering()
+ private _expandSubTagRenderings;
- constructor() {
+ constructor(state: DesugaringContext) {
super(
"Converts a rewrite config for tagRenderings into the expanded form"
);
+ this._expandSubTagRenderings = new ExpandTagRendering(state)
}
- convert(state: DesugaringContext, json:
+ convert( json:
{
rewrite:
{ sourceString: string; into: string[] }[]; renderings: (string | { builtin: string; override: any } | TagRenderingConfigJson)[]
@@ -186,7 +191,7 @@ class ExpandGroupRewrite extends Conversion<{
}
}
- const subRenderingsRes = <{ result: TagRenderingConfigJson[][], errors, warnings }> ExpandGroupRewrite.expandSubTagRenderings.convertAll(state, config.renderings, context);
+ const subRenderingsRes = <{ result: TagRenderingConfigJson[][], errors, warnings }> this._expandSubTagRenderings.convertAll(config.renderings, context);
const subRenderings: TagRenderingConfigJson[] = [].concat(...subRenderingsRes.result);
const errors = subRenderingsRes.errors;
const warnings = subRenderingsRes.warnings;
@@ -279,13 +284,13 @@ class ExpandGroupRewrite extends Conversion<{
export class PrepareLayer extends Fuse {
- constructor() {
+ constructor(state: DesugaringContext) {
super(
"Fully prepares and expands a layer for the LayerConfig.",
- new OnEveryConcat("tagRenderings", new ExpandGroupRewrite()),
- new OnEveryConcat("tagRenderings", new ExpandTagRendering()),
+ new OnEveryConcat("tagRenderings", new ExpandGroupRewrite(state)),
+ new OnEveryConcat("tagRenderings", new ExpandTagRendering(state)),
new SetDefault("titleIcons", ["defaults"]),
- new OnEveryConcat("titleIcons", new ExpandTagRendering())
+ new OnEveryConcat("titleIcons", new ExpandTagRendering(state))
);
}
}
\ No newline at end of file
diff --git a/Models/ThemeConfig/Conversion/PrepareTheme.ts b/Models/ThemeConfig/Conversion/PrepareTheme.ts
index afd90daf5c..04047c5fd7 100644
--- a/Models/ThemeConfig/Conversion/PrepareTheme.ts
+++ b/Models/ThemeConfig/Conversion/PrepareTheme.ts
@@ -13,14 +13,17 @@ import DependencyCalculator from "../DependencyCalculator";
import {ValidateThemeAndLayers} from "./Validation";
class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfigJson[]> {
- constructor() {
+ private readonly _state: DesugaringContext;
+ constructor(
+ state: DesugaringContext,
+ ) {
super("Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form", []);
+ this._state = state;
}
- convert(state: DesugaringContext, json: string | LayerConfigJson, context: string): { result: LayerConfigJson[]; errors: string[]; warnings: string[] } {
+ convert(json: string | LayerConfigJson, context: string): { result: LayerConfigJson[]; errors: string[] } {
const errors = []
- const warnings = []
-
+ const state= this._state
function reportNotFound(name: string){
const knownLayers = Array.from(state.sharedLayers.keys())
const withDistance = knownLayers.map(lname => [lname, Utils.levenshteinDistance(name, lname)])
@@ -39,12 +42,11 @@ class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfig
return {
result: null,
errors,
- warnings
}
}
return {
result: [found],
- errors, warnings
+ errors
}
}
@@ -72,28 +74,31 @@ class SubstituteLayer extends Conversion<(string | LayerConfigJson), LayerConfig
}
return {
result: layers,
- errors, warnings
+ errors
}
}
return {
result: [json],
- errors, warnings
+ errors
};
}
}
class AddDefaultLayers extends DesugaringStep {
+ private _state: DesugaringContext;
- constructor() {
+ constructor(state: DesugaringContext) {
super("Adds the default layers, namely: " + Constants.added_by_default.join(", "), ["layers"]);
+ this._state = state;
}
- convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
const errors = []
const warnings = []
+ const state = this._state
json.layers = [...json.layers]
const alreadyLoaded = new Set(json.layers.map(l => l["id"]))
@@ -141,7 +146,7 @@ class AddImportLayers extends DesugaringStep {
super("For every layer in the 'layers'-list, create a new layer which'll import notes. (Note that priviliged layers and layers which have a geojson-source set are ignored)", ["layers"]);
}
- convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
const errors = []
const warnings = []
@@ -176,11 +181,10 @@ class AddImportLayers extends DesugaringStep {
try {
- const importLayerResult = creator.convert(state, layer, context + ".(noteimportlayer)[" + i1 + "]")
+ const importLayerResult = creator.convert(layer, context + ".(noteimportlayer)[" + i1 + "]")
errors.push(...importLayerResult.errors)
warnings.push(...importLayerResult.warnings)
if (importLayerResult.result !== undefined) {
- warnings.push("Added an import layer to theme " + json.id + ", namely " + importLayerResult.result.id)
json.layers.push(importLayerResult.result)
}
} catch (e) {
@@ -199,8 +203,10 @@ class AddImportLayers extends DesugaringStep {
export class AddMiniMap extends DesugaringStep {
- constructor() {
+ private readonly _state: DesugaringContext;
+ constructor(state: DesugaringContext, ) {
super("Adds a default 'minimap'-element to the tagrenderings if none of the elements define such a minimap", ["tagRenderings"]);
+ this._state = state;
}
/**
@@ -229,9 +235,9 @@ export class AddMiniMap extends DesugaringStep {
return false;
}
- convert(state: DesugaringContext, layerConfig: LayerConfigJson, context: string): { result: LayerConfigJson; errors: string[]; warnings: string[] } {
-
+ convert(layerConfig: LayerConfigJson, context: string): { result: LayerConfigJson; errors: string[]; warnings: string[] } {
+ const state = this._state;
const hasMinimap = layerConfig.tagRenderings?.some(tr => AddMiniMap.hasMinimap(tr)) ?? true
if (!hasMinimap) {
layerConfig = {...layerConfig}
@@ -255,7 +261,7 @@ class ApplyOverrideAll extends DesugaringStep {
super("Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards", ["overrideAll", "layers"]);
}
- convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
const overrideAll = json.overrideAll;
if (overrideAll === undefined) {
@@ -280,8 +286,10 @@ class ApplyOverrideAll extends DesugaringStep {
}
class AddDependencyLayersToTheme extends DesugaringStep {
- constructor() {
+ private readonly _state: DesugaringContext;
+ constructor(state: DesugaringContext, ) {
super("If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)", ["layers"]);
+ this._state = state;
}
private static CalculateDependencies(alreadyLoaded: LayerConfigJson[], allKnownLayers: Map, themeId: string): LayerConfigJson[] {
@@ -326,7 +334,8 @@ class AddDependencyLayersToTheme extends DesugaringStep {
return dependenciesToAdd;
}
- convert(state: DesugaringContext, theme: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ convert(theme: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ const state = this._state
const allKnownLayers: Map = state.sharedLayers;
const knownTagRenderings: Map = state.tagRenderings;
const errors = [];
@@ -357,18 +366,18 @@ class AddDependencyLayersToTheme extends DesugaringStep {
export class PrepareTheme extends Fuse {
- constructor() {
+ constructor(state: DesugaringContext) {
super(
"Fully prepares and expands a theme",
- new OnEveryConcat("layers", new SubstituteLayer()),
+ new OnEveryConcat("layers", new SubstituteLayer(state)),
new SetDefault("socialImage", "assets/SocialImage.png", true),
- new OnEvery("layers", new PrepareLayer()),
+ new OnEvery("layers", new PrepareLayer(state)),
new ApplyOverrideAll(),
- new AddDefaultLayers(),
- new AddDependencyLayersToTheme(),
+ new AddDefaultLayers(state),
+ new AddDependencyLayersToTheme(state),
new AddImportLayers(),
- new OnEvery("layers", new AddMiniMap())
+ new OnEvery("layers", new AddMiniMap(state))
);
}
}
\ No newline at end of file
diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts
index 13385a5366..863d9cf28e 100644
--- a/Models/ThemeConfig/Conversion/Validation.ts
+++ b/Models/ThemeConfig/Conversion/Validation.ts
@@ -1,4 +1,4 @@
-import {DesugaringContext, DesugaringStep, Fuse, OnEvery} from "./Conversion";
+import {DesugaringStep, Fuse, OnEvery} from "./Conversion";
import {LayerConfigJson} from "../Json/LayerConfigJson";
import LayerConfig from "../LayerConfig";
import {Utils} from "../../../Utils";
@@ -8,7 +8,6 @@ import {LayoutConfigJson} from "../Json/LayoutConfigJson";
import LayoutConfig from "../LayoutConfig";
import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson";
import {TagUtils} from "../../../Logic/Tags/TagUtils";
-import {parseString} from "xml2js";
class ValidateLanguageCompleteness extends DesugaringStep {
@@ -19,7 +18,7 @@ class ValidateLanguageCompleteness extends DesugaringStep {
this._languages = languages;
}
- convert(state: DesugaringContext, obj: any, context: string): { result: LayerConfig; errors: string[]; warnings: string[] } {
+ convert(obj: any, context: string): { result: LayerConfig; errors: string[] } {
const errors = []
const translations = Translation.ExtractAllTranslationsFrom(
obj
@@ -34,7 +33,7 @@ class ValidateLanguageCompleteness extends DesugaringStep {
return {
result: obj,
- warnings: [], errors
+ errors
};
}
}
@@ -55,9 +54,8 @@ class ValidateTheme extends DesugaringStep {
this._isBuiltin = isBuiltin;
}
- convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[]; warnings: string[] } {
+ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors: string[] } {
const errors = []
- const warnings = []
{
// Legacy format checks
if (this._isBuiltin) {
@@ -89,9 +87,8 @@ class ValidateTheme extends DesugaringStep {
}
if (json["mustHaveLanguage"] !== undefined) {
const checked = new ValidateLanguageCompleteness(...json["mustHaveLanguage"])
- .convert(state, theme, theme.id)
+ .convert(theme, theme.id)
errors.push(...checked.errors)
- warnings.push(...checked.warnings)
}
} catch (e) {
@@ -100,8 +97,7 @@ class ValidateTheme extends DesugaringStep {
return {
result: json,
- errors,
- warnings
+ errors
};
}
}
@@ -122,7 +118,7 @@ class OverrideShadowingCheck extends DesugaringStep{
super("Checks that an 'overrideAll' does not override a single override");
}
- convert(state: DesugaringContext, json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } {
+ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } {
const overrideAll = json.overrideAll;
if(overrideAll === undefined){
@@ -144,12 +140,10 @@ class OverrideShadowingCheck extends DesugaringStep{
return {result: json, errors}
}
-
-
}
export class PrevalidateTheme extends Fuse{
-
+
constructor() {
super("Various consistency checks on the raw JSON",
new OverrideShadowingCheck()
@@ -157,7 +151,6 @@ export class PrevalidateTheme extends Fuse{
}
-
}
export class DetectShadowedMappings extends DesugaringStep{
@@ -165,7 +158,7 @@ export class DetectShadowedMappings extends DesugaringStep {
this._isBuiltin = isBuiltin;
}
- convert(state: DesugaringContext, json: LayerConfigJson, context: string): { result: LayerConfigJson; errors: string[]; warnings?: string[] } {
+ convert(json: LayerConfigJson, context: string): { result: LayerConfigJson; errors: string[]; warnings?: string[] } {
const errors = []
const warnings = []
@@ -315,7 +308,7 @@ export class ValidateLayer extends DesugaringStep {
}
}
if(json.tagRenderings !== undefined){
- new DetectShadowedMappings().convertAll(state, json.tagRenderings, context+".tagRenderings")
+ new DetectShadowedMappings().convertAll( json.tagRenderings, context+".tagRenderings")
}
} catch (e) {
diff --git a/assets/layers/charging_station/charging_station.json b/assets/layers/charging_station/charging_station.json
index 6561120322..20e9ea4d23 100644
--- a/assets/layers/charging_station/charging_station.json
+++ b/assets/layers/charging_station/charging_station.json
@@ -10,13 +10,14 @@
"osmTags": {
"and": [
{
- "or": [
- "amenity=charging_station",
- "disused:amenity=charging_station",
- "planned:amenity=charging_station",
- "construction:amenity=charging_station"
+ "or": [
+ "amenity=charging_station",
+ "disused:amenity=charging_station",
+ "planned:amenity=charging_station",
+ "construction:amenity=charging_station"
+ ]
+ }
]
- } ]
}
},
"title": {
diff --git a/scripts/generateDocs.ts b/scripts/generateDocs.ts
index b0f07113e0..763b8b0e11 100644
--- a/scripts/generateDocs.ts
+++ b/scripts/generateDocs.ts
@@ -53,6 +53,7 @@ WriteFile("./Docs/SpecialInputElements.md", ValidatedTextField.HelpText(), ["Val
WriteFile("./Docs/BuiltinLayers.md", AllKnownLayouts.GenLayerOverviewText(), ["AllKnownLayers.ts"])
{
+ // Generate the builtinIndex which shows interlayer dependencies
var layers = ScriptUtils.getLayerFiles().map(f => f.parsed)
var builtinsPerLayer= new Map();
var layersUsingBuiltin = new Map();
diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts
index a15f35a868..ed2bbedd6d 100644
--- a/scripts/generateLayerOverview.ts
+++ b/scripts/generateLayerOverview.ts
@@ -138,16 +138,16 @@ class LayerOverviewUtils {
const sharedTagRenderings = this.getSharedTagRenderings();
const layerFiles = ScriptUtils.getLayerFiles();
const sharedLayers = new Map()
- const prepLayer = new PrepareLayer();
const state: DesugaringContext = {
tagRenderings: sharedTagRenderings,
sharedLayers
}
+ const prepLayer = new PrepareLayer(state);
for (const sharedLayerJson of layerFiles) {
const context = "While building builtin layer " + sharedLayerJson.path
- const fixed = prepLayer.convertStrict(state, sharedLayerJson.parsed, context)
+ const fixed = prepLayer.convertStrict(sharedLayerJson.parsed, context)
const validator = new ValidateLayer(knownImagePaths, sharedLayerJson.path, true);
- validator.convertStrict(state, fixed, context)
+ validator.convertStrict(fixed, context)
if (sharedLayers.has(fixed.id)) {
throw "There are multiple layers with the id " + fixed.id
@@ -174,11 +174,11 @@ class LayerOverviewUtils {
let themeFile = themeInfo.parsed
const themePath = themeInfo.path
- new PrevalidateTheme().convertStrict(convertState, themeFile, themePath)
- themeFile = new PrepareTheme().convertStrict(convertState, themeFile, themePath)
+ new PrevalidateTheme().convertStrict(themeFile, themePath)
+ themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath)
new ValidateThemeAndLayers(knownImagePaths, themePath, true)
- .convertStrict(convertState, themeFile, themePath)
+ .convertStrict(themeFile, themePath)
this.writeTheme(themeFile)
fixed.set(themeFile.id, themeFile)
diff --git a/test/LegacyThemeLoader.spec.ts b/test/LegacyThemeLoader.spec.ts
index f0b09b7b45..9cc2ccf80f 100644
--- a/test/LegacyThemeLoader.spec.ts
+++ b/test/LegacyThemeLoader.spec.ts
@@ -357,10 +357,7 @@ export default class LegacyThemeLoaderSpec extends T {
["Walking_node_theme", () => {
const config = LegacyThemeLoaderSpec.walking_node_theme
- const fixed = new FixLegacyTheme().convert({
- tagRenderings: new Map(),
- sharedLayers: new Map()
- },
+ const fixed = new FixLegacyTheme().convert(
// @ts-ignore
config,
"While testing")
@@ -414,7 +411,7 @@ export default class LegacyThemeLoaderSpec extends T {
}],
["Shadowed mappings are detected",
() => {
- const r = new DetectShadowedMappings().convert(undefined, {
+ const r = new DetectShadowedMappings().convert({
mappings: [
{
if: {or: ["key=value", "x=y"]},
@@ -428,7 +425,7 @@ export default class LegacyThemeLoaderSpec extends T {
}, "test");
T.isTrue(r.errors.length > 0, "Failing case is not detected")
- const r0 = new DetectShadowedMappings().convert(undefined, {
+ const r0 = new DetectShadowedMappings().convert( {
mappings: [
{
if: {or: ["key=value", "x=y"]},
diff --git a/test/Theme.spec.ts b/test/Theme.spec.ts
index 4cd428f06a..e331af3a00 100644
--- a/test/Theme.spec.ts
+++ b/test/Theme.spec.ts
@@ -40,10 +40,10 @@ export default class ThemeSpec extends T {
Constants.added_by_default.splice(0, Constants.added_by_default.length)
const sharedLayers = new Map()
sharedLayers.set("public_bookcase", bookcaseLayer["default"])
- themeConfigJson = new PrepareTheme().convertStrict({
+ themeConfigJson = new PrepareTheme({
tagRenderings: new Map(),
sharedLayers: sharedLayers
- }, themeConfigJson, "test")
+ }).convertStrict( themeConfigJson, "test")
const themeConfig = new LayoutConfig(themeConfigJson);
assert.equal("xyz", themeConfig.layers[0].source.geojsonSource)