diff --git a/Models/ThemeConfig/Conversion/Conversion.ts b/Models/ThemeConfig/Conversion/Conversion.ts index 3d9aa1183a..5b6b72c008 100644 --- a/Models/ThemeConfig/Conversion/Conversion.ts +++ b/Models/ThemeConfig/Conversion/Conversion.ts @@ -216,13 +216,18 @@ export class Fuse extends DesugaringStep { const information = [] for (let i = 0; i < this.steps.length; i++) { const step = this.steps[i]; - let r = step.convert(json, "While running step " + step.name + ": " + context) - errors.push(...r.errors ?? []) - warnings.push(...r.warnings ?? []) - information.push(...r.information ?? []) - json = r.result - if (errors.length > 0) { - break; + try{ + let r = step.convert(json, "While running step " + step.name + ": " + context) + errors.push(...r.errors ?? []) + warnings.push(...r.warnings ?? []) + information.push(...r.information ?? []) + json = r.result + if (errors.length > 0) { + break; + } + }catch(e){ + console.error("Step "+step.name+" failed due to "+e); + throw e } } return { diff --git a/Models/ThemeConfig/Conversion/PrepareTheme.ts b/Models/ThemeConfig/Conversion/PrepareTheme.ts index 7c1aa17211..8a9877e108 100644 --- a/Models/ThemeConfig/Conversion/PrepareTheme.ts +++ b/Models/ThemeConfig/Conversion/PrepareTheme.ts @@ -479,6 +479,7 @@ export class PrepareTheme extends Fuse { }) { super( "Fully prepares and expands a theme", + new AddContextToTransltionsInLayout(), new PreparePersonalTheme(state), new WarnForUnsubstitutedLayersInTheme(), diff --git a/Models/ThemeConfig/Conversion/Validation.ts b/Models/ThemeConfig/Conversion/Validation.ts index 912707877c..b0c121953b 100644 --- a/Models/ThemeConfig/Conversion/Validation.ts +++ b/Models/ThemeConfig/Conversion/Validation.ts @@ -217,12 +217,17 @@ class MiscThemeChecks extends DesugaringStep{ convert(json: LayoutConfigJson, context: string): { result: LayoutConfigJson; errors?: string[]; warnings?: string[]; information?: string[] } { const warnings = [] + const errors = [] + if(json.id !== "personal" && (json.layers === undefined || json.layers.length === 0)){ + errors.push("The theme "+json.id+" has no 'layers' defined ("+context+")") + } if(json.socialImage === ""){ warnings.push("Social image for theme "+json.id+" is the emtpy string") } return { result :json, - warnings + warnings, + errors }; } } @@ -231,8 +236,8 @@ export class PrevalidateTheme extends Fuse { constructor() { super("Various consistency checks on the raw JSON", - new OverrideShadowingCheck(), - new MiscThemeChecks() + new MiscThemeChecks(), + new OverrideShadowingCheck() ); } diff --git a/Models/ThemeConfig/Json/UnitConfigJson.ts b/Models/ThemeConfig/Json/UnitConfigJson.ts index 5eba5eaf49..bde2683b23 100644 --- a/Models/ThemeConfig/Json/UnitConfigJson.ts +++ b/Models/ThemeConfig/Json/UnitConfigJson.ts @@ -18,9 +18,12 @@ export default interface UnitConfigJson { export interface ApplicableUnitJson { /** - * The canonical value which will be added to the text. + * The canonical value which will be added to the value in OSM. * e.g. "m" for meters - * If the user inputs '42', the canonical value will be added and it'll become '42m' + * If the user inputs '42', the canonical value will be added and it'll become '42m'. + * + * Important: often, _no_ canonical values are expected, e.g. in the case of 'maxspeed' where 'km/h' is the default. + * In this case, an empty string should be used */ canonicalDenomination: string, /** diff --git a/Models/ThemeConfig/LayerConfig.ts b/Models/ThemeConfig/LayerConfig.ts index b7863b4274..ade6d6b6df 100644 --- a/Models/ThemeConfig/LayerConfig.ts +++ b/Models/ThemeConfig/LayerConfig.ts @@ -134,6 +134,9 @@ export default class LayerConfig extends WithContextLoader { this.allowSplit = json.allowSplit ?? false; this.name = Translations.T(json.name, translationContext + ".name"); + if(json.units!==undefined && !Array.isArray(json.units)){ + throw "At "+context+".units: the 'units'-section should be a list; you probably have an object there" + } this.units = (json.units ?? []).map(((unitJson, i) => Unit.fromJson(unitJson, `${context}.unit[${i}]`))) if (json.description !== undefined) { diff --git a/scripts/generateLayerOverview.ts b/scripts/generateLayerOverview.ts index d9faf2d9ab..02cc138594 100644 --- a/scripts/generateLayerOverview.ts +++ b/scripts/generateLayerOverview.ts @@ -203,16 +203,22 @@ class LayerOverviewUtils { const themePath = themeInfo.path new PrevalidateTheme().convertStrict(themeFile, themePath) - themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath) - - if(knownImagePaths === undefined){ - throw "Could not load known images/licenses" + try{ + + themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath) + + if(knownImagePaths === undefined){ + throw "Could not load known images/licenses" + } + new ValidateThemeAndLayers(knownImagePaths, themePath, true, convertState.tagRenderings) + .convertStrict(themeFile, themePath) + + this.writeTheme(themeFile) + fixed.set(themeFile.id, themeFile) + }catch(e){ + console.error("ERROR: could not prepare theme "+themePath+" due to "+e) + throw e; } - new ValidateThemeAndLayers(knownImagePaths, themePath, true, convertState.tagRenderings) - .convertStrict(themeFile, themePath) - - this.writeTheme(themeFile) - fixed.set(themeFile.id, themeFile) } this.writeSmallOverview(themeFiles.map(tf => {