diff --git a/Logic/DetermineLayout.ts b/Logic/DetermineLayout.ts index 4fae151d3..36233b73b 100644 --- a/Logic/DetermineLayout.ts +++ b/Logic/DetermineLayout.ts @@ -126,7 +126,7 @@ export default class DetermineLayout { .AttachTo("centermessage"); } - private static prepCustomTheme(json: any, sourceUrl?: string): LayoutConfig { + private static prepCustomTheme(json: any, sourceUrl?: string, forceId?: string): LayoutConfig { if(json.layers === undefined && json.tagRenderings !== undefined){ const iconTr = json.mapRendering.map(mr => mr.icon).find(icon => icon !== undefined) @@ -161,6 +161,7 @@ export default class DetermineLayout { json = new PrepareTheme(converState).convertStrict(json, "While preparing a dynamic theme") console.log("The layoutconfig is ", json) + json.id = forceId ?? json.id return new LayoutConfig(json, false, { definitionRaw: JSON.stringify(raw, null, " "), @@ -178,9 +179,13 @@ export default class DetermineLayout { let parsed = await Utils.downloadJson(link) try { - parsed.id = link; + let forcedId = parsed.id + const url = new URL(link) + if(!(url.hostname === "localhost" || url.hostname === "127.0.0.1")){ + forcedId = link; + } console.log("Loaded remote link:", link) - return DetermineLayout.prepCustomTheme(parsed, link) + return DetermineLayout.prepCustomTheme(parsed, link, forcedId); } catch (e) { console.error(e) DetermineLayout.ShowErrorOnCustomTheme( diff --git a/Logic/Tags/TagUtils.ts b/Logic/Tags/TagUtils.ts index b249291de..fb6aa22b7 100644 --- a/Logic/Tags/TagUtils.ts +++ b/Logic/Tags/TagUtils.ts @@ -10,6 +10,9 @@ import {AndOrTagConfigJson} from "../../Models/ThemeConfig/Json/TagConfigJson"; import {isRegExp} from "util"; import * as key_counts from "../../assets/key_totals.json" +type Tags = Record +type OsmTags = Tags & {id: string} + export class TagUtils { private static keyCounts: { keys: any, tags: any } = key_counts["default"] ?? key_counts private static comparators @@ -56,11 +59,17 @@ export class TagUtils { return true; } + static SplitKeys(tagsFilters: TagsFilter[]): Record { + return this.SplitKeysRegex(tagsFilters, false); + } + /*** * Creates a hash {key --> [values : string | RegexTag ]}, with all the values present in the tagsfilter + * + * TagUtils.SplitKeysRegex([new Tag("isced:level", "bachelor; master")], true) // => {"isced:level": ["bachelor","master"]} */ - static SplitKeys(tagsFilters: TagsFilter[], allowRegex = false) { - const keyValues = {} // Map string -> (string | RegexTag)[] + static SplitKeysRegex(tagsFilters: TagsFilter[], allowRegex: boolean): Record { + const keyValues: Record = {} tagsFilters = [...tagsFilters] // copy all, use as queue while (tagsFilters.length > 0) { const tagsFilter = tagsFilters.shift(); @@ -78,7 +87,7 @@ export class TagUtils { if (keyValues[tagsFilter.key] === undefined) { keyValues[tagsFilter.key] = []; } - keyValues[tagsFilter.key].push(...tagsFilter.value.split(";")); + keyValues[tagsFilter.key].push(...tagsFilter.value.split(";").map(s => s.trim())); continue; } @@ -130,19 +139,23 @@ export class TagUtils { /** * Returns true if the properties match the tagsFilter, interpreted as a multikey. * Note that this might match a regex tag - * @param tag - * @param properties - * @constructor + * + * TagUtils.MatchesMultiAnswer(new Tag("isced:level","bachelor"), {"isced:level":"bachelor; master"}) // => true + * TagUtils.MatchesMultiAnswer(new Tag("isced:level","master"), {"isced:level":"bachelor;master"}) // => true + * TagUtils.MatchesMultiAnswer(new Tag("isced:level","doctorate"), {"isced:level":"bachelor; master"}) // => false + * + * // should match with a space too + * TagUtils.MatchesMultiAnswer(new Tag("isced:level","master"), {"isced:level":"bachelor; master"}) // => true */ - static MatchesMultiAnswer(tag: TagsFilter, properties: any): boolean { - const splitted = TagUtils.SplitKeys([tag], true); + static MatchesMultiAnswer(tag: TagsFilter, properties: Tags): boolean { + const splitted = TagUtils.SplitKeysRegex([tag], true); for (const splitKey in splitted) { const neededValues = splitted[splitKey]; if (properties[splitKey] === undefined) { return false; } - const actualValue = properties[splitKey].split(";"); + const actualValue = properties[splitKey].split(";").map(s => s.trim()); for (const neededValue of neededValues) { if (neededValue instanceof RegexTag) { diff --git a/Models/ThemeConfig/Conversion/FixImages.ts b/Models/ThemeConfig/Conversion/FixImages.ts index cdda7ff46..f58294cbb 100644 --- a/Models/ThemeConfig/Conversion/FixImages.ts +++ b/Models/ThemeConfig/Conversion/FixImages.ts @@ -205,6 +205,11 @@ export class FixImages extends DesugaringStep { let relative = url.protocol + "//" + url.host + url.pathname relative = relative.substring(0, relative.lastIndexOf("/")) const self = this; + + if(relative.endsWith("assets/generated/themes")){ + warnings.push("Detected 'assets/generated/themes' as relative URL. I'm assuming that you are loading your file for the MC-repository, so I'm rewriting all image links as if they were absolute instead of relative") + relative = absolute + } function replaceString(leaf: string) { if (self._knownImages.has(leaf)) { diff --git a/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts b/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts index 5d9ae5862..dc25f2afc 100644 --- a/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts +++ b/Models/ThemeConfig/Conversion/LegacyJsonConvert.ts @@ -100,7 +100,7 @@ export class UpdateLegacyLayer extends DesugaringStep any), travelledPath: string[] = []) { + public static WalkPath(path: string[], object: any, replaceLeaf: ((leaf: any, travelledPath: string[]) => any), travelledPath: string[] = []) : void { + if(object == null){ + return; + } + const head = path[0] if (path.length === 1) { // We have reached the leaf