Chore: housekeeping, linting

This commit is contained in:
Pieter Vander Vennet 2025-06-04 00:21:28 +02:00
parent f942529755
commit 30d00eb06d
74 changed files with 998 additions and 623 deletions

View file

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

View file

@ -2,7 +2,10 @@ import { DesugaringStep } from "./Conversion"
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
@ -10,7 +13,7 @@ export default class AddPrefixToTagRenderingConfig extends DesugaringStep<Questi
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, ...)",
"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, ...)"
)
this._prefix = prefix
}

View file

@ -52,7 +52,14 @@ export abstract class Conversion<TIn, TOut> {
throw new Error(
[
"Detected one or more errors, stopping now:",
context.getAll("error").map((e) => `${e.context.path.join(".")} (in operation: ${e.context.operation.join(".")}): ${e.message}`)
context
.getAll("error")
.map(
(e) =>
`${e.context.path.join(
"."
)} (in operation: ${e.context.operation.join(".")}): ${e.message}`
),
].join("\n\t")
)
}
@ -107,7 +114,10 @@ export class Bypass<T> extends DesugaringStep<T> {
private readonly _step: DesugaringStep<T>
constructor(applyIf: (t: T) => boolean, step: DesugaringStep<T>) {
super("Bypass(" + step.name + ")", "Applies the step on the object, if the object satisfies the predicate")
super(
"Bypass(" + step.name + ")",
"Applies the step on the object, if the object satisfies the predicate"
)
this._applyIf = applyIf
this._step = step
}
@ -161,10 +171,7 @@ export class On<P, T> extends DesugaringStep<T> {
private readonly step: (t: T) => Conversion<P, P>
constructor(key: string, step: Conversion<P, P> | ((t: T) => Conversion<P, P>)) {
super(
`On(${key}, ${step.name})`,
"Applies " + step.name + " onto property `" + key + "`",
)
super(`On(${key}, ${step.name})`, "Applies " + step.name + " onto property `" + key + "`")
if (typeof step === "function") {
this.step = step
} else {
@ -264,7 +271,7 @@ export class Fuse<T> extends DesugaringStep<T> {
"Fuse",
(doc ?? "") +
"This fused pipeline of the following steps: " +
steps.map((s) => s.name).join(", "),
steps.map((s) => s.name).join(", ")
)
this.steps = Utils.NoNull(steps)
}

View file

@ -11,7 +11,7 @@ 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",
"Checks that 'then'clauses in mappings don't have images, but use 'icon' instead"
)
this._doesImageExist = doesImageExist
}

View file

@ -19,7 +19,7 @@ export class PruneFilters extends DesugaringStep<LayerConfigJson> {
constructor() {
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"
)
}
@ -117,7 +117,7 @@ export class ExpandFilter extends DesugaringStep<LayerConfigJson> {
[
"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(" "),
].join(" ")
)
this._state = state
}

View file

@ -39,7 +39,11 @@ export class ExpandTagRendering extends Conversion<
addToContext?: false | boolean
}
) {
super("ExpandTagRendering", "Converts a tagRenderingSpec into the full tagRendering, e.g. by substituting the tagRendering by the shared-question and reusing the builtins", [])
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

@ -232,12 +232,14 @@ export class ExtractImages extends Conversion<
// Split "circle:white;./assets/layers/.../something.svg" into ["circle", "./assets/layers/.../something.svg"]
const allPaths = Utils.NoNull(
Utils.NoEmpty(foundImage.path?.split(";")?.map((part) => {
if (part.startsWith("http")) {
return part
}
return part.split(":")[0]
}))
Utils.NoEmpty(
foundImage.path?.split(";")?.map((part) => {
if (part.startsWith("http")) {
return part
}
return part.split(":")[0]
})
)
)
for (const path of allPaths) {
cleanedImages.push({ path, context: foundImage.context })

View file

@ -12,7 +12,7 @@ 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",
"Updates various attributes from the old data format to the new to provide backwards compatibility with the formats"
)
}

View file

@ -1,7 +1,10 @@
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"

View file

