From 36aed9984341e9464a9ff29299c3ab10a1024e5f Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Fri, 3 Feb 2023 03:57:30 +0100 Subject: [PATCH] Fix generateLayerOverview, drop priviliged 'icons.json' from code --- Customizations/SharedTagRenderings.ts | 25 +-- Logic/DetermineLayout.ts | 3 +- Models/ThemeConfig/Conversion/FixImages.ts | 47 +++-- Models/ThemeConfig/Conversion/PrepareLayer.ts | 163 ++++++++++++++---- Models/ThemeConfig/Conversion/Validation.ts | 127 +++++++------- Models/ThemeConfig/LayoutConfig.ts | 10 +- Models/ThemeConfig/PointRenderingConfig.ts | 12 +- package.json | 2 +- scripts/generateLayerOverview.ts | 43 ++--- .../Conversion/PrepareTheme.spec.ts | 2 +- 10 files changed, 267 insertions(+), 167 deletions(-) diff --git a/Customizations/SharedTagRenderings.ts b/Customizations/SharedTagRenderings.ts index 11b8954f4..85877b7e5 100644 --- a/Customizations/SharedTagRenderings.ts +++ b/Customizations/SharedTagRenderings.ts @@ -1,5 +1,4 @@ import questions from "../assets/tagRenderings/questions.json" -import icons from "../assets/tagRenderings/icons.json" import { Utils } from "../Utils" import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig" import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson" @@ -14,11 +13,9 @@ export default class SharedTagRenderings { SharedTagRenderings.generatedSharedFields() public static SharedTagRenderingJson: Map = SharedTagRenderings.generatedSharedFieldsJsons() - public static SharedIcons: Map = - SharedTagRenderings.generatedSharedFields(true) - private static generatedSharedFields(iconsOnly = false): Map { - const configJsons = SharedTagRenderings.generatedSharedFieldsJsons(iconsOnly) + private static generatedSharedFields(): Map { + const configJsons = SharedTagRenderings.generatedSharedFieldsJsons() const d = new Map() for (const key of Array.from(configJsons.keys())) { try { @@ -31,7 +28,7 @@ export default class SharedTagRenderings { console.error( "BUG: could not parse", key, - " from questions.json or icons.json - this error happened during the build step of the SharedTagRenderings", + " from questions.json - this error happened during the build step of the SharedTagRenderings", e ) } @@ -40,24 +37,14 @@ export default class SharedTagRenderings { return d } - private static generatedSharedFieldsJsons( - iconsOnly = false - ): Map { + private static generatedSharedFieldsJsons(): Map { const dict = new Map() - if (!iconsOnly) { - for (const key in questions) { - if (key === "id") { - continue - } - dict.set(key, questions[key]) - } - } - for (const key in icons) { + for (const key in questions) { if (key === "id") { continue } - dict.set(key, icons[key]) + dict.set(key, questions[key]) } dict.forEach((value, key) => { diff --git a/Logic/DetermineLayout.ts b/Logic/DetermineLayout.ts index 072581d46..473bd5f74 100644 --- a/Logic/DetermineLayout.ts +++ b/Logic/DetermineLayout.ts @@ -194,8 +194,7 @@ export default class DetermineLayout { let { errors } = new ValidateThemeAndLayers( new DoesImageExist(new Set(), (_) => true), "", - false, - SharedTagRenderings.SharedTagRendering + false ).convert(json, "validation") if (errors.length > 0) { throw "Detected errors: " + errors.join("\n") diff --git a/Models/ThemeConfig/Conversion/FixImages.ts b/Models/ThemeConfig/Conversion/FixImages.ts index a873abb6d..2b5122007 100644 --- a/Models/ThemeConfig/Conversion/FixImages.ts +++ b/Models/ThemeConfig/Conversion/FixImages.ts @@ -5,9 +5,12 @@ import metapaths from "../../../assets/layoutconfigmeta.json" import tagrenderingmetapaths from "../../../assets/questionabletagrenderingconfigmeta.json" import Translations from "../../../UI/i18n/Translations" -export class ExtractImages extends Conversion { +export class ExtractImages extends Conversion< + LayoutConfigJson, + { path: string; context: string }[] +> { private _isOfficial: boolean - private _sharedTagRenderings: Map + private _sharedTagRenderings: Set private static readonly layoutMetaPaths = metapaths.filter( (mp) => @@ -16,7 +19,7 @@ export class ExtractImages extends Conversion { ) private static readonly tagRenderingMetaPaths = tagrenderingmetapaths - constructor(isOfficial: boolean, sharedTagRenderings: Map) { + constructor(isOfficial: boolean, sharedTagRenderings: Set) { super("Extract all images from a layoutConfig using the meta paths.", [], "ExctractImages") this._isOfficial = isOfficial this._sharedTagRenderings = sharedTagRenderings @@ -79,8 +82,8 @@ export class ExtractImages extends Conversion { convert( json: LayoutConfigJson, context: string - ): { result: string[]; errors: string[]; warnings: string[] } { - const allFoundImages: string[] = [] + ): { result: { path: string; context: string }[]; errors: string[]; warnings: string[] } { + const allFoundImages: { path: string; context: string }[] = [] const errors = [] const warnings = [] for (const metapath of ExtractImages.layoutMetaPaths) { @@ -108,7 +111,7 @@ export class ExtractImages extends Conversion { continue } - allFoundImages.push(foundImage) + allFoundImages.push({ path: foundImage, context: context + "." + path }) } else { // This is a tagRendering. // Either every rendered value might be an icon @@ -137,7 +140,10 @@ export class ExtractImages extends Conversion { JSON.stringify(img.leaf) ) } else { - allFoundImages.push(img.leaf) + allFoundImages.push({ + path: img.leaf, + context: context + "." + path, + }) } } if (!allRenderedValuesAreImages && isImage) { @@ -146,7 +152,12 @@ export class ExtractImages extends Conversion { ...Translations.T( img.leaf, "extract_images from " + img.path.join(".") - ).ExtractImages(false) + ) + .ExtractImages(false) + .map((path) => ({ + path, + context: context + "." + path, + })) ) } } @@ -166,15 +177,19 @@ export class ExtractImages extends Conversion { } } - const splitParts = [] - .concat( - ...Utils.NoNull(allFoundImages) - .map((img) => img["path"] ?? img) - .map((img) => img.split(";")) + const cleanedImages: { path: string; context: string }[] = [] + + for (const foundImage of allFoundImages) { + // Split "circle:white;./assets/layers/.../something.svg" into ["circle", "./assets/layers/.../something.svg"] + const allPaths = Utils.NoNull( + Utils.NoEmpty(foundImage.path?.split(";")?.map((part) => part.split(":")[0])) ) - .map((img) => img.split(":")[0]) - .filter((img) => img !== "") - return { result: Utils.Dedup(splitParts), errors, warnings } + for (const path of allPaths) { + cleanedImages.push({ path, context: foundImage.context }) + } + } + + return { result: cleanedImages, errors, warnings } } } diff --git a/Models/ThemeConfig/Conversion/PrepareLayer.ts b/Models/ThemeConfig/Conversion/PrepareLayer.ts index fb00edb80..10b021c75 100644 --- a/Models/ThemeConfig/Conversion/PrepareLayer.ts +++ b/Models/ThemeConfig/Conversion/PrepareLayer.ts @@ -7,29 +7,24 @@ import { FirstOf, Fuse, On, - SetDefault, -} from "./Conversion" -import { LayerConfigJson } from "../Json/LayerConfigJson" -import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" -import { Utils } from "../../../Utils" -import RewritableConfigJson from "../Json/RewritableConfigJson" -import SpecialVisualizations from "../../../UI/SpecialVisualizations" -import Translations from "../../../UI/i18n/Translations" -import { Translation } from "../../../UI/i18n/Translation" -import tagrenderingconfigmeta from "../../../assets/tagrenderingconfigmeta.json" -import { AddContextToTranslations } from "./AddContextToTranslations" -import FilterConfigJson from "../Json/FilterConfigJson" -import predifined_filters from "../../../assets/layers/filters/filters.json" + SetDefault +} from "./Conversion"; +import { LayerConfigJson } from "../Json/LayerConfigJson"; +import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"; +import { Utils } from "../../../Utils"; +import RewritableConfigJson from "../Json/RewritableConfigJson"; +import SpecialVisualizations from "../../../UI/SpecialVisualizations"; +import Translations from "../../../UI/i18n/Translations"; +import { Translation } from "../../../UI/i18n/Translation"; +import tagrenderingconfigmeta from "../../../assets/tagrenderingconfigmeta.json"; +import { AddContextToTranslations } from "./AddContextToTranslations"; +import FilterConfigJson from "../Json/FilterConfigJson"; +import predifined_filters from "../../../assets/layers/filters/filters.json"; +import { TagConfigJson } from "../Json/TagConfigJson"; +import PointRenderingConfigJson from "../Json/PointRenderingConfigJson"; +import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"; class ExpandFilter extends DesugaringStep { - private static load_filters(): Map { - let filters = new Map() - for (const filter of predifined_filters.filter) { - filters.set(filter.id, filter) - } - return filters - } - private static readonly predefinedFilters = ExpandFilter.load_filters() constructor() { @@ -40,6 +35,14 @@ class ExpandFilter extends DesugaringStep { ) } + private static load_filters(): Map { + let filters = new Map() + for (const filter of predifined_filters.filter) { + filters.set(filter.id, filter) + } + return filters + } + convert( json: LayerConfigJson, context: string @@ -128,6 +131,37 @@ class ExpandTagRendering extends Conversion< } private lookup(name: string): TagRenderingConfigJson[] { + const direct = this.directLookup(name) + if (direct === undefined) { + return undefined + } + const result: TagRenderingConfigJson[] = [] + for (const tagRenderingConfigJson of direct) { + if (tagRenderingConfigJson["builtin"] !== undefined) { + let nm: string | string[] = tagRenderingConfigJson["builtin"] + let indirect: TagRenderingConfigJson[] + if (typeof nm === "string") { + indirect = this.lookup(nm) + } else { + indirect = [].concat(...nm.map((n) => this.lookup(n))) + } + for (let foundTr of indirect) { + foundTr = Utils.Clone(foundTr) + Utils.Merge(tagRenderingConfigJson["override"] ?? {}, foundTr) + foundTr.id = tagRenderingConfigJson.id ?? foundTr.id + result.push(foundTr) + } + } else { + result.push(tagRenderingConfigJson) + } + } + return result + } + + /** + * Looks up a tagRendering based on the name. + */ + private directLookup(name: string): TagRenderingConfigJson[] { const state = this._state if (state.tagRenderings.has(name)) { return [state.tagRenderings.get(name)] @@ -747,6 +781,79 @@ export class RewriteSpecial extends DesugaringStep { } } +class ExpandIconBadges extends DesugaringStep { + private _state: DesugaringContext + private _layer: LayerConfigJson + private _expand: ExpandTagRendering + + constructor(state: DesugaringContext, layer: LayerConfigJson) { + super("Expands shorthand properties on iconBadges", ["iconBadges"], "ExpandIconBadges") + this._state = state + this._layer = layer + this._expand = new ExpandTagRendering(state, layer) + } + + convert( + json: PointRenderingConfigJson | LineRenderingConfigJson, + context: string + ): { + result: PointRenderingConfigJson | LineRenderingConfigJson + errors?: string[] + warnings?: string[] + information?: string[] + } { + if (!json["iconBadges"]) { + return { result: json } + } + const badgesJson = (json).iconBadges + + const iconBadges: { if: TagConfigJson; then: string | TagRenderingConfigJson }[] = [] + + const errs: string[] = [] + const warns: string[] = [] + for (let i = 0; i < badgesJson.length; i++) { + const iconBadge: { if: TagConfigJson; then: string | TagRenderingConfigJson } = + badgesJson[i] + const { errors, result, warnings } = this._expand.convert( + iconBadge.then, + context + ".iconBadges[" + i + "]" + ) + errs.push(...errors) + warns.push(...warnings) + if (result === undefined) { + iconBadges.push(iconBadge) + continue + } + + iconBadges.push( + ...result.map((resolved) => ({ + if: iconBadge.if, + then: resolved, + })) + ) + } + + return { + result: { ...json, iconBadges }, + errors: errs, + warnings: warns, + } + } +} + +class PreparePointRendering extends Fuse { + constructor(state: DesugaringContext, layer: LayerConfigJson) { + super( + "Prepares point renderings by expanding 'icon' and 'iconBadges'", + new On( + "icon", + new FirstOf(new ExpandTagRendering(state, layer, { applyCondition: false })) + ), + new ExpandIconBadges(state, layer) + ) + } +} + export class PrepareLayer extends Fuse { constructor(state: DesugaringContext) { super( @@ -755,19 +862,11 @@ export class PrepareLayer extends Fuse { new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)), new On("tagRenderings", (layer) => new Concat(new ExpandTagRendering(state, layer))), new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)), - new On( + new On<(PointRenderingConfigJson | LineRenderingConfigJson)[], LayerConfigJson>( "mapRendering", - (layer) => - new Each( - new On( - "icon", - new FirstOf( - new ExpandTagRendering(state, layer, { applyCondition: false }) - ) - ) - ) + (layer) => new Each(new PreparePointRendering(state, layer)) ), - new SetDefault("titleIcons", ["defaults"]), + new SetDefault("titleIcons", ["icons.defaults"]), new On("titleIcons", (layer) => new Concat(new ExpandTagRendering(state, layer))), new ExpandFilter() ) diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index 6e366b64b..ff895007e 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -59,13 +59,16 @@ class ValidateLanguageCompleteness extends DesugaringStep { export class DoesImageExist extends DesugaringStep { private readonly _knownImagePaths: Set + private readonly _ignore?: Set private readonly doesPathExist: (path: string) => boolean = undefined constructor( knownImagePaths: Set, - checkExistsSync: (path: string) => boolean = undefined + checkExistsSync: (path: string) => boolean = undefined, + ignore?: Set ) { super("Checks if an image exists", [], "DoesImageExist") + this._ignore = ignore this._knownImagePaths = knownImagePaths this.doesPathExist = checkExistsSync } @@ -74,6 +77,10 @@ export class DoesImageExist extends DesugaringStep { image: string, context: string ): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } { + if (this._ignore?.has(image)) { + return { result: image } + } + const errors = [] const warnings = [] const information = [] @@ -123,20 +130,23 @@ class ValidateTheme extends DesugaringStep { */ private readonly _path?: string private readonly _isBuiltin: boolean - private _sharedTagRenderings: Map + //private readonly _sharedTagRenderings: Map private readonly _validateImage: DesugaringStep + private readonly _extractImages: ExtractImages = undefined constructor( doesImageExist: DoesImageExist, path: string, isBuiltin: boolean, - sharedTagRenderings: Map + sharedTagRenderings?: Set ) { super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme") this._validateImage = doesImageExist this._path = path this._isBuiltin = isBuiltin - this._sharedTagRenderings = sharedTagRenderings + if (sharedTagRenderings) { + this._extractImages = new ExtractImages(this._isBuiltin, sharedTagRenderings) + } } convert( @@ -168,13 +178,10 @@ class ValidateTheme extends DesugaringStep { } } } - if (this._isBuiltin) { + if (this._isBuiltin && this._extractImages !== undefined) { // Check images: are they local, are the licenses there, is the theme icon square, ... - const images = new ExtractImages( - this._isBuiltin, - this._sharedTagRenderings - ).convertStrict(json, "validation") - const remoteImages = images.filter((img) => img.indexOf("http") == 0) + const images = this._extractImages.convertStrict(json, "validation") + const remoteImages = images.filter((img) => img.path.indexOf("http") == 0) for (const remoteImage of remoteImages) { errors.push( "Found a remote image: " + @@ -186,8 +193,8 @@ class ValidateTheme extends DesugaringStep { } for (const image of images) { this._validateImage.convertJoin( - image, - context === undefined ? "" : ` in a layer defined in the theme ${context}`, + image.path, + context === undefined ? "" : ` in the theme ${context} at ${image.context}`, errors, warnings, information @@ -267,7 +274,7 @@ export class ValidateThemeAndLayers extends Fuse { doesImageExist: DoesImageExist, path: string, isBuiltin: boolean, - sharedTagRenderings: Map + sharedTagRenderings?: Set ) { super( "Validates a theme and the contained layers", @@ -878,53 +885,6 @@ export class DetectDuplicateFilters extends DesugaringStep<{ ) } - /** - * Add all filter options into 'perOsmTag' - */ - private addLayerFilters( - layer: LayerConfigJson, - perOsmTag: Map< - string, - { - layer: LayerConfigJson - layout: LayoutConfigJson | undefined - filter: FilterConfigJson - }[] - >, - layout?: LayoutConfigJson | undefined - ): void { - if (layer.filter === undefined || layer.filter === null) { - return - } - if (layer.filter["sameAs"] !== undefined) { - return - } - for (const filter of <(string | FilterConfigJson)[]>layer.filter) { - if (typeof filter === "string") { - continue - } - - if (filter["#"]?.indexOf("ignore-possible-duplicate") >= 0) { - continue - } - - for (const option of filter.options) { - if (option.osmTags === undefined) { - continue - } - const key = JSON.stringify(option.osmTags) - if (!perOsmTag.has(key)) { - perOsmTag.set(key, []) - } - perOsmTag.get(key).push({ - layer, - filter, - layout, - }) - } - } - } - convert( json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] }, context: string @@ -991,4 +951,51 @@ export class DetectDuplicateFilters extends DesugaringStep<{ information, } } + + /** + * Add all filter options into 'perOsmTag' + */ + private addLayerFilters( + layer: LayerConfigJson, + perOsmTag: Map< + string, + { + layer: LayerConfigJson + layout: LayoutConfigJson | undefined + filter: FilterConfigJson + }[] + >, + layout?: LayoutConfigJson | undefined + ): void { + if (layer.filter === undefined || layer.filter === null) { + return + } + if (layer.filter["sameAs"] !== undefined) { + return + } + for (const filter of <(string | FilterConfigJson)[]>layer.filter) { + if (typeof filter === "string") { + continue + } + + if (filter["#"]?.indexOf("ignore-possible-duplicate") >= 0) { + continue + } + + for (const option of filter.options) { + if (option.osmTags === undefined) { + continue + } + const key = JSON.stringify(option.osmTags) + if (!perOsmTag.has(key)) { + perOsmTag.set(key, []) + } + perOsmTag.get(key).push({ + layer, + filter, + layout, + }) + } + } + } } diff --git a/Models/ThemeConfig/LayoutConfig.ts b/Models/ThemeConfig/LayoutConfig.ts index 8fe75183e..b6fb91ef2 100644 --- a/Models/ThemeConfig/LayoutConfig.ts +++ b/Models/ThemeConfig/LayoutConfig.ts @@ -82,10 +82,12 @@ export default class LayoutConfig { this.credits = json.credits this.language = json.mustHaveLanguage ?? Object.keys(json.title) this.usedImages = Array.from( - new ExtractImages(official, undefined).convertStrict( - json, - "while extracting the images of " + json.id + " " + context ?? "" - ) + new ExtractImages(official, undefined) + .convertStrict( + json, + "while extracting the images of " + json.id + " " + context ?? "" + ) + .map((i) => i.path) ).sort() { if (typeof json.title === "string") { diff --git a/Models/ThemeConfig/PointRenderingConfig.ts b/Models/ThemeConfig/PointRenderingConfig.ts index f70a656d5..8c3712f1f 100644 --- a/Models/ThemeConfig/PointRenderingConfig.ts +++ b/Models/ThemeConfig/PointRenderingConfig.ts @@ -1,7 +1,6 @@ import PointRenderingConfigJson from "./Json/PointRenderingConfigJson" import TagRenderingConfig from "./TagRenderingConfig" import { TagsFilter } from "../../Logic/Tags/TagsFilter" -import SharedTagRenderings from "../../Customizations/SharedTagRenderings" import { TagUtils } from "../../Logic/Tags/TagUtils" import { Utils } from "../../Utils" import Svg from "../../Svg" @@ -72,18 +71,9 @@ export default class PointRenderingConfig extends WithContextLoader { } this.cssClasses = this.tr("cssClasses", undefined) this.iconBadges = (json.iconBadges ?? []).map((overlay, i) => { - let tr: TagRenderingConfig - if ( - typeof overlay.then === "string" && - SharedTagRenderings.SharedIcons.get(overlay.then) !== undefined - ) { - tr = SharedTagRenderings.SharedIcons.get(overlay.then) - } else { - tr = new TagRenderingConfig(overlay.then, `iconBadges.${i}`) - } return { if: TagUtils.Tag(overlay.if), - then: tr, + then: new TagRenderingConfig(overlay.then, `iconBadges.${i}`), } }) diff --git a/package.json b/package.json index ffca88a41..872c5866d 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "generate:service-worker": "tsc service-worker.ts && git_hash=$(git rev-parse HEAD) && sed -i'.bkp' \"s/GITHUB-COMMIT/$git_hash/\" service-worker.js && rm service-worker.js.bkp", "optimize-images": "cd assets/generated/ && find -name '*.png' -exec optipng '{}' \\; && echo 'PNGs are optimized'", "generate:stats": "vite-node scripts/GenerateSeries.ts", - "reset:layeroverview": "echo {\\\"layers\\\":[], \\\"themes\\\":[]} > ./assets/generated/known_layers_and_themes.json && echo {\\\"layers\\\": []} > ./assets/generated/known_layers.json && rm -f ./assets/generated/layers/*.json && rm -f ./assets/generated/themes/*.json && npm run generate:layeroverview && vite-node scripts/generateLayerOverview.ts --force", + "reset:layeroverview": "echo {\\\"layers\\\":[], \\\"themes\\\":[]} > ./assets/generated/known_layers_and_themes.json && echo {\\\"layers\\\": []} > ./assets/generated/known_layers.json && rm -f ./assets/generated/layers/*.json && rm -f ./assets/generated/themes/*.json && npm run generate:layeroverview && vite-node scripts/generateLayerOverview.ts -- --force", "generate": "mkdir -p ./assets/generated; npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:translations; npm run reset:layeroverview; npm run generate:service-worker", "generate:charging-stations": "cd ./assets/layers/charging_station && vite-node csvToJson.ts && cd -", "prepare-deploy": "npm run generate:service-worker && ./scripts/build.sh", diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index 0f9d50c66..89fa025d7 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -15,7 +15,6 @@ import { import { Translation } from "../UI/i18n/Translation" import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson" import questions from "../assets/tagRenderings/questions.json" -import icons from "../assets/tagRenderings/icons.json" import PointRenderingConfigJson from "../Models/ThemeConfig/Json/PointRenderingConfigJson" import { PrepareLayer } from "../Models/ThemeConfig/Conversion/PrepareLayer" import { PrepareTheme } from "../Models/ThemeConfig/Conversion/PrepareTheme" @@ -167,21 +166,6 @@ class LayerOverviewUtils { ) dict.set(key, config) } - for (const key in icons) { - if (key === "id") { - continue - } - if (typeof icons[key] !== "object") { - continue - } - icons[key].id = key - const config = icons[key] - validator.convertStrict( - config, - "generate-layer-overview:tagRenderings/icons.json:" + key - ) - dict.set(key, config) - } dict.forEach((value, key) => { if (key === "id") { @@ -251,7 +235,7 @@ class LayerOverviewUtils { const sharedLayers = this.buildLayerIndex(doesImageExist, forceReload) const recompiledThemes: string[] = [] const sharedThemes = this.buildThemeIndex( - doesImageExist, + licensePaths, sharedLayers, recompiledThemes, forceReload @@ -381,7 +365,7 @@ class LayerOverviewUtils { } private buildThemeIndex( - doesImageExist: DoesImageExist, + licensePaths: Set, sharedLayers: Map, recompiledThemes: string[], forceReload: boolean @@ -396,9 +380,26 @@ class LayerOverviewUtils { const convertState: DesugaringContext = { sharedLayers, - tagRenderings: this.getSharedTagRenderings(doesImageExist), + tagRenderings: this.getSharedTagRenderings( + new DoesImageExist(licensePaths, existsSync) + ), publicLayers, } + const knownTagRenderings = new Set() + convertState.tagRenderings.forEach((_, key) => knownTagRenderings.add(key)) + sharedLayers.forEach((layer) => { + for (const tagRendering of layer.tagRenderings ?? []) { + if (tagRendering["id"]) { + knownTagRenderings.add(layer.id + "." + tagRendering["id"]) + } + if (tagRendering["labels"]) { + for (const label of tagRendering["labels"]) { + knownTagRenderings.add(layer.id + "." + label) + } + } + } + }) + const skippedThemes: string[] = [] for (const themeInfo of themeFiles) { const themePath = themeInfo.path @@ -433,10 +434,10 @@ class LayerOverviewUtils { themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath) new ValidateThemeAndLayers( - doesImageExist, + new DoesImageExist(licensePaths, existsSync, knownTagRenderings), themePath, true, - convertState.tagRenderings + knownTagRenderings ).convertStrict(themeFile, themePath) if (themeFile.icon.endsWith(".svg")) { diff --git a/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts b/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts index 8dbc989a1..1fffb01a0 100644 --- a/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts +++ b/test/Models/ThemeConfig/Conversion/PrepareTheme.spec.ts @@ -143,7 +143,7 @@ describe("PrepareTheme", () => { describe("ExtractImages", () => { it("should find all images in a themefile", () => { const images = new Set( - new ExtractImages(true, new Map()).convertStrict(cyclofix, "test") + new ExtractImages(true, new Set()).convertStrict(cyclofix, "test") ) const expectedValues = [ "./assets/layers/bike_repair_station/repair_station.svg",