Refactoring: change order of parameters and remove parameter for Conversion.ts

This commit is contained in:
Pieter Vander Vennet 2025-05-16 15:48:55 +02:00
parent f9ba3126a4
commit a0b7a32223
20 changed files with 147 additions and 213 deletions

View file

@ -5,32 +5,26 @@ import { QuestionableTagRenderingConfigJson } from "../src/Models/ThemeConfig/Js
import * as fakedom from "fake-dom" import * as fakedom from "fake-dom"
import Script from "./Script" import Script from "./Script"
import { FixedUiElement } from "../src/UI/Base/FixedUiElement" import { FixedUiElement } from "../src/UI/Base/FixedUiElement"
import { ConversionContext } from "../src/Models/ThemeConfig/Conversion/ConversionContext"
class ExtractQuestionHint extends DesugaringStep<QuestionableTagRenderingConfigJson> { class ExtractQuestionHint extends DesugaringStep<QuestionableTagRenderingConfigJson> {
constructor() { constructor() {
super( super(
"ExtractQuestionHint",
"Tries to extract a 'questionHint' from the question", "Tries to extract a 'questionHint' from the question",
["question", "questionhint"],
"ExtractQuestionHint"
) )
} }
convert( convert(
json: QuestionableTagRenderingConfigJson, json: QuestionableTagRenderingConfigJson
context: string ): QuestionableTagRenderingConfigJson {
): {
result: QuestionableTagRenderingConfigJson
errors?: string[]
warnings?: string[]
information?: string[]
} {
json = { ...json } json = { ...json }
if (json.question === undefined || json.questionHint !== undefined) { if (json.question === undefined || json.questionHint !== undefined) {
return { result: json } return json
} }
if (typeof json.question === "string") { if (typeof json.question === "string") {
return { result: json } return json
} }
const hint: Record<string, string> = {} const hint: Record<string, string> = {}
@ -64,12 +58,11 @@ class ExtractQuestionHint extends DesugaringStep<QuestionableTagRenderingConfigJ
console.log("Inspecting ", json.question) console.log("Inspecting ", json.question)
return { result: json } return json
} }
} }
class FixQuestionHint extends Script { class FixQuestionHint extends Script {
private fs: any
constructor() { constructor() {
super("Extracts a 'questionHint' from a question for a given 'layer.json' or 'theme.json'") super("Extracts a 'questionHint' from a question for a given 'layer.json' or 'theme.json'")
if (fakedom === undefined) { if (fakedom === undefined) {
@ -89,7 +82,9 @@ class FixQuestionHint extends Script {
} }
contents[key] = convertor.convertStrict( contents[key] = convertor.convertStrict(
tr, tr,
"While automatically extracting questiondHints of " + filepath ConversionContext.construct([],
["While automatically extracting questiondHints of " + filepath]
)
) )
} }
fs.writeFileSync(filepath, JSON.stringify(contents, null, " "), { encoding: "utf-8" }) fs.writeFileSync(filepath, JSON.stringify(contents, null, " "), { encoding: "utf-8" })
@ -105,7 +100,9 @@ class FixQuestionHint extends Script {
} }
layer.tagRenderings[i] = convertor.convertStrict( layer.tagRenderings[i] = convertor.convertStrict(
<QuestionableTagRenderingConfigJson>tagRendering, <QuestionableTagRenderingConfigJson>tagRendering,
ConversionContext.construct([], [
"While automatically extracting questionHints of " + filepath "While automatically extracting questionHints of " + filepath
])
) )
} }
} }

View file