@ -1,6 +1,18 @@
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"
@ -25,7 +37,7 @@ 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"',
'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"'
)
}
@ -96,7 +108,7 @@ 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",
"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"
)
}
@ -158,10 +170,7 @@ 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",
)
super("AddQuestionBox", "Adds a 'questions'-object if no question element is added yet")
}
/**
@ -373,7 +382,7 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
constructor() {
super(
"RewriteSpecial",
"Converts a 'special' translation into a regular translation which uses parameters",
"Converts a 'special' translation into a regular translation which uses parameters"
)
}
@ -748,10 +757,7 @@ class PreparePointRendering extends Fuse<PointRenderingConfigJson> {
class SetFullNodeDatabase extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"SetFullNodeDatabase",
"sets the fullNodeDatabase-bit if needed",
)
super("SetFullNodeDatabase", "sets the fullNodeDatabase-bit if needed")
}
convert(json: LayerConfigJson, context: ConversionContext): LayerConfigJson {
@ -776,10 +782,7 @@ class ExpandMarkerRenderings extends DesugaringStep<IconConfigJson> {
private readonly _state: DesugaringContext
constructor(state: DesugaringContext, layer: LayerConfigJson) {
super(
"ExpandMarkerRenderings",
"Expands tagRenderings in the icons, if needed",
)
super("ExpandMarkerRenderings", "Expands tagRenderings in the icons, if needed")
this._layer = layer
this._state = state
}
@ -811,7 +814,7 @@ class AddFavouriteBadges extends DesugaringStep<LayerConfigJson> {
constructor() {
super(
"AddFavouriteBadges",
"Adds the favourite heart to the title and the rendering badges",
"Adds the favourite heart to the title and the rendering badges"
)
}
@ -835,7 +838,7 @@ export class AddRatingBadge extends DesugaringStep<LayerConfigJson> {
constructor() {
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"
)
}
@ -870,7 +873,7 @@ 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",
"The auto-icon creates a (non-clickable) title icon based on a tagRendering which has icons"
)
}
@ -946,34 +949,35 @@ 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")
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 qtr = <QuestionableTagRenderingConfigJson>tr
const unitConfig = qtr?.freeform?.unit
if (!unitConfig) {
continue
}
json.units.push({
[qtr.freeform.key]: unitConfig
[qtr.freeform.key]: unitConfig,
})
// Note: we do not delete the config - this way, if the tagRendering is imported in another layer, the unit comes along
}
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",
"If no source is given, automatically derives the osmTags by 'or'-ing all the preset tags"
)
}

View file

@ -1,4 +1,14 @@
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"
@ -15,7 +25,11 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
private readonly _state: DesugaringContext
constructor(state: DesugaringContext) {
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'", [])
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
}
@ -170,7 +184,7 @@ export class AddDefaultLayers extends DesugaringStep<ThemeConfigJson> {
constructor(state: DesugaringContext) {
super(
"AddDefaultLayers",
"Adds the default layers, namely: " + Constants.added_by_default.join(", "),
"Adds the default layers, namely: " + Constants.added_by_default.join(", ")
)
this._state = state
}
@ -211,7 +225,7 @@ 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",
"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"
)
}
@ -229,7 +243,7 @@ class ApplyOverrideAll extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"ApplyOverrideAll",
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards",
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards"
)
}
@ -280,7 +294,7 @@ 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)`,
`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)`
)
this._state = state
}
@ -462,7 +476,7 @@ 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",
"Generates a warning if a theme uses an inline layer; we recommend splitting of all layers in separate files"
)
}

View file

@ -64,8 +64,9 @@ export class ValidateTheme extends DesugaringStep<ThemeConfigJson> {
if (this._isBuiltin && this._extractImages !== undefined) {
// Check images: are they local, are the licenses there, is the theme icon square, ...
const images = this._extractImages.convert(json, context.inOperation("ValidateTheme"))
const remoteImages = images.filter((img) => img.path.indexOf("http") == 0)
.filter(img => !img.path.startsWith(Constants.nsiLogosEndpoint))
const remoteImages = images
.filter((img) => img.path.indexOf("http") == 0)
.filter((img) => !img.path.startsWith(Constants.nsiLogosEndpoint))
for (const remoteImage of remoteImages) {
context.err(
"Found a remote image: " +
@ -125,7 +126,10 @@ export class ValidateTheme extends DesugaringStep<ThemeConfigJson> {
}
// Official, public themes must have a full english translation
new ValidateLanguageCompleteness("en").convert(theme, context.inOperation("ValidateLanguageCompleteness"))
new ValidateLanguageCompleteness("en").convert(
theme,
context.inOperation("ValidateLanguageCompleteness")
)
}
} catch (e) {
console.error(e)
@ -133,7 +137,10 @@ export class ValidateTheme extends DesugaringStep<ThemeConfigJson> {
}
if (theme.id !== "personal") {
new DetectDuplicatePresets().convert(theme, context.inOperation("DectectDuplicatePrsets"))
new DetectDuplicatePresets().convert(
theme,
context.inOperation("DectectDuplicatePrsets")
)
}
if (!theme.title) {

View file

@ -29,7 +29,7 @@ export class ValidateLanguageCompleteness extends DesugaringStep<ThemeConfig> {
constructor(...languages: string[]) {
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"
)
this._languages = languages ?? ["en"]
}
@ -132,7 +132,7 @@ class OverrideShadowingCheck extends DesugaringStep<ThemeConfigJson> {
constructor() {
super(
"OverrideShadowingCheck",
"Checks that an 'overrideAll' does not override a single override",
"Checks that an 'overrideAll' does not override a single override"
)
}
@ -267,7 +267,7 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
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",
"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"
)
}
@ -311,7 +311,7 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
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",
"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"
)
}
@ -407,7 +407,7 @@ 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",
"Checks that, if the tagrendering has a condition, that a mapping is not contradictory to it, i.e. that there are no dead mappings"
)
this._forceError = forceError
}
@ -598,7 +598,7 @@ export class ValidatePossibleLinks extends DesugaringStep<string | Record<string
constructor() {
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"
)
}
@ -657,10 +657,7 @@ export class CheckTranslation extends DesugaringStep<Translatable> {
private readonly _allowUndefined: boolean
constructor(allowUndefined: boolean = false) {
super(
"CheckTranslation",
"Checks that a translation is valid and internally consistent",
)
super("CheckTranslation", "Checks that a translation is valid and internally consistent")
this._allowUndefined = allowUndefined
}
@ -1037,7 +1034,7 @@ export class DetectDuplicatePresets extends DesugaringStep<ThemeConfig> {
constructor() {
super(
"DetectDuplicatePresets",
"Detects mappings which have identical (english) names or identical mappings.",
"Detects mappings which have identical (english) names or identical mappings."
)
}
@ -1101,7 +1098,10 @@ export class ValidateThemeEnsemble extends Conversion<
>
> {
constructor() {
super("ValidateThemeEnsemble", "Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes")
super(
"ValidateThemeEnsemble",
"Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes"
)
}
convert(

View file

@ -312,14 +312,14 @@ export interface QuestionableTagRenderingConfigJson extends TagRenderingConfigJs
canonical?: string
inverted?: boolean
},
}
/**
* question: In what range should the value be?
* For example, a door width under 65cm is suspicious, under 40cm it is a mistake.
*/
range?: {
min?: number,
warnBelow?: number,
min?: number
warnBelow?: number
warnAbove?: number
max?: number
}

