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)