forked from MapComplete/MapComplete
		
	Merge branch 'develop' into feature/maproulette
This commit is contained in:
		
						commit
						64288ec1b8
					
				
					 20 changed files with 402 additions and 241 deletions
				
			
		| 
						 | 
					@ -10,5 +10,5 @@ ports:
 | 
				
			||||||
vscode:
 | 
					vscode:
 | 
				
			||||||
  extensions:
 | 
					  extensions:
 | 
				
			||||||
    - "esbenp.prettier-vscode"
 | 
					    - "esbenp.prettier-vscode"
 | 
				
			||||||
    - "eamodio.gitlens",
 | 
					    - "eamodio.gitlens"
 | 
				
			||||||
    - "GitHub.vscode-pull-request-github"
 | 
					    - "GitHub.vscode-pull-request-github"
 | 
				
			||||||
| 
						 | 
					@ -72,6 +72,12 @@ To use the WSL in Visual Studio Code:
 | 
				
			||||||
   or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
 | 
					   or `userlayout=true#<layout configuration>` as [Query parameter](URL_Parameters.md). Note that the shorter URLs (
 | 
				
			||||||
   e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
 | 
					   e.g. `bookcases.html`, `aed.html`, ...) _don't_ exist on the development version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Dependencie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`make` , `python3` `g++`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(run `nix-env -iA nixos.gnumake nixos.gdc nixos.python3`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Automatic deployment
 | 
					Automatic deployment
 | 
				
			||||||
--------------------
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,7 @@ import FullNodeDatabaseSource from "./TiledFeatureSource/FullNodeDatabaseSource"
 | 
				
			||||||
import MapState from "../State/MapState";
 | 
					import MapState from "../State/MapState";
 | 
				
			||||||
import {ElementStorage} from "../ElementStorage";
 | 
					import {ElementStorage} from "../ElementStorage";
 | 
				
			||||||