View file

@ -85,8 +85,7 @@ export default interface UnitConfigJson {
* When a default input method should be used, this can be specified by setting the canonical denomination here, e.g.
* `defaultInput: "cm"`. This must be a denomination which appears in the applicableUnits
*/
defaultInput?: string,
defaultInput?: string
}
export interface DenominationConfigJson {

View file

@ -5,7 +5,10 @@ import { TagUtils } from "../../Logic/Tags/TagUtils"
import { And } from "../../Logic/Tags/And"
import { Utils } from "../../Utils"
import { Tag } from "../../Logic/Tags/Tag"
import { MappingConfigJson, QuestionableTagRenderingConfigJson } from "./Json/QuestionableTagRenderingConfigJson"
import {
MappingConfigJson,
QuestionableTagRenderingConfigJson,
} from "./Json/QuestionableTagRenderingConfigJson"
import Validators, { ValidatorType } from "../../UI/InputElement/Validators"
import { TagRenderingConfigJson } from "./Json/TagRenderingConfigJson"
import { RegexTag } from "../../Logic/Tags/RegexTag"
@ -40,9 +43,9 @@ export interface Mapping {
}
export interface ValueRange {
min?: number,
max?: number,
warnBelow?: number,
min?: number
max?: number
warnBelow?: number
warnAbove?: number
}
/***
@ -238,7 +241,7 @@ export default class TagRenderingConfig {
default: json.freeform.default,
postfixDistinguished: json.freeform.postfixDistinguished?.trim(),
args: json.freeform.helperArgs,
range: json.freeform.range
range: json.freeform.range,
}
if (json.freeform["extraTags"] !== undefined) {
throw `Freeform.extraTags is defined. This should probably be 'freeform.addExtraTag' (at ${context})`
@ -804,11 +807,20 @@ export default class TagRenderingConfig {
if (validator && freeformValue) {
// We try to reformat; but a unit might annoy us here
if (unit) {
const [valueNoUnit, denom] = unit.findDenomination(freeformValue, () => currentProperties["_country"])
const formatted = validator.reformat(valueNoUnit, () => currentProperties["_country"])
const [valueNoUnit, denom] = unit.findDenomination(
freeformValue,
() => currentProperties["_country"]
)
const formatted = validator.reformat(
valueNoUnit,
() => currentProperties["_country"]
)
freeformValue = formatted + denom.canonical
} else {
freeformValue = validator.reformat(freeformValue, () => currentProperties["_country"])
freeformValue = validator.reformat(
freeformValue,
() => currentProperties["_country"]
)
}
}
if (freeformValue === "") {
@ -940,7 +952,9 @@ export default class TagRenderingConfig {
freeform += "\n\nThe allowed input is of type " + (this.freeform.type ?? "string")
if (this.freeform.range) {
const r = this.freeform.range
freeform += ` and is in range ${r.min ?? "-infinty"} until ${r.max ?? "infinity"} (both inclusive).`
freeform += ` and is in range ${r.min ?? "-infinty"} until ${
r.max ?? "infinity"
} (both inclusive).`
if (r.warnAbove && r.warnBelow) {
freeform += ` A warning will appear if the value is outside of ${r.warnBelow} and ${r.warnAbove}.`
} else if (r.warnBelow) {