@ -9,16 +9,12 @@ import {
DoesImageExist, DoesImageExist,
PrevalidateTheme, PrevalidateTheme,
ValidateLayer, ValidateLayer,
ValidateThemeEnsemble, ValidateThemeEnsemble
} from "../src/Models/ThemeConfig/Conversion/Validation" } from "../src/Models/ThemeConfig/Conversion/Validation"
import { Translation } from "../src/UI/i18n/Translation" import { Translation } from "../src/UI/i18n/Translation"
import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer" import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer"
import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme" import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme"
import { import { Conversion, DesugaringContext, DesugaringStep } from "../src/Models/ThemeConfig/Conversion/Conversion"
Conversion,
DesugaringContext,
DesugaringStep,
} from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Utils } from "../src/Utils" import { Utils } from "../src/Utils"
import Script from "./Script" import Script from "./Script"
import { AllSharedLayers } from "../src/Customizations/AllSharedLayers" import { AllSharedLayers } from "../src/Customizations/AllSharedLayers"
@ -35,10 +31,7 @@ import { Translatable } from "../src/Models/ThemeConfig/Json/Translatable"
import { ValidateThemeAndLayers } from "../src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers" import { ValidateThemeAndLayers } from "../src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers"
import { ExtractImages } from "../src/Models/ThemeConfig/Conversion/FixImages" import { ExtractImages } from "../src/Models/ThemeConfig/Conversion/FixImages"
import { TagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/TagRenderingConfigJson" import { TagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/TagRenderingConfigJson"
import { import { LayerConfigDependencyGraph, LevelInfo } from "../src/Models/ThemeConfig/LayerConfigDependencyGraph"
LayerConfigDependencyGraph,
LevelInfo,
} from "../src/Models/ThemeConfig/LayerConfigDependencyGraph"
// This scripts scans 'src/assets/layers/*.json' for layer definition files and 'src/assets/themes/*.json' for theme definition files. // This scripts scans 'src/assets/layers/*.json' for layer definition files and 'src/assets/themes/*.json' for theme definition files.
// It spits out an overview of those to be used to load them // It spits out an overview of those to be used to load them
@ -54,7 +47,7 @@ class ParseLayer extends Conversion<
private readonly _doesImageExist: DoesImageExist private readonly _doesImageExist: DoesImageExist
constructor(prepareLayer: PrepareLayer, doesImageExist: DoesImageExist) { constructor(prepareLayer: PrepareLayer, doesImageExist: DoesImageExist) {
super("Parsed a layer from file, validates it", [], "ParseLayer") super("ParseLayer", "Parsed a layer from file, validates it", [])
this._prepareLayer = prepareLayer this._prepareLayer = prepareLayer
this._doesImageExist = doesImageExist this._doesImageExist = doesImageExist
} }
@ -158,7 +151,7 @@ class LayerBuilder extends Conversion<object, Map<string, LayerConfigJson>> {
states: Map<string, "clean" | "dirty" | "changed">, states: Map<string, "clean" | "dirty" | "changed">,
sharedTagRenderings: QuestionableTagRenderingConfigJson[] sharedTagRenderings: QuestionableTagRenderingConfigJson[]
) { ) {
super("Builds all the layers, writes them to file", [], "LayerBuilder") super("LayerBuilder", "Builds all the layers, writes them to file", [])
this._levels = levels this._levels = levels
this._dependencies = dependencies this._dependencies = dependencies
this._states = states this._states = states

View file

@ -8,9 +8,8 @@ export class AddContextToTranslations<T> extends DesugaringStep<T> {
constructor(prefix = "") { constructor(prefix = "") {
super( super(
"AddContextToTranslation",
"Adds a '_context' to every object that is probably a translation", "Adds a '_context' to every object that is probably a translation",
["_context"],
"AddContextToTranslation"
) )
this._prefix = prefix this._prefix = prefix
} }

View file

@ -1,21 +1,16 @@
import { DesugaringStep } from "./Conversion" import { DesugaringStep } from "./Conversion"
import { ConversionContext } from "./ConversionContext"
import SpecialVisualizations from "../../../UI/SpecialVisualizations" import SpecialVisualizations from "../../../UI/SpecialVisualizations"
import { Translatable } from "../Json/Translatable" import { Translatable } from "../Json/Translatable"
import { TagConfigJson } from "../Json/TagConfigJson" import { TagConfigJson } from "../Json/TagConfigJson"
import { import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "../Json/QuestionableTagRenderingConfigJson"
export default class AddPrefixToTagRenderingConfig extends DesugaringStep<QuestionableTagRenderingConfigJson> { export default class AddPrefixToTagRenderingConfig extends DesugaringStep<QuestionableTagRenderingConfigJson> {
private readonly _prefix: string private readonly _prefix: string
constructor(prefix: string) { constructor(prefix: string) {
super( super(
"AddPrefixToTagRenderingConfig",
"Adds `prefix` to _all_ keys. Used to add information about a subamenity withing a bigger amenity (e.g. toilets in a restaurant, a sauna in a water park, ...)", "Adds `prefix` to _all_ keys. Used to add information about a subamenity withing a bigger amenity (e.g. toilets in a restaurant, a sauna in a water park, ...)",
["*"],
"AddPrefixToTagRenderingConfig"
) )
this._prefix = prefix this._prefix = prefix
} }
@ -106,8 +101,7 @@ export default class AddPrefixToTagRenderingConfig extends DesugaringStep<Questi
} }
public convert( public convert(
json: Readonly<QuestionableTagRenderingConfigJson>, json: Readonly<QuestionableTagRenderingConfigJson>
context: ConversionContext
): QuestionableTagRenderingConfigJson { ): QuestionableTagRenderingConfigJson {
let freeform = json.freeform let freeform = json.freeform
if (freeform) { if (freeform) {

View file

@ -22,13 +22,11 @@ export interface ConversionMessage {
} }
export abstract class Conversion<TIn, TOut> { export abstract class Conversion<TIn, TOut> {
public readonly modifiedAttributes: string[]
public readonly name: string public readonly name: string
protected readonly doc: string protected readonly doc: string
constructor(doc: string, modifiedAttributes: string[] = [], name: string) { constructor(name: string, doc: string) {
this.modifiedAttributes = modifiedAttributes this.doc = doc
this.doc = doc + "\n\nModified attributes are\n" + modifiedAttributes.join(", ")
this.name = name this.name = name
} }
@ -76,7 +74,7 @@ export class Pipe<TIn, TInter, TOut> extends Conversion<TIn, TOut> {
private readonly _failfast: boolean private readonly _failfast: boolean
constructor(step0: Conversion<TIn, TInter>, step1: Conversion<TInter, TOut>, failfast = false) { constructor(step0: Conversion<TIn, TInter>, step1: Conversion<TInter, TOut>, failfast = false) {
super("Merges two steps with different types", [], `Pipe(${step0.name}, ${step1.name})`) super(`Pipe(${step0.name}, ${step1.name})`, "Merges two steps with different types")
this._step0 = step0 this._step0 = step0
this._step1 = step1 this._step1 = step1
this._failfast = failfast this._failfast = failfast
@ -95,11 +93,11 @@ export class Pure<TIn, TOut> extends Conversion<TIn, TOut> {
private readonly _f: (t: TIn) => TOut private readonly _f: (t: TIn) => TOut
constructor(f: (t: TIn) => TOut) { constructor(f: (t: TIn) => TOut) {
super("Wrapper around a pure function", [], "Pure") super("Pure", "Wrapper around a pure function")
this._f = f this._f = f
} }
convert(json: TIn, context: ConversionContext): TOut { convert(json: TIn): TOut {
return this._f(json) return this._f(json)
} }
} }
@ -109,7 +107,7 @@ export class Bypass<T> extends DesugaringStep<T> {
private readonly _step: DesugaringStep<T> private readonly _step: DesugaringStep<T>
constructor(applyIf: (t: T) => boolean, step: DesugaringStep<T>) { constructor(applyIf: (t: T) => boolean, step: DesugaringStep<T>) {
super("Applies the step on the object, if the object satisfies the predicate", [], "Bypass") super("Bypass", "Applies the step on the object, if the object satisfies the predicate")
this._applyIf = applyIf this._applyIf = applyIf
this._step = step this._step = step
} }
@ -127,11 +125,7 @@ export class Each<X, Y> extends Conversion<X[], Y[]> {
private readonly _msg: string private readonly _msg: string
constructor(step: Conversion<X, Y>, options?: { msg?: string }) { constructor(step: Conversion<X, Y>, options?: { msg?: string }) {
super( super("OnEach(" + step.name + ")", "Applies the given step on every element of the list")
"Applies the given step on every element of the list",
[],
"OnEach(" + step.name + ")"
)
this._step = step this._step = step
this._msg = options?.msg this._msg = options?.msg
} }
@ -168,14 +162,13 @@ export class On<P, T> extends DesugaringStep<T> {
constructor(key: string, step: Conversion<P, P> | ((t: T) => Conversion<P, P>)) { constructor(key: string, step: Conversion<P, P> | ((t: T) => Conversion<P, P>)) {
super( super(
`On(${key}, ${step.name})`,
"Applies " + step.name + " onto property `" + key + "`", "Applies " + step.name + " onto property `" + key + "`",
[key],
`On(${key}, ${step.name})`
) )
if (typeof step === "function") { if (typeof step === "function") {
this.step = step this.step = step
} else { } else {
this.step = (_) => step this.step = () => step
} }
this.key = key this.key = key
} }
@ -196,10 +189,10 @@ export class On<P, T> extends DesugaringStep<T> {
export class Pass<T> extends Conversion<T, T> { export class Pass<T> extends Conversion<T, T> {
constructor(message?: string) { constructor(message?: string) {
super(message ?? "Does nothing, often to swap out steps in testing", [], "Pass") super("Pass", message ?? "Does nothing, often to swap out steps in testing")
} }
convert(json: T, _: ConversionContext): T { convert(json: T): T {
return json return json
} }
} }
@ -208,11 +201,7 @@ export class Concat<X, T> extends Conversion<X[], T[]> {
private readonly _step: Conversion<X, T[]> private readonly _step: Conversion<X, T[]>
constructor(step: Conversion<X, T[]>) { constructor(step: Conversion<X, T[]>) {
super( super("Concat(" + step.name + ")", "Executes the given step, flattens the resulting list")
"Executes the given step, flattens the resulting list",
[],
"Concat(" + step.name + ")"
)
this._step = step this._step = step
} }
@ -230,11 +219,7 @@ export class FirstOf<T, X> extends Conversion<T, X> {
private readonly _conversion: Conversion<T, X[]> private readonly _conversion: Conversion<T, X[]>
constructor(conversion: Conversion<T, X[]>) { constructor(conversion: Conversion<T, X[]>) {
super( super("FirstOf(" + conversion.name + ")", "Picks the first result of the conversion step")
"Picks the first result of the conversion step",
[],
"FirstOf(" + conversion.name + ")"
)
this._conversion = conversion this._conversion = conversion
} }
@ -252,7 +237,7 @@ export class Cached<TIn, TOut> extends Conversion<TIn, TOut> {
private readonly key: string private readonly key: string
constructor(step: Conversion<TIn, TOut>) { constructor(step: Conversion<TIn, TOut>) {
super("Secretly caches the output for the given input", [], "cached") super("cached", "Secretly caches the output for the given input")
this._step = step this._step = step
this.key = "__super_secret_caching_key_" + step.name this.key = "__super_secret_caching_key_" + step.name
} }
@ -276,11 +261,10 @@ export class Fuse<T> extends DesugaringStep<T> {
constructor(doc: string, ...steps: DesugaringStep<T>[]) { constructor(doc: string, ...steps: DesugaringStep<T>[]) {
super( super(
"Fuse",
(doc ?? "") + (doc ?? "") +
"This fused pipeline of the following steps: " + "This fused pipeline of the following steps: " +
steps.map((s) => s.name).join(", "), steps.map((s) => s.name).join(", "),
Utils.Dedup([].concat(...steps.map((step) => step.modifiedAttributes))),
"Fuse"
) )
this.steps = Utils.NoNull(steps) this.steps = Utils.NoNull(steps)
} }
@ -318,19 +302,19 @@ export class Fuse<T> extends DesugaringStep<T> {
} }
} }
export class SetDefault<T> extends DesugaringStep<T> { export class SetDefault<X, T extends object> extends DesugaringStep<T> {
private readonly value: any private readonly value: X
private readonly key: string private readonly key: string
private readonly _overrideEmptyString: boolean private readonly _overrideEmptyString: boolean
constructor(key: string, value: any, overrideEmptyString = false) { constructor(key: string, value: X, overrideEmptyString = false) {
super("Sets " + key + " to a default value if undefined", [], "SetDefault of " + key) super("SetDefault of " + key, "Sets " + key + " to a default value if undefined")
this.key = key this.key = key
this.value = value this.value = value
this._overrideEmptyString = overrideEmptyString this._overrideEmptyString = overrideEmptyString
} }
convert(json: T, _: ConversionContext): T { convert(json: T): T {
if (json === undefined) { if (json === undefined) {
return undefined return undefined
} }

View file

@ -10,9 +10,8 @@ export class DetectMappingsWithImages extends DesugaringStep<TagRenderingConfigJ
constructor(doesImageExist: DoesImageExist) { constructor(doesImageExist: DoesImageExist) {
super( super(
"DetectMappingsWithImages",
"Checks that 'then'clauses in mappings don't have images, but use 'icon' instead", "Checks that 'then'clauses in mappings don't have images, but use 'icon' instead",
[],
"DetectMappingsWithImages"
) )
this._doesImageExist = doesImageExist this._doesImageExist = doesImageExist
} }

View file

@ -18,9 +18,8 @@ import { Translation } from "../../../UI/i18n/Translation"
export class PruneFilters extends DesugaringStep<LayerConfigJson> { export class PruneFilters extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"PruneFilters",
"Removes all filters which are impossible, e.g. because they conflict with the base tags", "Removes all filters which are impossible, e.g. because they conflict with the base tags",
["filter"],
"PruneFilters"
) )
} }
@ -114,12 +113,11 @@ export class ExpandFilter extends DesugaringStep<LayerConfigJson> {
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super( super(
"ExpandFilter",
[ [
"Expands filters: replaces a shorthand by the value found in 'filters.json'.", "Expands filters: replaces a shorthand by the value found in 'filters.json'.",
"If the string is formatted 'layername.filtername, it will be looked up into that layer instead. Note that pruning should still be done", "If the string is formatted 'layername.filtername, it will be looked up into that layer instead. Note that pruning should still be done",
].join(" "), ].join(" "),
["filter"],
"ExpandFilter"
) )
this._state = state this._state = state
} }

View file

@ -6,7 +6,7 @@ import { Utils } from "../../../Utils"
export class ExpandRewrite<T> extends Conversion<T | RewritableConfigJson<T>, T[]> { export class ExpandRewrite<T> extends Conversion<T | RewritableConfigJson<T>, T[]> {
constructor() { constructor() {
super("Applies a rewrite", [], "ExpandRewrite") super("ExpandRewrite", "Applies a rewrite", [])
} }
/** /**

View file

@ -39,11 +39,7 @@ export class ExpandTagRendering extends Conversion<
addToContext?: false | boolean addToContext?: false | boolean
} }
) { ) {
super( super("ExpandTagRendering", "Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question and reusing the builtins", [])
"Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question and reusing the builtins",
[],
"ExpandTagRendering"
)
this._state = state this._state = state
this._self = self this._self = self
this._options = options this._options = options

View file

@ -28,7 +28,7 @@ export class ExtractImages extends Conversion<
private _sharedTagRenderings: Set<string> private _sharedTagRenderings: Set<string>
constructor(isOfficial: boolean, sharedTagRenderings: Set<string>) { constructor(isOfficial: boolean, sharedTagRenderings: Set<string>) {
super("Extract all images from a layoutConfig using the meta paths.", [], "ExctractImages") super("ExctractImages", "Extract all images from a layoutConfig using the meta paths.", [])
this._isOfficial = isOfficial this._isOfficial = isOfficial
this._sharedTagRenderings = sharedTagRenderings this._sharedTagRenderings = sharedTagRenderings
} }

View file

@ -11,9 +11,8 @@ export class UpdateLegacyLayer extends DesugaringStep<
> { > {
constructor() { constructor() {
super( super(
"UpdateLegacyLayer",
"Updates various attributes from the old data format to the new to provide backwards compatibility with the formats", "Updates various attributes from the old data format to the new to provide backwards compatibility with the formats",
["overpassTags", "source.osmtags", "tagRenderings[*].id", "mapRendering"],
"UpdateLegacyLayer"
) )
} }
@ -259,7 +258,7 @@ export class UpdateLegacyLayer extends DesugaringStep<
class UpdateLegacyTheme extends DesugaringStep<ThemeConfigJson> { class UpdateLegacyTheme extends DesugaringStep<ThemeConfigJson> {
constructor() { constructor() {
super("Small fixes in the theme config", ["roamingRenderings"], "UpdateLegacyTheme") super("UpdateLegacyTheme", "Small fixes in the theme config")
} }
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {

View file

@ -1,10 +1,7 @@
import { DesugaringStep } from "./Conversion" import { DesugaringStep } from "./Conversion"
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson" import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import { LayerConfigJson } from "../Json/LayerConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson"
import { import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "../Json/QuestionableTagRenderingConfigJson"
import { ConversionContext } from "./ConversionContext" import { ConversionContext } from "./ConversionContext"
import { Translation } from "../../../UI/i18n/Translation" import { Translation } from "../../../UI/i18n/Translation"
import Validators from "../../../UI/InputElement/Validators" import Validators from "../../../UI/InputElement/Validators"
@ -14,7 +11,7 @@ export class MiscTagRenderingChecks extends DesugaringStep<TagRenderingConfigJso
private readonly _layerConfig: LayerConfigJson private readonly _layerConfig: LayerConfigJson
constructor(layerConfig?: LayerConfigJson) { constructor(layerConfig?: LayerConfigJson) {
super("Miscellaneous checks on the tagrendering", ["special"], "MiscTagRenderingChecks") super("MiscTagRenderingChecks", "Miscellaneous checks on the tagrendering")
this._layerConfig = layerConfig this._layerConfig = layerConfig
} }

View file

@ -1,18 +1,6 @@
import { import { Concat, DesugaringContext, DesugaringStep, Each, FirstOf, Fuse, On, SetDefault } from "./Conversion"
Concat,
DesugaringContext,
DesugaringStep,
Each,
FirstOf,
Fuse,
On,
SetDefault,
} from "./Conversion"
import { LayerConfigJson } from "../Json/LayerConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson"
import { import { MinimalTagRenderingConfigJson, TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
MinimalTagRenderingConfigJson,
TagRenderingConfigJson,
} from "../Json/TagRenderingConfigJson"
import { Utils } from "../../../Utils" import { Utils } from "../../../Utils"
import RewritableConfigJson from "../Json/RewritableConfigJson" import RewritableConfigJson from "../Json/RewritableConfigJson"
import SpecialVisualizations from "../../../UI/SpecialVisualizations" import SpecialVisualizations from "../../../UI/SpecialVisualizations"
@ -36,9 +24,8 @@ import { ExpandTagRendering } from "./ExpandTagRendering"
class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> { class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"AddFiltersFromTagRenderings",
'Inspects all the tagRenderings. If some tagRenderings have the `filter` attribute set, introduce those filters. This step might introduce shorthand filter names, thus \'ExpandFilter\' should be run afterwards. Can be disabled with "#filter":"no-auto"', 'Inspects all the tagRenderings. If some tagRenderings have the `filter` attribute set, introduce those filters. This step might introduce shorthand filter names, thus \'ExpandFilter\' should be run afterwards. Can be disabled with "#filter":"no-auto"',
["filter"],
"AddFiltersFromTagRenderings"
) )
} }
@ -108,9 +95,8 @@ class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> {
class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> { class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
constructor() { constructor() {
super( super(
"DetectInline",
"If no 'inline' is set on the freeform key, it will be automatically added. If no special renderings are used, it'll be set to true", "If no 'inline' is set on the freeform key, it will be automatically added. If no special renderings are used, it'll be set to true",
["freeform.inline"],
"DetectInline"
) )
} }
@ -173,9 +159,8 @@ class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
export class AddQuestionBox extends DesugaringStep<LayerConfigJson> { export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"AddQuestionBox",
"Adds a 'questions'-object if no question element is added yet", "Adds a 'questions'-object if no question element is added yet",
["tagRenderings"],
"AddQuestionBox"
) )
} }
@ -284,9 +269,8 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
constructor(desugaring: DesugaringContext) { constructor(desugaring: DesugaringContext) {
super( super(
"Add some editing elements, such as the delete button or the move button if they are configured. These used to be handled by the feature info box, but this has been replaced by special visualisation elements", "AddEditingElements",
[], "Add some editing elements, such as the delete button or the move button if they are configured. These used to be handled by the feature info box, but this has been replaced by special visualisation elements"
"AddEditingElements"
) )
this._desugaring = desugaring this._desugaring = desugaring
this.builtinQuestions = Array.from(this._desugaring.tagRenderings?.values() ?? []) this.builtinQuestions = Array.from(this._desugaring.tagRenderings?.values() ?? [])
@ -388,9 +372,8 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> { export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
constructor() { constructor() {
super( super(
"RewriteSpecial",
"Converts a 'special' translation into a regular translation which uses parameters", "Converts a 'special' translation into a regular translation which uses parameters",
["special"],
"RewriteSpecial"
) )
} }
@ -664,7 +647,7 @@ class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson> {
private _expand: ExpandTagRendering private _expand: ExpandTagRendering
constructor(state: DesugaringContext, layer: LayerConfigJson) { constructor(state: DesugaringContext, layer: LayerConfigJson) {
super("Expands shorthand properties on iconBadges", ["iconBadges"], "ExpandIconBadges") super("ExpandIconBadges", "Expands shorthand properties on iconBadges")
this._expand = new ExpandTagRendering(state, layer) this._expand = new ExpandTagRendering(state, layer)
} }
@ -766,9 +749,8 @@ class PreparePointRendering extends Fuse<PointRenderingConfigJson> {
class SetFullNodeDatabase extends DesugaringStep<LayerConfigJson> { class SetFullNodeDatabase extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"SetFullNodeDatabase",
"sets the fullNodeDatabase-bit if needed", "sets the fullNodeDatabase-bit if needed",
["fullNodeDatabase"],
"SetFullNodeDatabase"
) )
} }
@ -795,9 +777,8 @@ class ExpandMarkerRenderings extends DesugaringStep<IconConfigJson> {
constructor(state: DesugaringContext, layer: LayerConfigJson) { constructor(state: DesugaringContext, layer: LayerConfigJson) {
super( super(
"ExpandMarkerRenderings",
"Expands tagRenderings in the icons, if needed", "Expands tagRenderings in the icons, if needed",
["icon", "color"],
"ExpandMarkerRenderings"
) )
this._layer = layer this._layer = layer
this._state = state this._state = state
@ -829,9 +810,8 @@ class ExpandMarkerRenderings extends DesugaringStep<IconConfigJson> {
class AddFavouriteBadges extends DesugaringStep<LayerConfigJson> { class AddFavouriteBadges extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"AddFavouriteBadges",
"Adds the favourite heart to the title and the rendering badges", "Adds the favourite heart to the title and the rendering badges",
[],
"AddFavouriteBadges"
) )
} }
@ -854,9 +834,8 @@ class AddFavouriteBadges extends DesugaringStep<LayerConfigJson> {
export class AddRatingBadge extends DesugaringStep<LayerConfigJson> { export class AddRatingBadge extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"AddRatingBadge",
"Adds the 'rating'-element if a reviews-element is used in the tagRenderings", "Adds the 'rating'-element if a reviews-element is used in the tagRenderings",
["titleIcons"],
"AddRatingBadge"
) )
} }
@ -890,9 +869,8 @@ export class AddRatingBadge extends DesugaringStep<LayerConfigJson> {
export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> { export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"AutoTitleIcon",
"The auto-icon creates a (non-clickable) title icon based on a tagRendering which has icons", "The auto-icon creates a (non-clickable) title icon based on a tagRendering which has icons",
["titleIcons"],
"AutoTitleIcon"
) )
} }
@ -967,12 +945,34 @@ export class AutoTitleIcon extends DesugaringStep<LayerConfigJson> {
} }
} }
class MoveUnitConfigs extends DesugaringStep<LayerConfigJson> {
constructor() {
super("MoveUnitConfigs", "Looks into all the tagRenderings for a 'unitConfig', moves them to the layer level")
}
convert(json: LayerConfigJson, context: ConversionContext): LayerConfigJson {
json = { ...json, units: [...(json.units ?? [])] }
for (const tr of json.tagRenderings ?? []) {
const qtr = (<QuestionableTagRenderingConfigJson>tr)
const unitConfig = qtr?.freeform?.unit
if (!unitConfig) {
continue
}
json.units.push({
[qtr.freeform.key]: unitConfig
})
}
return json
}
}
class DeriveSource extends DesugaringStep<LayerConfigJson> { class DeriveSource extends DesugaringStep<LayerConfigJson> {
constructor() { constructor() {
super( super(
"DeriveSource",
"If no source is given, automatically derives the osmTags by 'or'-ing all the preset tags", "If no source is given, automatically derives the osmTags by 'or'-ing all the preset tags",
["source"],
"DeriveSource"
) )
} }

View file

@ -1,14 +1,4 @@
import { import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
Concat,
Conversion,
DesugaringContext,
DesugaringStep,
Each,
Fuse,
On,
Pass,
SetDefault,
} from "./Conversion"
import { ThemeConfigJson } from "../Json/ThemeConfigJson" import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { PrepareLayer, RewriteSpecial } from "./PrepareLayer" import { PrepareLayer, RewriteSpecial } from "./PrepareLayer"
import { LayerConfigJson } from "../Json/LayerConfigJson" import { LayerConfigJson } from "../Json/LayerConfigJson"
@ -25,11 +15,7 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
private readonly _state: DesugaringContext private readonly _state: DesugaringContext
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super( super("SubstituteLayer", "Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form. Note that 'tagRenderings+' will be inserted before 'leftover-questions'", [])
"Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form. Note that 'tagRenderings+' will be inserted before 'leftover-questions'",
[],
"SubstituteLayer"
)
this._state = state this._state = state
} }
@ -183,9 +169,8 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super( super(
"AddDefaultLayers",
"Adds the default layers, namely: " + Constants.added_by_default.join(", "), "Adds the default layers, namely: " + Constants.added_by_default.join(", "),
["layers"],
"AddDefaultLayers"
) )
this._state = state this._state = state
} }
@ -225,9 +210,8 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
class AddContextToTranslationsInLayout extends DesugaringStep<ThemeConfigJson> { class AddContextToTranslationsInLayout extends DesugaringStep<ThemeConfigJson> {
constructor() { constructor() {
super( super(
"AddContextToTranlationsInLayout",
"Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too", "Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too",
["_context"],
"AddContextToTranlationsInLayout"
) )
} }
@ -244,9 +228,8 @@ class AddContextToTranslationsInLayout extends DesugaringStep<ThemeConfigJson> {
class ApplyOverrideAll extends DesugaringStep<ThemeConfigJson> { class ApplyOverrideAll extends DesugaringStep<ThemeConfigJson> {
constructor() { constructor() {
super( super(
"ApplyOverrideAll",
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards", "Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards",
["overrideAll", "layers"],
"ApplyOverrideAll"
) )
} }
@ -296,9 +279,8 @@ class AddDependencyLayersToTheme extends DesugaringStep<ThemeConfigJson> {
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super( super(
"AddDependencyLayersToTheme",
`If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)`, `If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)`,
["layers"],
"AddDependencyLayersToTheme"
) )
this._state = state this._state = state
} }
@ -456,7 +438,7 @@ class PreparePersonalTheme extends DesugaringStep<ThemeConfigJson> {
private readonly _state: DesugaringContext private readonly _state: DesugaringContext
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super("Adds every public layer to the personal theme", ["layers"], "PreparePersonalTheme") super("PreparePersonalTheme", "Adds every public layer to the personal theme")
this._state = state this._state = state
} }
@ -479,9 +461,8 @@ class PreparePersonalTheme extends DesugaringStep<ThemeConfigJson> {
class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<ThemeConfigJson> { class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<ThemeConfigJson> {
constructor() { constructor() {
super( super(
"WarnForUnsubstitutedLayersInTheme",
"Generates a warning if a theme uses an inline layer; we recommend splitting of all layers in separate files", "Generates a warning if a theme uses an inline layer; we recommend splitting of all layers in separate files",
["layers"],
"WarnForUnsubstitutedLayersInTheme"
) )
} }
@ -531,7 +512,7 @@ class PostvalidateTheme extends DesugaringStep<ThemeConfigJson> {
private readonly _state: DesugaringContext private readonly _state: DesugaringContext
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super("Various validation steps when everything is done", [], "PostvalidateTheme") super("PostvalidateTheme", "Various validation steps when everything is done")
this._state = state this._state = state
} }

View file

@ -27,7 +27,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
doesImageExist: DoesImageExist, doesImageExist: DoesImageExist,
studioValidations: boolean studioValidations: boolean
) { ) {
super("Runs various checks against common mistakes for a layer", [], "PrevalidateLayer") super("PrevalidateLayer", "Runs various checks against common mistakes for a layer")
this._path = path this._path = path
this._isBuiltin = isBuiltin this._isBuiltin = isBuiltin
this._doesImageExist = doesImageExist this._doesImageExist = doesImageExist
@ -57,6 +57,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
} }
} else { } else {
if (json.source === "special" || json.source === "special:library") { if (json.source === "special" || json.source === "special:library") {
// pass
} else if (json.source && json.source["osmTags"] === undefined) { } else if (json.source && json.source["osmTags"] === undefined) {
context context
.enters("source", "osmTags") .enters("source", "osmTags")
@ -232,11 +233,6 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
} }
} }
try {
} catch (e) {
context.err("Could not validate layer due to: " + e + e.stack)
}
if (this._studioValidations) { if (this._studioValidations) {
if (!json.description) { if (!json.description) {
context.enter("description").err("A description is required") context.enter("description").err("A description is required")
@ -358,7 +354,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
if (pointRendering.marker === undefined) { if (pointRendering.marker === undefined) {
continue continue
} }
for (const icon of pointRendering?.marker) { for (const icon of pointRendering?.marker ?? []) {
const indexM = pointRendering?.marker.indexOf(icon) const indexM = pointRendering?.marker.indexOf(icon)
if (!icon.icon) { if (!icon.icon) {
continue continue

View file

@ -24,7 +24,7 @@ export class ValidateTheme extends DesugaringStep<ThemeConfigJson> {
isBuiltin: boolean, isBuiltin: boolean,
sharedTagRenderings?: Set<string> sharedTagRenderings?: Set<string>
) { ) {
super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme") super("ValidateTheme", "Doesn't change anything, but emits warnings and errors")
this._validateImage = doesImageExist this._validateImage = doesImageExist
this._path = path this._path = path
this._isBuiltin = isBuiltin this._isBuiltin = isBuiltin

View file

@ -28,9 +28,8 @@ export class ValidateLanguageCompleteness extends DesugaringStep<ThemeConfig> {
constructor(...languages: string[]) { constructor(...languages: string[]) {
super( super(
"ValidateLanguageCompleteness",
"Checks that the given object is fully translated in the specified languages", "Checks that the given object is fully translated in the specified languages",
[],
"ValidateLanguageCompleteness"
) )
this._languages = languages ?? ["en"] this._languages = languages ?? ["en"]
} }
@ -74,7 +73,7 @@ export class DoesImageExist extends DesugaringStep<string> {
checkExistsSync: (path: string) => boolean = undefined, checkExistsSync: (path: string) => boolean = undefined,
ignore?: Set<string> ignore?: Set<string>
) { ) {
super("Checks if an image exists", [], "DoesImageExist") super("DoesImageExist", "Checks if an image exists")
this._ignore = ignore this._ignore = ignore
this._knownImagePaths = knownImagePaths this._knownImagePaths = knownImagePaths
this.doesPathExist = checkExistsSync this.doesPathExist = checkExistsSync
@ -129,9 +128,8 @@ export class DoesImageExist extends DesugaringStep<string> {
class OverrideShadowingCheck extends DesugaringStep<ThemeConfigJson> { class OverrideShadowingCheck extends DesugaringStep<ThemeConfigJson> {
constructor() { constructor() {
super( super(
"OverrideShadowingCheck",
"Checks that an 'overrideAll' does not override a single override", "Checks that an 'overrideAll' does not override a single override",
[],
"OverrideShadowingCheck"
) )
} }
@ -170,7 +168,7 @@ class OverrideShadowingCheck extends DesugaringStep<ThemeConfigJson> {
class MiscThemeChecks extends DesugaringStep<ThemeConfigJson> { class MiscThemeChecks extends DesugaringStep<ThemeConfigJson> {
constructor() { constructor() {
super("Miscelleanous checks on the theme", [], "MiscThemesChecks") super("Miscelleanous checks on the theme", "MiscThemesChecks")
} }
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson { convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
@ -265,9 +263,8 @@ export class PrevalidateTheme extends Fuse<ThemeConfigJson> {
export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingConfigJson> { export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingConfigJson> {
constructor() { constructor() {
super( super(
"DetectConflictingAddExtraTags",
"The `if`-part in a mapping might set some keys. Those keys are not allowed to be set in the `addExtraTags`, as this might result in conflicting values", "The `if`-part in a mapping might set some keys. Those keys are not allowed to be set in the `addExtraTags`, as this might result in conflicting values",
[],
"DetectConflictingAddExtraTags"
) )
} }
@ -310,9 +307,8 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTagRenderingConfigJson> { export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTagRenderingConfigJson> {
constructor() { constructor() {
super( super(
"DetectNonErasedKeysInMappings",
"A tagRendering might set a freeform key (e.g. `name` and have an option that _should_ erase this name, e.g. `noname=yes`). Under normal circumstances, every mapping/freeform should affect all touched keys", "A tagRendering might set a freeform key (e.g. `name` and have an option that _should_ erase this name, e.g. `noname=yes`). Under normal circumstances, every mapping/freeform should affect all touched keys",
[],
"DetectNonErasedKeysInMappings"
) )
} }
@ -407,9 +403,8 @@ export class DetectMappingsShadowedByCondition extends DesugaringStep<TagRenderi
constructor(forceError: boolean = false) { constructor(forceError: boolean = false) {
super( super(
"DetectMappingsShadowedByCondition",
"Checks that, if the tagrendering has a condition, that a mapping is not contradictory to it, i.e. that there are no dead mappings", "Checks that, if the tagrendering has a condition, that a mapping is not contradictory to it, i.e. that there are no dead mappings",
[],
"DetectMappingsShadowedByCondition"
) )
this._forceError = forceError this._forceError = forceError
} }
@ -471,7 +466,7 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
private readonly _calculatedTagNames: string[] private readonly _calculatedTagNames: string[]
constructor(layerConfig?: LayerConfigJson) { constructor(layerConfig?: LayerConfigJson) {
super("Checks that the mappings don't shadow each other", [], "DetectShadowedMappings") super("DetectShadowedMappings", "Checks that the mappings don't shadow each other")
this._calculatedTagNames = DetectShadowedMappings.extractCalculatedTagNames(layerConfig) this._calculatedTagNames = DetectShadowedMappings.extractCalculatedTagNames(layerConfig)
} }
@ -599,9 +594,8 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
export class ValidatePossibleLinks extends DesugaringStep<string | Record<string, string>> { export class ValidatePossibleLinks extends DesugaringStep<string | Record<string, string>> {
constructor() { constructor() {
super( super(
"ValidatePossibleLinks",
"Given a possible set of translations, validates that <a href=... target='_blank'> does have `rel='noopener'` set", "Given a possible set of translations, validates that <a href=... target='_blank'> does have `rel='noopener'` set",
[],
"ValidatePossibleLinks"
) )
} }
@ -661,9 +655,8 @@ export class CheckTranslation extends DesugaringStep<Translatable> {
constructor(allowUndefined: boolean = false) { constructor(allowUndefined: boolean = false) {
super( super(
"CheckTranslation",
"Checks that a translation is valid and internally consistent", "Checks that a translation is valid and internally consistent",
["*"],
"CheckTranslation"
) )
this._allowUndefined = allowUndefined this._allowUndefined = allowUndefined
} }
@ -712,7 +705,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
studioValidations: boolean = false, studioValidations: boolean = false,
skipDefaultLayers: boolean = false skipDefaultLayers: boolean = false
) { ) {
super("Thin wrapper around 'ValidateLayer", [], "ValidateLayerConfig") super("ValidateLayerConfig", "Thin wrapper around 'ValidateLayer")
this.validator = new ValidateLayer( this.validator = new ValidateLayer(
path, path,
isBuiltin, isBuiltin,
@ -734,7 +727,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJson> { export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJson> {
constructor() { constructor() {
super("Various checks for pointRenderings", [], "ValidatePOintRendering") super("ValidatePointRendering", "Various checks for pointRenderings")
} }
convert(json: PointRenderingConfigJson, context: ConversionContext): PointRenderingConfigJson { convert(json: PointRenderingConfigJson, context: ConversionContext): PointRenderingConfigJson {
@ -777,7 +770,7 @@ export class ValidateLayer extends Conversion<
studioValidations: boolean = false, studioValidations: boolean = false,
skipDefaultLayers: boolean = false skipDefaultLayers: boolean = false
) { ) {
super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer") super("ValidateLayer", "Doesn't change anything, but emits warnings and errors")
this._prevalidation = new PrevalidateLayer( this._prevalidation = new PrevalidateLayer(
path, path,
isBuiltin, isBuiltin,
@ -819,7 +812,7 @@ export class ValidateLayer extends Conversion<
} }
for (let i = 0; i < (layerConfig.calculatedTags ?? []).length; i++) { for (let i = 0; i < (layerConfig.calculatedTags ?? []).length; i++) {
const [_, code, __] = layerConfig.calculatedTags[i] const code = layerConfig.calculatedTags[i][1]
try { try {
new Function("feat", "return " + code + ";") new Function("feat", "return " + code + ";")
} catch (e) { } catch (e) {
@ -894,7 +887,7 @@ export class ValidateLayer extends Conversion<
export class ValidateFilter extends DesugaringStep<FilterConfigJson> { export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
constructor() { constructor() {
super("Detect common errors in the filters", [], "ValidateFilter") super("ValidateFilter", "Detect common errors in the filters")
} }
convert(filter: FilterConfigJson, context: ConversionContext): FilterConfigJson { convert(filter: FilterConfigJson, context: ConversionContext): FilterConfigJson {
@ -931,9 +924,8 @@ export class DetectDuplicateFilters extends DesugaringStep<{
}> { }> {
constructor() { constructor() {
super( super(
"Tries to detect layers where a shared filter can be used (or where similar filters occur)", "DetectDuplicateFilters",
[], "Tries to detect layers where a shared filter can be used (or where similar filters occur)"
"DetectDuplicateFilters"
) )
} }
@ -1041,9 +1033,8 @@ export class DetectDuplicateFilters extends DesugaringStep<{
export class DetectDuplicatePresets extends DesugaringStep<ThemeConfig> { export class DetectDuplicatePresets extends DesugaringStep<ThemeConfig> {
constructor() { constructor() {
super( super(
"DetectDuplicatePresets",
"Detects mappings which have identical (english) names or identical mappings.", "Detects mappings which have identical (english) names or identical mappings.",
["presets"],
"DetectDuplicatePresets"
) )
} }
@ -1107,11 +1098,7 @@ export class ValidateThemeEnsemble extends Conversion<
> >
> { > {
constructor() { constructor() {
super( super("ValidateThemeEnsemble", "Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes")
"Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes",
[],
"ValidateThemeEnsemble"
)
} }
convert( convert(

View file

@ -556,7 +556,7 @@ export interface LayerConfigJson {
allowSplit?: boolean allowSplit?: boolean
/** /**
* Either a list with [{"key": "unitname", "key2": {"quantity": "unitname", "denominations": ["denom", "denom"]}}] * Either a list of unitConfigs with [{"key": "unitname", "key2": {"quantity": "unitname", "denominations": ["denom", "denom"]}}]
* *
* Use `"inverted": true` if the amount should be _divided_ by the denomination, e.g. for charge over time (`€5/day`) * Use `"inverted": true` if the amount should be _divided_ by the denomination, e.g. for charge over time (`€5/day`)
* *

View file

@ -290,6 +290,29 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
* group: hidden * group: hidden
*/ */
helperArgs?: any helperArgs?: any
/**
* question: what units
*
* group: hidden
*
* Note: this is actually a syntactic sugar and is translated to the unit-syntax on layer level
*/
unit?: {
/**
* What is the quantity? E.g. 'voltage', 'speed', ...
* See [builtin_units.md] for options
*/
quantity: string
/**
* The possible denominations for the quantities. E.g. For 'length', might be 'cm', 'm', 'km', ...
* If none given, will allow all the defaults
*/
denominations: string[]
canonical?: string
inverted?: boolean
}
} }
/** /**

View file

@ -1,12 +1,7 @@
import { ConfigMeta } from "./configMeta" import { ConfigMeta } from "./configMeta"
import { Store, UIEventSource } from "../../Logic/UIEventSource" import { Store, UIEventSource } from "../../Logic/UIEventSource"
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson" import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
import { import { Conversion, ConversionMessage, DesugaringContext, Pipe } from "../../Models/ThemeConfig/Conversion/Conversion"
Conversion,
ConversionMessage,
DesugaringContext,
Pipe,
} from "../../Models/ThemeConfig/Conversion/Conversion"
import { PrepareLayer } from "../../Models/ThemeConfig/Conversion/PrepareLayer" import { PrepareLayer } from "../../Models/ThemeConfig/Conversion/PrepareLayer"
import { PrevalidateTheme, ValidateLayer } from "../../Models/ThemeConfig/Conversion/Validation" import { PrevalidateTheme, ValidateLayer } from "../../Models/ThemeConfig/Conversion/Validation"
import { AllSharedLayers } from "../../Customizations/AllSharedLayers" import { AllSharedLayers } from "../../Customizations/AllSharedLayers"
@ -281,11 +276,7 @@ class ContextRewritingStep<T> extends Conversion<LayerConfigJson, T> {
step: Conversion<LayerConfigJson, T>, step: Conversion<LayerConfigJson, T>,
getTagRenderings: (t: T) => TagRenderingConfigJson[] getTagRenderings: (t: T) => TagRenderingConfigJson[]
) { ) {
super( super("ContextRewritingStep", "When validating a layer, the tagRenderings are first expanded. Some builtin tagRendering-calls (e.g. `contact`) will introduce _multiple_ tagRenderings, causing the count to be off. This class rewrites the error messages to fix this", [])
"When validating a layer, the tagRenderings are first expanded. Some builtin tagRendering-calls (e.g. `contact`) will introduce _multiple_ tagRenderings, causing the count to be off. This class rewrites the error messages to fix this",
[],
"ContextRewritingStep"
)
this._state = state this._state = state
this._step = step this._step = step
this._getTagRenderings = getTagRenderings this._getTagRenderings = getTagRenderings