import {Feature, Geometry} from "@turf/turf";
 | 
					import {Feature, Geometry} from "@turf/turf";
 | 
				
			||||||
 | 
					import {OsmFeature} from "../../Models/OsmFeature";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -338,15 +339,19 @@ export default class FeaturePipeline {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public GetAllFeaturesWithin(bbox: BBox): Feature<Geometry, {id: string}>[][] {
 | 
					    public GetAllFeaturesWithin(bbox: BBox): OsmFeature[][] {
 | 
				
			||||||
        const self = this
 | 
					        const self = this
 | 
				
			||||||
        const tiles = []
 | 
					        const tiles: OsmFeature[][] = []
 | 
				
			||||||
        Array.from(this.perLayerHierarchy.keys())
 | 
					        Array.from(this.perLayerHierarchy.keys())
 | 
				
			||||||
            .forEach(key => tiles.push(...self.GetFeaturesWithin(key, bbox)))
 | 
					            .forEach(key => {
 | 
				
			||||||
 | 
					                const fetched : OsmFeature[][] = self.GetFeaturesWithin(key, bbox)
 | 
				
			||||||
 | 
					                tiles.push(...fetched);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        return tiles;
 | 
					        return tiles;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public GetAllFeaturesAndMetaWithin(bbox: BBox, layerIdWhitelist?: Set<string>): {features: any[], layer: string}[] {
 | 
					    public GetAllFeaturesAndMetaWithin(bbox: BBox, layerIdWhitelist?: Set<string>): 
 | 
				
			||||||
 | 
					        {features: OsmFeature[], layer: string}[] {
 | 
				
			||||||
        const self = this
 | 
					        const self = this
 | 
				
			||||||
        const tiles :{features: any[], layer: string}[]= []
 | 
					        const tiles :{features: any[], layer: string}[]= []
 | 
				
			||||||
        Array.from(this.perLayerHierarchy.keys())
 | 
					        Array.from(this.perLayerHierarchy.keys())
 | 
				
			||||||
| 
						 | 
					@ -362,7 +367,11 @@ export default class FeaturePipeline {
 | 
				
			||||||
        return tiles;
 | 
					        return tiles;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public GetFeaturesWithin(layerId: string, bbox: BBox): any[][] {
 | 
					    /**
 | 
				
			||||||
 | 
					     * Gets all the tiles which overlap with the given BBOX.
 | 
				
			||||||
 | 
					     * This might imply that extra features might be shown
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public GetFeaturesWithin(layerId: string, bbox: BBox): OsmFeature[][] {
 | 
				
			||||||
        if (layerId === "*") {
 | 
					        if (layerId === "*") {
 | 
				
			||||||
            return this.GetAllFeaturesWithin(bbox)
 | 
					            return this.GetAllFeaturesWithin(bbox)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,11 @@
 | 
				
			||||||
import {Store, UIEventSource} from "../UIEventSource";
 | 
					import {Store, UIEventSource} from "../UIEventSource";
 | 
				
			||||||
import FilteredLayer from "../../Models/FilteredLayer";
 | 
					import FilteredLayer from "../../Models/FilteredLayer";
 | 
				
			||||||
import {BBox} from "../BBox";
 | 
					import {BBox} from "../BBox";
 | 
				
			||||||
 | 
					import {Feature, Geometry} from "@turf/turf";
 | 
				
			||||||
 | 
					import {OsmFeature} from "../../Models/OsmFeature";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default interface FeatureSource {
 | 
					export default interface FeatureSource {
 | 
				
			||||||
    features: Store<{ feature: any, freshness: Date }[]>;
 | 
					    features: Store<{ feature: OsmFeature, freshness: Date }[]>;
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Mainly used for debuging
 | 
					     * Mainly used for debuging
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -28,12 +30,3 @@ export interface FeatureSourceForLayer extends FeatureSource {
 | 
				
			||||||
export interface IndexedFeatureSource extends FeatureSource {
 | 
					export interface IndexedFeatureSource extends FeatureSource {
 | 
				
			||||||
    readonly containedIds: Store<Set<string>>
 | 
					    readonly containedIds: Store<Set<string>>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * A feature source which has some extra data about it's state
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
export interface FeatureSourceState {
 | 
					 | 
				
			||||||
    readonly sufficientlyZoomed: Store<boolean>;
 | 
					 | 
				
			||||||
    readonly runningQuery: Store<boolean>;
 | 
					 | 
				
			||||||
    readonly timeout: Store<number>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ export default interface TileHierarchy<T extends FeatureSource & Tiled> {
 | 
				
			||||||
export class TileHierarchyTools {
 | 
					export class TileHierarchyTools {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static getTiles<T extends FeatureSource & Tiled>(hierarchy: TileHierarchy<T>, bbox: BBox): T[] {
 | 
					    public static getTiles<T extends FeatureSource & Tiled>(hierarchy: TileHierarchy<T>, bbox: BBox): T[] {
 | 
				
			||||||
        const result = []
 | 
					        const result: T[] = []
 | 
				
			||||||
        hierarchy.loadedTiles.forEach((tile) => {
 | 
					        hierarchy.loadedTiles.forEach((tile) => {
 | 
				
			||||||
            if (tile.bbox.overlapsWith(bbox)) {
 | 
					            if (tile.bbox.overlapsWith(bbox)) {
 | 
				
			||||||
                result.push(tile)
 | 
					                result.push(tile)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import {BBox} from "./BBox";
 | 
				
			||||||
import togpx from "togpx"
 | 
					import togpx from "togpx"
 | 
				
			||||||
import Constants from "../Models/Constants";
 | 
					import Constants from "../Models/Constants";
 | 
				
			||||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
					import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
				
			||||||
import {booleanWithin, Coord, Feature, Geometry, MultiPolygon, Polygon, Properties} from "@turf/turf";
 | 
					import {AllGeoJSON, booleanWithin, Coord, Feature, Geometry, MultiPolygon, Polygon, Properties} from "@turf/turf";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class GeoOperations {
 | 
					export class GeoOperations {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ export class GeoOperations {
 | 
				
			||||||
     * Returns [lon,lat] coordinates
 | 
					     * Returns [lon,lat] coordinates
 | 
				
			||||||
     * @param feature
 | 
					     * @param feature
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    static centerpointCoordinates(feature: any): [number, number] {
 | 
					    static centerpointCoordinates(feature: AllGeoJSON): [number, number] {
 | 
				
			||||||
        return <[number, number]>turf.center(feature).geometry.coordinates;
 | 
					        return <[number, number]>turf.center(feature).geometry.coordinates;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ export class Changes {
 | 
				
			||||||
        const recentLocationPoints = locations.map(ff => ff.feature)
 | 
					        const recentLocationPoints = locations.map(ff => ff.feature)
 | 
				
			||||||
            .filter(feat => feat.geometry.type === "Point")
 | 
					            .filter(feat => feat.geometry.type === "Point")
 | 
				
			||||||
            .filter(feat => {
 | 
					            .filter(feat => {
 | 
				
			||||||
                const visitTime = new Date((<GeoLocationPointProperties>feat.properties).date)
 | 
					                const visitTime = new Date((<GeoLocationPointProperties><any>feat.properties).date)
 | 
				
			||||||
                // In seconds
 | 
					                // In seconds
 | 
				
			||||||
                const diff = (now.getTime() - visitTime.getTime()) / 1000
 | 
					                const diff = (now.getTime() - visitTime.getTime()) / 1000
 | 
				
			||||||
                return diff < Constants.nearbyVisitTime;
 | 
					                return diff < Constants.nearbyVisitTime;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +13,7 @@ export class Tag extends TagsFilter {
 | 
				
			||||||
            throw "Invalid key: undefined or empty";
 | 
					            throw "Invalid key: undefined or empty";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (value === undefined) {
 | 
					        if (value === undefined) {
 | 
				
			||||||
            throw "Invalid value: value is undefined";
 | 
					            throw `Invalid value while constructing a Tag with key '${key}': value is undefined`;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (value === "*") {
 | 
					        if (value === "*") {
 | 
				
			||||||
            console.warn(`Got suspicious tag ${key}=*   ; did you mean ${key}~* ?`)
 | 
					            console.warn(`Got suspicious tag ${key}=*   ; did you mean ${key}~* ?`)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								Models/OsmFeature.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								Models/OsmFeature.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					import {Feature, Geometry} from "@turf/turf";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type OsmTags = Record<string, string> & {id: string}
 | 
				
			||||||
 | 
					export type OsmFeature = Feature<Geometry, OsmTags>
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ export interface Mapping {
 | 
				
			||||||
    readonly ifnot?: TagsFilter,
 | 
					    readonly ifnot?: TagsFilter,
 | 
				
			||||||
    readonly then: TypedTranslation<object>,
 | 
					    readonly then: TypedTranslation<object>,
 | 
				
			||||||
    readonly icon: string,
 | 
					    readonly icon: string,
 | 
				
			||||||
    readonly iconClass: string
 | 
					    readonly iconClass: string | "small"  | "medium" | "large" | "small-height" | "medium-height" | "large-height",
 | 
				
			||||||
    readonly hideInAnswer: boolean | TagsFilter
 | 
					    readonly hideInAnswer: boolean | TagsFilter
 | 
				
			||||||
    readonly addExtraTags: Tag[],
 | 
					    readonly addExtraTags: Tag[],
 | 
				
			||||||
    readonly searchTerms?: Record<string, string[]>
 | 
					    readonly searchTerms?: Record<string, string[]>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ class SelfHidingToggle extends UIElement implements InputElement<boolean> {
 | 
				
			||||||
                return true
 | 
					                return true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            s = s?.trim()?.toLowerCase()
 | 
					            s = s?.trim()?.toLowerCase()
 | 
				
			||||||
            return searchTerms[Locale.language.data].some(t => t.indexOf(s) >= 0);
 | 
					            return searchTerms[Locale.language.data]?.some(t => t.indexOf(s) >= 0) ?? false;
 | 
				
			||||||
        }, [selected, Locale.language])
 | 
					        }, [selected, Locale.language])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const self = this;
 | 
					        const self = this;
 | 
				
			||||||
| 
						 | 
					@ -121,10 +121,15 @@ class SelfHidingToggle extends UIElement implements InputElement<boolean> {
 | 
				
			||||||
 * A searchfield can be used to filter the values
 | 
					 * A searchfield can be used to filter the values
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class SearchablePillsSelector<T> extends Combine implements InputElement<T[]> {
 | 
					export class SearchablePillsSelector<T> extends Combine implements InputElement<T[]> {
 | 
				
			||||||
    private selectedElements: UIEventSource<T[]>;
 | 
					    private readonly selectedElements: UIEventSource<T[]>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public readonly someMatchFound: Store<boolean>;
 | 
					    public readonly someMatchFound: Store<boolean>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param values
 | 
				
			||||||
 | 
					     * @param options
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        values: { show: BaseUIElement, value: T, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[],
 | 
					        values: { show: BaseUIElement, value: T, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[],
 | 
				
			||||||
        options?: {
 | 
					        options?: {
 | 
				
			||||||
| 
						 | 
					@ -188,7 +193,6 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        let somethingShown: Store<boolean>
 | 
					        let somethingShown: Store<boolean>
 | 
				
			||||||
        if (options.selectIfSingle) {
 | 
					        if (options.selectIfSingle) {
 | 
				
			||||||
            let forcedSelection : { value: T, show: SelfHidingToggle } = undefined
 | 
					            let forcedSelection : { value: T, show: SelfHidingToggle } = undefined
 | 
				
			||||||
| 
						 | 
					@ -203,15 +207,15 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (totalShown == 1) {
 | 
					                if (totalShown == 1) {
 | 
				
			||||||
                    if (this.selectedElements.data.indexOf(lastShownValue.value) < 0) {
 | 
					                    if (selectedElements.data?.indexOf(lastShownValue.value) < 0) {
 | 
				
			||||||
                        this.selectedElements.setData([lastShownValue.value])
 | 
					                        selectedElements.setData([lastShownValue.value])
 | 
				
			||||||
                        lastShownValue.show.forceSelected.setData(true)
 | 
					                        lastShownValue.show.forceSelected.setData(true)
 | 
				
			||||||
                        forcedSelection = lastShownValue
 | 
					                        forcedSelection = lastShownValue
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else if (forcedSelection != undefined) {
 | 
					                } else if (forcedSelection != undefined) {
 | 
				
			||||||
                    forcedSelection?.show?.forceSelected?.setData(false)
 | 
					                    forcedSelection?.show?.forceSelected?.setData(false)
 | 
				
			||||||
                    forcedSelection = undefined;
 | 
					                    forcedSelection = undefined;
 | 
				
			||||||
                    this.selectedElements.setData([])
 | 
					                    selectedElements.setData([])
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return totalShown > 0
 | 
					                return totalShown > 0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ import BaseUIElement from "../BaseUIElement";
 | 
				
			||||||
import {DropDown} from "../Input/DropDown";
 | 
					import {DropDown} from "../Input/DropDown";
 | 
				
			||||||
import InputElementWrapper from "../Input/InputElementWrapper";
 | 
					import InputElementWrapper from "../Input/InputElementWrapper";
 | 
				
			||||||
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction";
 | 
					import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction";
 | 
				
			||||||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
 | 
					import TagRenderingConfig, {Mapping} from "../../Models/ThemeConfig/TagRenderingConfig";
 | 
				
			||||||
import {Unit} from "../../Models/Unit";
 | 
					import {Unit} from "../../Models/Unit";
 | 
				
			||||||
import VariableInputElement from "../Input/VariableInputElement";
 | 
					import VariableInputElement from "../Input/VariableInputElement";
 | 
				
			||||||
import Toggle from "../Input/Toggle";
 | 
					import Toggle from "../Input/Toggle";
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ import Title from "../Base/Title";
 | 
				
			||||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
 | 
					import {OsmConnection} from "../../Logic/Osm/OsmConnection";
 | 
				
			||||||
import {GeoOperations} from "../../Logic/GeoOperations";
 | 
					import {GeoOperations} from "../../Logic/GeoOperations";
 | 
				
			||||||
import {SearchablePillsSelector} from "../Input/SearchableMappingsSelector";
 | 
					import {SearchablePillsSelector} from "../Input/SearchableMappingsSelector";
 | 
				
			||||||
 | 
					import {OsmTags} from "../../Models/OsmFeature";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Shows the question element.
 | 
					 * Shows the question element.
 | 
				
			||||||
| 
						 | 
					@ -39,7 +40,7 @@ import {SearchablePillsSelector} from "../Input/SearchableMappingsSelector";
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class TagRenderingQuestion extends Combine {
 | 
					export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(tags: UIEventSource<Record<string, string> & {id: string}>,
 | 
					    constructor(tags: UIEventSource<Record<string, string> & { id: string }>,
 | 
				
			||||||
                configuration: TagRenderingConfig,
 | 
					                configuration: TagRenderingConfig,
 | 
				
			||||||
                state?: FeaturePipelineState,
 | 
					                state?: FeaturePipelineState,
 | 
				
			||||||
                options?: {
 | 
					                options?: {
 | 
				
			||||||
| 
						 | 
					@ -53,7 +54,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const applicableMappingsSrc =
 | 
					        const applicableMappingsSrc =
 | 
				
			||||||
            Stores.ListStabilized(tags.map(tags => {
 | 
					            Stores.ListStabilized(tags.map(tags => {
 | 
				
			||||||
                const applicableMappings: { if: TagsFilter, icon?: string, then: TypedTranslation<object>, ifnot?: TagsFilter, addExtraTags: Tag[] }[] = []
 | 
					                const applicableMappings: Mapping[] = []
 | 
				
			||||||
                for (const mapping of configuration.mappings ?? []) {
 | 
					                for (const mapping of configuration.mappings ?? []) {
 | 
				
			||||||
                    if (mapping.hideInAnswer === true) {
 | 
					                    if (mapping.hideInAnswer === true) {
 | 
				
			||||||
                        continue
 | 
					                        continue
 | 
				
			||||||
| 
						 | 
					@ -142,7 +143,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
    private static GenerateInputElement(
 | 
					    private static GenerateInputElement(
 | 
				
			||||||
        state: FeaturePipelineState,
 | 
					        state: FeaturePipelineState,
 | 
				
			||||||
        configuration: TagRenderingConfig,
 | 
					        configuration: TagRenderingConfig,
 | 
				
			||||||
        applicableMappings: { if: TagsFilter, then: TypedTranslation<object>, icon?: string, ifnot?: TagsFilter, addExtraTags: Tag[], searchTerms?: Record<string, string[]> }[],
 | 
					        applicableMappings: Mapping[],
 | 
				
			||||||
        applicableUnit: Unit,
 | 
					        applicableUnit: Unit,
 | 
				
			||||||
        tagsSource: UIEventSource<any>,
 | 
					        tagsSource: UIEventSource<any>,
 | 
				
			||||||
        feedback: UIEventSource<Translation>
 | 
					        feedback: UIEventSource<Translation>
 | 
				
			||||||
| 
						 | 
					@ -231,15 +232,84 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * // Should return the search as freeform value
 | 
				
			||||||
 | 
					     * const source = new UIEventSource({id: "1234"})
 | 
				
			||||||
 | 
					     * const tr =  new TagRenderingConfig({
 | 
				
			||||||
 | 
					     *      id:"test",
 | 
				
			||||||
 | 
					     *      render:"The value is {key}",
 | 
				
			||||||
 | 
					     *      freeform: {
 | 
				
			||||||
 | 
					     *          key:"key"
 | 
				
			||||||
 | 
					     *      },
 | 
				
			||||||
 | 
					     *    
 | 
				
			||||||
 | 
					     *      mappings: [
 | 
				
			||||||
 | 
					     *          {
 | 
				
			||||||
 | 
					     *            if:"x=y",
 | 
				
			||||||
 | 
					     *            then:"z",
 | 
				
			||||||
 | 
					     *            searchTerms: {
 | 
				
			||||||
 | 
					     *              "en" : ["z"]
 | 
				
			||||||
 | 
					     *            }
 | 
				
			||||||
 | 
					     *          }
 | 
				
			||||||
 | 
					     *      ]
 | 
				
			||||||
 | 
					     * }, "test");
 | 
				
			||||||
 | 
					     * const selector = TagRenderingQuestion.GenerateSearchableSelector(
 | 
				
			||||||
 | 
					     *          undefined,
 | 
				
			||||||
 | 
					     *          tr,
 | 
				
			||||||
 | 
					     *          tr.mappings,
 | 
				
			||||||
 | 
					     *          source,
 | 
				
			||||||
 | 
					     *          {
 | 
				
			||||||
 | 
					     *              search: new UIEventSource<string>("value")
 | 
				
			||||||
 | 
					     *          }
 | 
				
			||||||
 | 
					     *      );
 | 
				
			||||||
 | 
					     * selector.GetValue().data // => new And([new Tag("key","value")])
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * // Should return the search as freeform value, even if a previous search matched
 | 
				
			||||||
 | 
					     * const source = new UIEventSource({id: "1234"})
 | 
				
			||||||
 | 
					     * const search = new UIEventSource<string>("")
 | 
				
			||||||
 | 
					     * const tr =  new TagRenderingConfig({
 | 
				
			||||||
 | 
					     *      id:"test",
 | 
				
			||||||
 | 
					     *      render:"The value is {key}",
 | 
				
			||||||
 | 
					     *      freeform: {
 | 
				
			||||||
 | 
					     *          key:"key"
 | 
				
			||||||
 | 
					     *      },
 | 
				
			||||||
 | 
					     *    
 | 
				
			||||||
 | 
					     *      mappings: [
 | 
				
			||||||
 | 
					     *          {
 | 
				
			||||||
 | 
					     *            if:"x=y",
 | 
				
			||||||
 | 
					     *            then:"z",
 | 
				
			||||||
 | 
					     *            searchTerms: {
 | 
				
			||||||
 | 
					     *              "en" : ["z"]
 | 
				
			||||||
 | 
					     *            }
 | 
				
			||||||
 | 
					     *          }
 | 
				
			||||||
 | 
					     *      ]
 | 
				
			||||||
 | 
					     * }, "test");
 | 
				
			||||||
 | 
					     * const selector = TagRenderingQuestion.GenerateSearchableSelector(
 | 
				
			||||||
 | 
					     *          undefined,
 | 
				
			||||||
 | 
					     *          tr,
 | 
				
			||||||
 | 
					     *          tr.mappings,
 | 
				
			||||||
 | 
					     *          source,
 | 
				
			||||||
 | 
					     *          {
 | 
				
			||||||
 | 
					     *              search
 | 
				
			||||||
 | 
					     *          }
 | 
				
			||||||
 | 
					     *      );
 | 
				
			||||||
 | 
					     * search.setData("z")
 | 
				
			||||||
 | 
					     * search.setData("zx")
 | 
				
			||||||
 | 
					     * selector.GetValue().data // => new And([new Tag("key","zx")])
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    private static GenerateSearchableSelector(
 | 
					    private static GenerateSearchableSelector(
 | 
				
			||||||
        state: FeaturePipelineState,
 | 
					        state: FeaturePipelineState,
 | 
				
			||||||
        configuration: TagRenderingConfig,
 | 
					        configuration: TagRenderingConfig,
 | 
				
			||||||
        applicableMappings: { if: TagsFilter; ifnot?: TagsFilter, then: TypedTranslation<object>; icon?: string; iconClass?: string, addExtraTags: Tag[], searchTerms?: Record<string, string[]> }[], tagsSource: UIEventSource<any>): InputElement<TagsFilter> {
 | 
					        applicableMappings: Mapping[],
 | 
				
			||||||
 | 
					        tagsSource: UIEventSource<OsmTags>,
 | 
				
			||||||
 | 
					        options?: {
 | 
				
			||||||
 | 
					            search: UIEventSource<string>
 | 
				
			||||||
 | 
					        }): InputElement<TagsFilter> {
 | 
				
			||||||
        const values: { show: BaseUIElement, value: number, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[] = []
 | 
					        const values: { show: BaseUIElement, value: number, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[] = []
 | 
				
			||||||
        for (let i = 0; i < applicableMappings.length; i++) {
 | 
					        for (let i = 0; i < applicableMappings.length; i++) {
 | 
				
			||||||
            const mapping = applicableMappings[i];
 | 
					            const mapping = applicableMappings[i];
 | 
				
			||||||
            const tr = mapping.then.Subs(tagsSource.data)
 | 
					            const tr = mapping.then.Subs(tagsSource.data)
 | 
				
			||||||
            const patchedMapping = <{ iconClass: "small-height", then: TypedTranslation<object> }>{
 | 
					            const patchedMapping = <Mapping>{
 | 
				
			||||||
                ...mapping,
 | 
					                ...mapping,
 | 
				
			||||||
                iconClass: `small-height`,
 | 
					                iconClass: `small-height`,
 | 
				
			||||||
                icon: mapping.icon ?? "./assets/svg/none.svg"
 | 
					                icon: mapping.icon ?? "./assets/svg/none.svg"
 | 
				
			||||||
| 
						 | 
					@ -253,7 +323,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const searchValue: UIEventSource<string> = new UIEventSource<string>(undefined)
 | 
					        const searchValue: UIEventSource<string> = options?.search ?? new UIEventSource<string>(undefined)
 | 
				
			||||||
        const ff = configuration.freeform
 | 
					        const ff = configuration.freeform
 | 
				
			||||||
        let onEmpty: BaseUIElement = undefined
 | 
					        let onEmpty: BaseUIElement = undefined
 | 
				
			||||||
        if (ff !== undefined) {
 | 
					        if (ff !== undefined) {
 | 
				
			||||||
| 
						 | 
					@ -266,8 +336,14 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
            mode: configuration.multiAnswer ? "select-many" : "select-one",
 | 
					            mode: configuration.multiAnswer ? "select-many" : "select-one",
 | 
				
			||||||
            searchValue,
 | 
					            searchValue,
 | 
				
			||||||
            onNoMatches: onEmpty?.SetClass(classes).SetClass("flex justify-center items-center"),
 | 
					            onNoMatches: onEmpty?.SetClass(classes).SetClass("flex justify-center items-center"),
 | 
				
			||||||
            searchAreaClass: classes
 | 
					            searchAreaClass: classes,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					        const fallbackTag = searchValue.map(s => {
 | 
				
			||||||
 | 
					            if (s === undefined || ff?.key === undefined) {
 | 
				
			||||||
 | 
					                return undefined
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return new Tag(ff.key, s)
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
        return new InputElementMap<number[], And>(presetSearch,
 | 
					        return new InputElementMap<number[], And>(presetSearch,
 | 
				
			||||||
            (x0, x1) => {
 | 
					            (x0, x1) => {
 | 
				
			||||||
                if (x0 == x1) {
 | 
					                if (x0 == x1) {
 | 
				
			||||||
| 
						 | 
					@ -288,7 +364,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            (selected) => {
 | 
					            (selected) => {
 | 
				
			||||||
                if (ff !== undefined && searchValue.data?.length > 0 && !presetSearch.someMatchFound.data) {
 | 
					                if (ff !== undefined && searchValue.data?.length > 0 && !presetSearch.someMatchFound.data) {
 | 
				
			||||||
                    const t = new Tag(ff.key, searchValue.data)
 | 
					                    const t = fallbackTag.data;
 | 
				
			||||||
                    if (ff.addExtraTags) {
 | 
					                    if (ff.addExtraTags) {
 | 
				
			||||||
                        return new And([t, ...ff.addExtraTags])
 | 
					                        return new And([t, ...ff.addExtraTags])
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -436,13 +512,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
    private static GenerateMappingElement(
 | 
					    private static GenerateMappingElement(
 | 
				
			||||||
        state,
 | 
					        state,
 | 
				
			||||||
        tagsSource: UIEventSource<any>,
 | 
					        tagsSource: UIEventSource<any>,
 | 
				
			||||||
        mapping: {
 | 
					        mapping: Mapping, ifNot?: TagsFilter[]): InputElement<TagsFilter> {
 | 
				
			||||||
            if: TagsFilter,
 | 
					 | 
				
			||||||
            then: Translation,
 | 
					 | 
				
			||||||
            addExtraTags: Tag[],
 | 
					 | 
				
			||||||
            icon?: string,
 | 
					 | 
				
			||||||
            iconClass?: "small" | "medium" | "large" | "small-height"
 | 
					 | 
				
			||||||
        }, ifNot?: TagsFilter[]): InputElement<TagsFilter> {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let tagging: TagsFilter = mapping.if;
 | 
					        let tagging: TagsFilter = mapping.if;
 | 
				
			||||||
        if (ifNot !== undefined) {
 | 
					        if (ifNot !== undefined) {
 | 
				
			||||||
| 
						 | 
					@ -459,11 +529,7 @@ export default class TagRenderingQuestion extends Combine {
 | 
				
			||||||
            (t0, t1) => t1.shadows(t0));
 | 
					            (t0, t1) => t1.shadows(t0));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static GenerateMappingContent(mapping: {
 | 
					    private static GenerateMappingContent(mapping: Mapping, tagsSource: UIEventSource<any>, state: FeaturePipelineState): BaseUIElement {
 | 
				
			||||||
        then: Translation,
 | 
					 | 
				
			||||||
        icon?: string,
 | 
					 | 
				
			||||||
        iconClass?: "small" | "medium" | "large" | "small-height" | "medium-height" | "large-height"
 | 
					 | 
				
			||||||
    }, tagsSource: UIEventSource<any>, state: FeaturePipelineState): BaseUIElement {
 | 
					 | 
				
			||||||
        const text = new SubstitutedTranslation(mapping.then, tagsSource, state)
 | 
					        const text = new SubstitutedTranslation(mapping.then, tagsSource, state)
 | 
				
			||||||
        if (mapping.icon === undefined) {
 | 
					        if (mapping.icon === undefined) {
 | 
				
			||||||
            return text;
 | 
					            return text;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -164,9 +164,9 @@
 | 
				
			||||||
        "de": "Wie hoch ist der Bordstein?"
 | 
					        "de": "Wie hoch ist der Bordstein?"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "render": {
 | 
					      "render": {
 | 
				
			||||||
        "en": "Kerb height: {{kerb:height}}",
 | 
					        "en": "Kerb height: {kerb:height}",
 | 
				
			||||||
        "nl": "Stoeprandhoogte: {{kerb:height}}",
 | 
					        "nl": "Stoeprandhoogte: {kerb:height}",
 | 
				
			||||||
        "de": "Bordsteinhöhe: {{kerb:height}}"
 | 
					        "de": "Bordsteinhöhe: {kerb:height}"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "freeform": {
 | 
					      "freeform": {
 | 
				
			||||||
        "key": "kerb:height",
 | 
					        "key": "kerb:height",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,142 @@
 | 
				
			||||||
    "es": "Una capa que muestra aparcamientos para coches"
 | 
					    "es": "Una capa que muestra aparcamientos para coches"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "tagRenderings": [
 | 
					  "tagRenderings": [
 | 
				
			||||||
    "images"
 | 
					    "images",
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "id": "parking-type",
 | 
				
			||||||
 | 
					      "mappings": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=surface",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a surface parking lot",
 | 
				
			||||||
 | 
					            "nl": "Dit is een bovengronds parkeerterrein"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=street_side",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a parking bay next to a street",
 | 
				
			||||||
 | 
					            "nl": "Dit is een parkeerplek langs een weg"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=underground",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is an underground parking garage",
 | 
				
			||||||
 | 
					            "nl": "Dit is een ondergrondse parkeergarage"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=multi-storey",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a multi-storey parking garage",
 | 
				
			||||||
 | 
					            "nl": "Dit is een bovengrondse parkeergarage met meerdere verdiepingen"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=rooftop",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a rooftop parking deck",
 | 
				
			||||||
 | 
					            "nl": "Dit is een parkeerdek op een dak"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=lane",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a lane for parking on the road",
 | 
				
			||||||
 | 
					            "nl": "Dit is een strook voor parkeren op de weg"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=carports",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is parking covered by carports",
 | 
				
			||||||
 | 
					            "nl": "Dit is parking overdekt met carports"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=garage_boxes",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This a parking consisting of garage boxes",
 | 
				
			||||||
 | 
					            "nl": "Dit is een parking bestaande uit garageboxen"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=layby",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a parking on a layby",
 | 
				
			||||||
 | 
					            "nl": "Dit is een parkeerplek op een layby"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "parking=sheds",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "This is a parking consisting of sheds",
 | 
				
			||||||
 | 
					            "nl": "Dit is een parking bestaande uit schuren"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "question": {
 | 
				
			||||||
 | 
					        "en": "What kind of parking is this?",
 | 
				
			||||||
 | 
					        "nl": "Wat voor parking is dit?"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "id": "capacity-disabled",
 | 
				
			||||||
 | 
					      "freeform": {
 | 
				
			||||||
 | 
					        "key": "capacity:disabled",
 | 
				
			||||||
 | 
					        "type": "pnat",
 | 
				
			||||||
 | 
					        "placeholder": {
 | 
				
			||||||
 | 
					          "en": "Amount of parking spots reserved for disabled people",
 | 
				
			||||||
 | 
					          "nl": "Aantal parkeerplaatsen voor gehandicapten"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "mappings": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "capacity:disabled=yes",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "There are disabled parking spots, but it is not known how many",
 | 
				
			||||||
 | 
					            "nl": "Er zijn parkeerplaatsen voor gehandicapten, maar het is niet bekend hoeveel er zijn"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "hideInAnswer": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "if": "capacity:disabled=no",
 | 
				
			||||||
 | 
					          "then": {
 | 
				
			||||||
 | 
					            "en": "There are no disabled parking spots",
 | 
				
			||||||
 | 
					            "nl": "Er zijn geen parkeerplaatsen voor gehandicapten"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "hideInAnswer": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "question": {
 | 
				
			||||||
 | 
					        "en": "How many disabled parking spots are there at this parking?",
 | 
				
			||||||
 | 
					        "nl": "Hoeveel parkeerplaatsen voor gehandicapten zijn er op deze parking?"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "render": {
 | 
				
			||||||
 | 
					        "en": "There are {capacity:disabled} disabled parking spots",
 | 
				
			||||||
 | 
					        "nl": "Er zijn {capacity:disabled} parkeerplaatsen voor gehandicapten"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "id": "capacity",
 | 
				
			||||||
 | 
					      "freeform": {
 | 
				
			||||||
 | 
					        "key": "capacity",
 | 
				
			||||||
 | 
					        "type": "pnat",
 | 
				
			||||||
 | 
					        "placeholder": {
 | 
				
			||||||
 | 
					          "en": "Amount of parking spots",
 | 
				
			||||||
 | 
					          "nl": "Aantal parkeerplaatsen"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "question": {
 | 
				
			||||||
 | 
					        "en": "How many parking spots are there at this parking?",
 | 
				
			||||||
 | 
					        "nl": "Hoeveel parkeerplaatsen zijn er op deze parking?"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "render": {
 | 
				
			||||||
 | 
					        "en": "There are {capacity} parking spots",
 | 
				
			||||||
 | 
					        "nl": "Er zijn {capacity} parkeerplaatsen"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "presets": [
 | 
					  "presets": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -52,7 +187,7 @@
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "allowMove": {
 | 
					  "allowMove": {
 | 
				
			||||||
    "enableRelocation": false,
 | 
					    "enableRelocation": false,
 | 
				
			||||||
    "enableImproveAccuraccy": true
 | 
					    "enableImproveAccuracy": true
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "mapRendering": [
 | 
					  "mapRendering": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4122,7 +4122,7 @@
 | 
				
			||||||
                    "placeholder": "Höhe des Bordsteins"
 | 
					                    "placeholder": "Höhe des Bordsteins"
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "Wie hoch ist der Bordstein?",
 | 
					                "question": "Wie hoch ist der Bordstein?",
 | 
				
			||||||
                "render": "Bordsteinhöhe: {{kerb:height}}"
 | 
					                "render": "Bordsteinhöhe: {kerb:height}"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "kerb-type": {
 | 
					            "kerb-type": {
 | 
				
			||||||
                "mappings": {
 | 
					                "mappings": {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4193,7 +4193,7 @@
 | 
				
			||||||
                    "placeholder": "Height of the kerb"
 | 
					                    "placeholder": "Height of the kerb"
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "What is the height of this kerb?",
 | 
					                "question": "What is the height of this kerb?",
 | 
				
			||||||
                "render": "Kerb height: {{kerb:height}}"
 | 
					                "render": "Kerb height: {kerb:height}"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "kerb-type": {
 | 
					            "kerb-type": {
 | 
				
			||||||
                "mappings": {
 | 
					                "mappings": {
 | 
				
			||||||
| 
						 | 
					@ -4843,6 +4843,65 @@
 | 
				
			||||||
                "title": "a car parking"
 | 
					                "title": "a car parking"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "tagRenderings": {
 | 
				
			||||||
 | 
					            "capacity": {
 | 
				
			||||||
 | 
					                "freeform": {
 | 
				
			||||||
 | 
					                    "placeholder": "Amount of parking spots"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "How many parking spots are there at this parking?",
 | 
				
			||||||
 | 
					                "render": "There are {capacity} parking spots"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "capacity-disabled": {
 | 
				
			||||||
 | 
					                "freeform": {
 | 
				
			||||||
 | 
					                    "placeholder": "Amount of parking spots reserved for disabled people"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "There are disabled parking spots, but it is not known how many"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "There are no disabled parking spots"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "How many disabled parking spots are there at this parking?",
 | 
				
			||||||
 | 
					                "render": "There are {capacity:disabled} disabled parking spots"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "parking-type": {
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "This is a surface parking lot"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "This is a parking bay next to a street"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "2": {
 | 
				
			||||||
 | 
					                        "then": "This is an underground parking garage"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "3": {
 | 
				
			||||||
 | 
					                        "then": "This is a multi-storey parking garage"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "4": {
 | 
				
			||||||
 | 
					                        "then": "This is a rooftop parking deck"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "5": {
 | 
				
			||||||
 | 
					                        "then": "This is a lane for parking on the road"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "6": {
 | 
				
			||||||
 | 
					                        "then": "This is parking covered by carports"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "7": {
 | 
				
			||||||
 | 
					                        "then": "This a parking consisting of garage boxes"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "8": {
 | 
				
			||||||
 | 
					                        "then": "This is a parking on a layby"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "9": {
 | 
				
			||||||
 | 
					                        "then": "This is a parking consisting of sheds"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "What kind of parking is this?"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "title": {
 | 
					        "title": {
 | 
				
			||||||
            "render": "Car parking"
 | 
					            "render": "Car parking"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4053,7 +4053,7 @@
 | 
				
			||||||
                    "placeholder": "Hoogte van de stoeprand"
 | 
					                    "placeholder": "Hoogte van de stoeprand"
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                "question": "Hoe hoog is deze stoeprand?",
 | 
					                "question": "Hoe hoog is deze stoeprand?",
 | 
				
			||||||
                "render": "Stoeprandhoogte: {{kerb:height}}"
 | 
					                "render": "Stoeprandhoogte: {kerb:height}"
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "kerb-type": {
 | 
					            "kerb-type": {
 | 
				
			||||||
                "mappings": {
 | 
					                "mappings": {
 | 
				
			||||||
| 
						 | 
					@ -4535,6 +4535,65 @@
 | 
				
			||||||
                "title": "een parking voor auto's"
 | 
					                "title": "een parking voor auto's"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "tagRenderings": {
 | 
				
			||||||
 | 
					            "capacity": {
 | 
				
			||||||
 | 
					                "freeform": {
 | 
				
			||||||
 | 
					                    "placeholder": "Aantal parkeerplaatsen"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "Hoeveel parkeerplaatsen zijn er op deze parking?",
 | 
				
			||||||
 | 
					                "render": "Er zijn {capacity} parkeerplaatsen"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "capacity-disabled": {
 | 
				
			||||||
 | 
					                "freeform": {
 | 
				
			||||||
 | 
					                    "placeholder": "Aantal parkeerplaatsen voor gehandicapten"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "Er zijn parkeerplaatsen voor gehandicapten, maar het is niet bekend hoeveel er zijn"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "Er zijn geen parkeerplaatsen voor gehandicapten"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "Hoeveel parkeerplaatsen voor gehandicapten zijn er op deze parking?",
 | 
				
			||||||
 | 
					                "render": "Er zijn {capacity:disabled} parkeerplaatsen voor gehandicapten"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "parking-type": {
 | 
				
			||||||
 | 
					                "mappings": {
 | 
				
			||||||
 | 
					                    "0": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een bovengronds parkeerterrein"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "1": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een parkeerplek langs een weg"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "2": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een ondergrondse parkeergarage"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "3": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een bovengrondse parkeergarage met meerdere verdiepingen"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "4": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een parkeerdek op een dak"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "5": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een strook voor parkeren op de weg"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "6": {
 | 
				
			||||||
 | 
					                        "then": "Dit is parking overdekt met carports"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "7": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een parking bestaande uit garageboxen"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "8": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een parkeerplek op een layby"
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    "9": {
 | 
				
			||||||
 | 
					                        "then": "Dit is een parking bestaande uit schuren"
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "question": "Wat voor parking is dit?"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "title": {
 | 
					        "title": {
 | 
				
			||||||
            "render": "Parking voor auto's"
 | 
					            "render": "Parking voor auto's"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										188
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										188
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -44,7 +44,7 @@
 | 
				
			||||||
        "leaflet-providers": "^1.13.0",
 | 
					        "leaflet-providers": "^1.13.0",
 | 
				
			||||||
        "leaflet-simple-map-screenshoter": "^0.4.4",
 | 
					        "leaflet-simple-map-screenshoter": "^0.4.4",
 | 
				
			||||||
        "libphonenumber": "^0.0.9",
 | 
					        "libphonenumber": "^0.0.9",
 | 
				
			||||||
        "libphonenumber-js": "^1.7.55",
 | 
					        "libphonenumber-js": "^1.10.8",
 | 
				
			||||||
        "lz-string": "^1.4.4",
 | 
					        "lz-string": "^1.4.4",
 | 
				
			||||||
        "mangrove-reviews": "^0.1.3",
 | 
					        "mangrove-reviews": "^0.1.3",
 | 
				
			||||||
        "moment": "^2.29.2",
 | 
					        "moment": "^2.29.2",
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,6 @@
 | 
				
			||||||
        "papaparse": "^5.3.1",
 | 
					        "papaparse": "^5.3.1",
 | 
				
			||||||
        "parcel": "^1.2.4",
 | 
					        "parcel": "^1.2.4",
 | 
				
			||||||
        "prompt-sync": "^4.2.0",
 | 
					        "prompt-sync": "^4.2.0",
 | 
				
			||||||
        "svg-resizer": "github:vieron/svg-resizer",
 | 
					 | 
				
			||||||
        "tailwindcss": "^2.2.15",
 | 
					        "tailwindcss": "^2.2.15",
 | 
				
			||||||
        "togpx": "^0.5.4",
 | 
					        "togpx": "^0.5.4",
 | 
				
			||||||
        "tslint": "^6.1.3",
 | 
					        "tslint": "^6.1.3",
 | 
				
			||||||
| 
						 | 
					@ -4772,14 +4771,6 @@
 | 
				
			||||||
        "simple-swizzle": "^0.2.2"
 | 
					        "simple-swizzle": "^0.2.2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/colors": {
 | 
					 | 
				
			||||||
      "version": "0.5.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=",
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=0.1.90"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/combined-stream": {
 | 
					    "node_modules/combined-stream": {
 | 
				
			||||||
      "version": "1.0.8",
 | 
					      "version": "1.0.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 | 
				
			||||||
| 
						 | 
					@ -7024,36 +7015,6 @@
 | 
				
			||||||
      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
 | 
					      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/fs-extra": {
 | 
					 | 
				
			||||||
      "version": "0.8.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.8.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-Dld5/7/t9RG8dVWVx/A8BtS0Po0=",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "jsonfile": "~1.1.0",
 | 
					 | 
				
			||||||
        "mkdirp": "0.3.x",
 | 
					 | 
				
			||||||
        "ncp": "~0.4.2",
 | 
					 | 
				
			||||||
        "rimraf": "~2.2.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/fs-extra/node_modules/jsonfile": {
 | 
					 | 
				
			||||||
      "version": "1.1.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.1.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-2k/WrXfxolUgPqY8e8Mtwx72RDM="
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/fs-extra/node_modules/mkdirp": {
 | 
					 | 
				
			||||||
      "version": "0.3.5",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=",
 | 
					 | 
				
			||||||
      "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/fs-extra/node_modules/rimraf": {
 | 
					 | 
				
			||||||
      "version": "2.2.8",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=",
 | 
					 | 
				
			||||||
      "bin": {
 | 
					 | 
				
			||||||
        "rimraf": "bin.js"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/fs.realpath": {
 | 
					    "node_modules/fs.realpath": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
				
			||||||
| 
						 | 
					@ -9177,9 +9138,9 @@
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/libphonenumber-js": {
 | 
					    "node_modules/libphonenumber-js": {
 | 
				
			||||||
      "version": "1.9.17",
 | 
					      "version": "1.10.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.17.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.8.tgz",
 | 
				
			||||||
      "integrity": "sha512-ElJki901OynMg1l+evooPH1VyHrECuLqpgc12z2BkK25dFU5lUKTuMHEYV2jXxvtns/PIuJax56cBeoSK7ANow=="
 | 
					      "integrity": "sha512-MGgHrKRGE7sg7y0DikHybRDgTXcYv4HL+WwhDm5UAiChCNb5tcy5OEaU8XTTt5bDBwhZGCJNxoGMVBpZ4RfhIg=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/lilconfig": {
 | 
					    "node_modules/lilconfig": {
 | 
				
			||||||
      "version": "2.0.3",
 | 
					      "version": "2.0.3",
 | 
				
			||||||
| 
						 | 
					@ -9947,14 +9908,6 @@
 | 
				
			||||||
      "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
 | 
					      "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/ncp": {
 | 
					 | 
				
			||||||
      "version": "0.4.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ=",
 | 
					 | 
				
			||||||
      "bin": {
 | 
					 | 
				
			||||||
        "ncp": "bin/ncp"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/neo-async": {
 | 
					    "node_modules/neo-async": {
 | 
				
			||||||
      "version": "2.6.2",
 | 
					      "version": "2.6.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
 | 
				
			||||||
| 
						 | 
					@ -10076,21 +10029,6 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.76.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.76.tgz",
 | 
				
			||||||
      "integrity": "sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA=="
 | 
					      "integrity": "sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/nomnom": {
 | 
					 | 
				
			||||||
      "version": "1.6.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=",
 | 
					 | 
				
			||||||
      "deprecated": "Package no longer supported. Contact support@npmjs.com for more info.",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "colors": "0.5.x",
 | 
					 | 
				
			||||||
        "underscore": "~1.4.4"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/nomnom/node_modules/underscore": {
 | 
					 | 
				
			||||||
      "version": "1.4.4",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/normalize-package-data": {
 | 
					    "node_modules/normalize-package-data": {
 | 
				
			||||||
      "version": "2.5.0",
 | 
					      "version": "2.5.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
 | 
				
			||||||
| 
						 | 
					@ -13582,17 +13520,6 @@
 | 
				
			||||||
        "node": ">=0.10.0"
 | 
					        "node": ">=0.10.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/shelljs": {
 | 
					 | 
				
			||||||
      "version": "0.2.6",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-kEktcv/MgVmXa6umL7D2iE8MM3g=",
 | 
					 | 
				
			||||||
      "bin": {
 | 
					 | 
				
			||||||
        "shjs": "bin/shjs"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=0.8.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/signal-exit": {
 | 
					    "node_modules/signal-exit": {
 | 
				
			||||||
      "version": "3.0.3",
 | 
					      "version": "3.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
 | 
				
			||||||
| 
						 | 
					@ -14314,30 +14241,6 @@
 | 
				
			||||||
        "node": ">=6.9.5"
 | 
					        "node": ">=6.9.5"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/svg-resizer": {
 | 
					 | 
				
			||||||
      "version": "0.0.1",
 | 
					 | 
				
			||||||
      "resolved": "git+ssh://git@github.com/vieron/svg-resizer.git#00968cb3e7248533ab9451ce7dffa8af288e4f4a",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "fs-extra": "~0.8.1",
 | 
					 | 
				
			||||||
        "lodash": "~2.4.1",
 | 
					 | 
				
			||||||
        "nomnom": "~1.6.2",
 | 
					 | 
				
			||||||
        "shelljs": "~0.2.6",
 | 
					 | 
				
			||||||
        "xml2js": "~0.4.2"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "bin": {
 | 
					 | 
				
			||||||
        "svg-resizer": "svg-resizer.js"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/svg-resizer/node_modules/lodash": {
 | 
					 | 
				
			||||||
      "version": "2.4.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
 | 
					 | 
				
			||||||
      "engines": [
 | 
					 | 
				
			||||||
        "node",
 | 
					 | 
				
			||||||
        "rhino"
 | 
					 | 
				
			||||||
      ]
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/svgo": {
 | 
					    "node_modules/svgo": {
 | 
				
			||||||
      "version": "1.3.2",
 | 
					      "version": "1.3.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
 | 
				
			||||||
| 
						 | 
					@ -20595,11 +20498,6 @@
 | 
				
			||||||
        "simple-swizzle": "^0.2.2"
 | 
					        "simple-swizzle": "^0.2.2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "colors": {
 | 
					 | 
				
			||||||
      "version": "0.5.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q="
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "combined-stream": {
 | 
					    "combined-stream": {
 | 
				
			||||||
      "version": "1.0.8",
 | 
					      "version": "1.0.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 | 
				
			||||||
| 
						 | 
					@ -22391,34 +22289,6 @@
 | 
				
			||||||
      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
 | 
					      "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "fs-extra": {
 | 
					 | 
				
			||||||
      "version": "0.8.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.8.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-Dld5/7/t9RG8dVWVx/A8BtS0Po0=",
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "jsonfile": "~1.1.0",
 | 
					 | 
				
			||||||
        "mkdirp": "0.3.x",
 | 
					 | 
				
			||||||
        "ncp": "~0.4.2",
 | 
					 | 
				
			||||||
        "rimraf": "~2.2.0"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "jsonfile": {
 | 
					 | 
				
			||||||
          "version": "1.1.1",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-1.1.1.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha1-2k/WrXfxolUgPqY8e8Mtwx72RDM="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "mkdirp": {
 | 
					 | 
				
			||||||
          "version": "0.3.5",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc="
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        "rimraf": {
 | 
					 | 
				
			||||||
          "version": "2.2.8",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI="
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "fs.realpath": {
 | 
					    "fs.realpath": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
				
			||||||
| 
						 | 
					@ -24042,9 +23912,9 @@
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "libphonenumber-js": {
 | 
					    "libphonenumber-js": {
 | 
				
			||||||
      "version": "1.9.17",
 | 
					      "version": "1.10.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.17.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.8.tgz",
 | 
				
			||||||
      "integrity": "sha512-ElJki901OynMg1l+evooPH1VyHrECuLqpgc12z2BkK25dFU5lUKTuMHEYV2jXxvtns/PIuJax56cBeoSK7ANow=="
 | 
					      "integrity": "sha512-MGgHrKRGE7sg7y0DikHybRDgTXcYv4HL+WwhDm5UAiChCNb5tcy5OEaU8XTTt5bDBwhZGCJNxoGMVBpZ4RfhIg=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "lilconfig": {
 | 
					    "lilconfig": {
 | 
				
			||||||
      "version": "2.0.3",
 | 
					      "version": "2.0.3",
 | 
				
			||||||
| 
						 | 
					@ -24635,11 +24505,6 @@
 | 
				
			||||||
      "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
 | 
					      "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ncp": {
 | 
					 | 
				
			||||||
      "version": "0.4.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.4.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-q8xsvT7C7Spyn/bnwfqPAXhKhXQ="
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "neo-async": {
 | 
					    "neo-async": {
 | 
				
			||||||
      "version": "2.6.2",
 | 
					      "version": "2.6.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
 | 
				
			||||||
| 
						 | 
					@ -24755,22 +24620,6 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.76.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.76.tgz",
 | 
				
			||||||
      "integrity": "sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA=="
 | 
					      "integrity": "sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "nomnom": {
 | 
					 | 
				
			||||||
      "version": "1.6.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=",
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "colors": "0.5.x",
 | 
					 | 
				
			||||||
        "underscore": "~1.4.4"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "underscore": {
 | 
					 | 
				
			||||||
          "version": "1.4.4",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ="
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "normalize-package-data": {
 | 
					    "normalize-package-data": {
 | 
				
			||||||
      "version": "2.5.0",
 | 
					      "version": "2.5.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
 | 
				
			||||||
| 
						 | 
					@ -27471,11 +27320,6 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
 | 
					      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "shelljs": {
 | 
					 | 
				
			||||||
      "version": "0.2.6",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.2.6.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha1-kEktcv/MgVmXa6umL7D2iE8MM3g="
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "signal-exit": {
 | 
					    "signal-exit": {
 | 
				
			||||||
      "version": "3.0.3",
 | 
					      "version": "3.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
 | 
				
			||||||
| 
						 | 
					@ -28038,24 +27882,6 @@
 | 
				
			||||||
      "integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==",
 | 
					      "integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==",
 | 
				
			||||||
      "optional": true
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "svg-resizer": {
 | 
					 | 
				
			||||||
      "version": "git+ssh://git@github.com/vieron/svg-resizer.git#00968cb3e7248533ab9451ce7dffa8af288e4f4a",
 | 
					 | 
				
			||||||
      "from": "svg-resizer@github:vieron/svg-resizer",
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "fs-extra": "~0.8.1",
 | 
					 | 
				
			||||||
        "lodash": "~2.4.1",
 | 
					 | 
				
			||||||
        "nomnom": "~1.6.2",
 | 
					 | 
				
			||||||
        "shelljs": "~0.2.6",
 | 
					 | 
				
			||||||
        "xml2js": "~0.4.2"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "lodash": {
 | 
					 | 
				
			||||||
          "version": "2.4.2",
 | 
					 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
 | 
					 | 
				
			||||||
          "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4="
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "svgo": {
 | 
					    "svgo": {
 | 
				
			||||||
      "version": "1.3.2",
 | 
					      "version": "1.3.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +102,7 @@
 | 
				
			||||||
    "leaflet-providers": "^1.13.0",
 | 
					    "leaflet-providers": "^1.13.0",
 | 
				
			||||||
    "leaflet-simple-map-screenshoter": "^0.4.4",
 | 
					    "leaflet-simple-map-screenshoter": "^0.4.4",
 | 
				
			||||||
    "libphonenumber": "^0.0.9",
 | 
					    "libphonenumber": "^0.0.9",
 | 
				
			||||||
    "libphonenumber-js": "^1.7.55",
 | 
					    "libphonenumber-js": "^1.10.8",
 | 
				
			||||||
    "lz-string": "^1.4.4",
 | 
					    "lz-string": "^1.4.4",
 | 
				
			||||||
    "mangrove-reviews": "^0.1.3",
 | 
					    "mangrove-reviews": "^0.1.3",
 | 
				
			||||||
    "moment": "^2.29.2",
 | 
					    "moment": "^2.29.2",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue