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

View file

@ -9,16 +9,12 @@ import {
DoesImageExist,
PrevalidateTheme,
ValidateLayer,
ValidateThemeEnsemble,
ValidateThemeEnsemble
} from "../src/Models/ThemeConfig/Conversion/Validation"
import { Translation } from "../src/UI/i18n/Translation"
import { PrepareLayer } from "../src/Models/ThemeConfig/Conversion/PrepareLayer"
import { PrepareTheme } from "../src/Models/ThemeConfig/Conversion/PrepareTheme"
import {
Conversion,
DesugaringContext,
DesugaringStep,
} from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Conversion, DesugaringContext, DesugaringStep } from "../src/Models/ThemeConfig/Conversion/Conversion"
import { Utils } from "../src/Utils"
import Script from "./Script"
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 { ExtractImages } from "../src/Models/ThemeConfig/Conversion/FixImages"
import { TagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/TagRenderingConfigJson"
import {
LayerConfigDependencyGraph,
LevelInfo,
} from "../src/Models/ThemeConfig/LayerConfigDependencyGraph"
import { 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.
// 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
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._doesImageExist = doesImageExist
}
@ -158,7 +151,7 @@ class LayerBuilder extends Conversion<object, Map<string, LayerConfigJson>> {
states: Map<string, "clean" | "dirty" | "changed">,
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._dependencies = dependencies
this._states = states

View file

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

View file

@ -1,21 +1,16 @@
import { DesugaringStep } from "./Conversion"
import { ConversionContext } from "./ConversionContext"
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
import { Translatable } from "../Json/Translatable"
import { TagConfigJson } from "../Json/TagConfigJson"
import {
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "../Json/QuestionableTagRenderingConfigJson"
import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
export default class AddPrefixToTagRenderingConfig extends DesugaringStep<QuestionableTagRenderingConfigJson> {
private readonly _prefix: string
constructor(prefix: string) {
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, ...)",
["*"],
"AddPrefixToTagRenderingConfig"
)
this._prefix = prefix
}
@ -106,8 +101,7 @@ export default class AddPrefixToTagRenderingConfig extends DesugaringStep<Questi
}
public convert(
json: Readonly<QuestionableTagRenderingConfigJson>,
context: ConversionContext
json: Readonly<QuestionableTagRenderingConfigJson>
): QuestionableTagRenderingConfigJson {
let freeform = json.freeform
if (freeform) {

View file

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

View file

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

View file

@ -18,9 +18,8 @@ import { Translation } from "../../../UI/i18n/Translation"
export class PruneFilters extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"PruneFilters",
"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) {
super(
"ExpandFilter",
[
"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",
].join(" "),
["filter"],
"ExpandFilter"
)
this._state = state
}

View file

@ -6,7 +6,7 @@ import { Utils } from "../../../Utils"
export class ExpandRewrite<T> extends Conversion<T | RewritableConfigJson<T>, T[]> {
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
}
) {
super(
"Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question and reusing the builtins",
[],
"ExpandTagRendering"
)
super("ExpandTagRendering", "Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question and reusing the builtins", [])
this._state = state
this._self = self
this._options = options

View file

@ -28,7 +28,7 @@ export class ExtractImages extends Conversion<
private _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._sharedTagRenderings = sharedTagRenderings
}

View file

@ -11,9 +11,8 @@ export class UpdateLegacyLayer extends DesugaringStep<
> {
constructor() {
super(
"UpdateLegacyLayer",
"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> {
constructor() {
super("Small fixes in the theme config", ["roamingRenderings"], "UpdateLegacyTheme")
super("UpdateLegacyTheme", "Small fixes in the theme config")
}
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {

View file

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

View file

@ -1,18 +1,6 @@
import {
Concat,
DesugaringContext,
DesugaringStep,
Each,
FirstOf,
Fuse,
On,
SetDefault,
} from "./Conversion"
import { Concat, DesugaringContext, DesugaringStep, Each, FirstOf, Fuse, On, SetDefault } from "./Conversion"
import { LayerConfigJson } from "../Json/LayerConfigJson"
import {
MinimalTagRenderingConfigJson,
TagRenderingConfigJson,
} from "../Json/TagRenderingConfigJson"
import { MinimalTagRenderingConfigJson, TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import { Utils } from "../../../Utils"
import RewritableConfigJson from "../Json/RewritableConfigJson"
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
@ -36,9 +24,8 @@ import { ExpandTagRendering } from "./ExpandTagRendering"
class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> {
constructor() {
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"',
["filter"],
"AddFiltersFromTagRenderings"
)
}
@ -108,9 +95,8 @@ class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> {
class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
constructor() {
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",
["freeform.inline"],
"DetectInline"
)
}
@ -173,9 +159,8 @@ class DetectInline extends DesugaringStep<QuestionableTagRenderingConfigJson> {
export class AddQuestionBox extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"AddQuestionBox",
"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) {
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"
"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"
)
this._desugaring = desugaring
this.builtinQuestions = Array.from(this._desugaring.tagRenderings?.values() ?? [])
@ -388,9 +372,8 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
constructor() {
super(
"RewriteSpecial",
"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
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)
}
@ -766,9 +749,8 @@ class PreparePointRendering extends Fuse<PointRenderingConfigJson> {
class SetFullNodeDatabase extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"SetFullNodeDatabase",
"sets the fullNodeDatabase-bit if needed",
["fullNodeDatabase"],
"SetFullNodeDatabase"
)
}
@ -795,9 +777,8 @@ class ExpandMarkerRenderings extends DesugaringStep<IconConfigJson> {
constructor(state: DesugaringContext, layer: LayerConfigJson) {
super(
"ExpandMarkerRenderings",
"Expands tagRenderings in the icons, if needed",
["icon", "color"],
"ExpandMarkerRenderings"
)
this._layer = layer
this._state = state
@ -829,9 +810,8 @@ class ExpandMarkerRenderings extends DesugaringStep<IconConfigJson> {
class AddFavouriteBadges extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"AddFavouriteBadges",
"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> {
constructor() {
super(
"AddRatingBadge",
"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> {
constructor() {
super(
"AutoTitleIcon",
"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> {
constructor() {
super(
"DeriveSource",
"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 {
Concat,
Conversion,
DesugaringContext,
DesugaringStep,
Each,
Fuse,
On,
Pass,
SetDefault,
} from "./Conversion"
import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
import { ThemeConfigJson } from "../Json/ThemeConfigJson"
import { PrepareLayer, RewriteSpecial } from "./PrepareLayer"
import { LayerConfigJson } from "../Json/LayerConfigJson"
@ -25,11 +15,7 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
private readonly _state: DesugaringContext
constructor(state: DesugaringContext) {
super(
"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"
)
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'", [])
this._state = state
}
@ -183,9 +169,8 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
constructor(state: DesugaringContext) {
super(
"AddDefaultLayers",
"Adds the default layers, namely: " + Constants.added_by_default.join(", "),
["layers"],
"AddDefaultLayers"
)
this._state = state
}
@ -225,9 +210,8 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
class AddContextToTranslationsInLayout extends DesugaringStep<ThemeConfigJson> {
constructor() {
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",
["_context"],
"AddContextToTranlationsInLayout"
)
}
@ -244,9 +228,8 @@ class AddContextToTranslationsInLayout extends DesugaringStep<ThemeConfigJson> {
class ApplyOverrideAll extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"ApplyOverrideAll",
"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) {
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)`,
["layers"],
"AddDependencyLayersToTheme"
)
this._state = state
}
@ -456,7 +438,7 @@ class PreparePersonalTheme extends DesugaringStep<ThemeConfigJson> {
private readonly _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
}
@ -479,9 +461,8 @@ class PreparePersonalTheme extends DesugaringStep<ThemeConfigJson> {
class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"WarnForUnsubstitutedLayersInTheme",
"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
constructor(state: DesugaringContext) {
super("Various validation steps when everything is done", [], "PostvalidateTheme")
super("PostvalidateTheme", "Various validation steps when everything is done")
this._state = state
}

View file

@ -27,7 +27,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
doesImageExist: DoesImageExist,
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._isBuiltin = isBuiltin
this._doesImageExist = doesImageExist
@ -57,6 +57,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
}
} else {
if (json.source === "special" || json.source === "special:library") {
// pass
} else if (json.source && json.source["osmTags"] === undefined) {
context
.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 (!json.description) {
context.enter("description").err("A description is required")
@ -358,7 +354,7 @@ export class PrevalidateLayer extends DesugaringStep<LayerConfigJson> {
if (pointRendering.marker === undefined) {
continue
}
for (const icon of pointRendering?.marker) {
for (const icon of pointRendering?.marker ?? []) {
const indexM = pointRendering?.marker.indexOf(icon)
if (!icon.icon) {
continue

View file

@ -24,7 +24,7 @@ export class ValidateTheme extends DesugaringStep<ThemeConfigJson> {
isBuiltin: boolean,
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._path = path
this._isBuiltin = isBuiltin

View file

@ -28,9 +28,8 @@ export class ValidateLanguageCompleteness extends DesugaringStep<ThemeConfig> {
constructor(...languages: string[]) {
super(
"ValidateLanguageCompleteness",
"Checks that the given object is fully translated in the specified languages",
[],
"ValidateLanguageCompleteness"
)
this._languages = languages ?? ["en"]
}
@ -74,7 +73,7 @@ export class DoesImageExist extends DesugaringStep<string> {
checkExistsSync: (path: string) => boolean = undefined,
ignore?: Set<string>
) {
super("Checks if an image exists", [], "DoesImageExist")
super("DoesImageExist", "Checks if an image exists")
this._ignore = ignore
this._knownImagePaths = knownImagePaths
this.doesPathExist = checkExistsSync
@ -129,9 +128,8 @@ export class DoesImageExist extends DesugaringStep<string> {
class OverrideShadowingCheck extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"OverrideShadowingCheck",
"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> {
constructor() {
super("Miscelleanous checks on the theme", [], "MiscThemesChecks")
super("Miscelleanous checks on the theme", "MiscThemesChecks")
}
convert(json: ThemeConfigJson, context: ConversionContext): ThemeConfigJson {
@ -265,9 +263,8 @@ export class PrevalidateTheme extends Fuse<ThemeConfigJson> {
export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingConfigJson> {
constructor() {
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",
[],
"DetectConflictingAddExtraTags"
)
}
@ -310,9 +307,8 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTagRenderingConfigJson> {
constructor() {
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",
[],
"DetectNonErasedKeysInMappings"
)
}
@ -407,9 +403,8 @@ export class DetectMappingsShadowedByCondition extends DesugaringStep<TagRenderi
constructor(forceError: boolean = false) {
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",
[],
"DetectMappingsShadowedByCondition"
)
this._forceError = forceError
}
@ -471,7 +466,7 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
private readonly _calculatedTagNames: string[]
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)
}
@ -599,9 +594,8 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
export class ValidatePossibleLinks extends DesugaringStep<string | Record<string, string>> {
constructor() {
super(
"ValidatePossibleLinks",
"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) {
super(
"CheckTranslation",
"Checks that a translation is valid and internally consistent",
["*"],
"CheckTranslation"
)
this._allowUndefined = allowUndefined
}
@ -712,7 +705,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
studioValidations: boolean = false,
skipDefaultLayers: boolean = false
) {
super("Thin wrapper around 'ValidateLayer", [], "ValidateLayerConfig")
super("ValidateLayerConfig", "Thin wrapper around 'ValidateLayer")
this.validator = new ValidateLayer(
path,
isBuiltin,
@ -734,7 +727,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJson> {
constructor() {
super("Various checks for pointRenderings", [], "ValidatePOintRendering")
super("ValidatePointRendering", "Various checks for pointRenderings")
}
convert(json: PointRenderingConfigJson, context: ConversionContext): PointRenderingConfigJson {
@ -777,7 +770,7 @@ export class ValidateLayer extends Conversion<
studioValidations: 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(
path,
isBuiltin,
@ -819,7 +812,7 @@ export class ValidateLayer extends Conversion<
}
for (let i = 0; i < (layerConfig.calculatedTags ?? []).length; i++) {
const [_, code, __] = layerConfig.calculatedTags[i]
const code = layerConfig.calculatedTags[i][1]
try {
new Function("feat", "return " + code + ";")
} catch (e) {
@ -894,7 +887,7 @@ export class ValidateLayer extends Conversion<
export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
constructor() {
super("Detect common errors in the filters", [], "ValidateFilter")
super("ValidateFilter", "Detect common errors in the filters")
}
convert(filter: FilterConfigJson, context: ConversionContext): FilterConfigJson {
@ -931,9 +924,8 @@ export class DetectDuplicateFilters extends DesugaringStep<{
}> {
constructor() {
super(
"Tries to detect layers where a shared filter can be used (or where similar filters occur)",
[],
"DetectDuplicateFilters"
"DetectDuplicateFilters",
"Tries to detect layers where a shared filter can be used (or where similar filters occur)"
)
}
@ -1041,9 +1033,8 @@ export class DetectDuplicateFilters extends DesugaringStep<{
export class DetectDuplicatePresets extends DesugaringStep<ThemeConfig> {
constructor() {
super(
"DetectDuplicatePresets",
"Detects mappings which have identical (english) names or identical mappings.",
["presets"],
"DetectDuplicatePresets"
)
}
@ -1107,11 +1098,7 @@ export class ValidateThemeEnsemble extends Conversion<
>
> {
constructor() {
super(
"Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes",
[],
"ValidateThemeEnsemble"
)
super("ValidateThemeEnsemble", "Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes")
}
convert(

View file

@ -556,7 +556,7 @@ export interface LayerConfigJson {
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`)
*

View file

@ -290,6 +290,29 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
* group: hidden
*/
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 { Store, UIEventSource } from "../../Logic/UIEventSource"
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
import {
Conversion,
ConversionMessage,
DesugaringContext,
Pipe,
} from "../../Models/ThemeConfig/Conversion/Conversion"
import { Conversion, ConversionMessage, DesugaringContext, Pipe } from "../../Models/ThemeConfig/Conversion/Conversion"
import { PrepareLayer } from "../../Models/ThemeConfig/Conversion/PrepareLayer"
import { PrevalidateTheme, ValidateLayer } from "../../Models/ThemeConfig/Conversion/Validation"
import { AllSharedLayers } from "../../Customizations/AllSharedLayers"
@ -281,11 +276,7 @@ class ContextRewritingStep<T> extends Conversion<LayerConfigJson, T> {
step: Conversion<LayerConfigJson, T>,
getTagRenderings: (t: T) => TagRenderingConfigJson[]
) {
super(
"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"
)
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", [])
this._state = state
this._step = step
this._getTagRenderings = getTagRenderings