chore: automated housekeeping...

This commit is contained in:
Pieter Vander Vennet 2024-08-14 13:53:56 +02:00
parent f77570589d
commit 9b8a9337fd
111 changed files with 2911 additions and 1280 deletions

View file

@ -28,7 +28,7 @@ export class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
super(
"Checks that the given object is fully translated in the specified languages",
[],
"ValidateLanguageCompleteness",
"ValidateLanguageCompleteness"
)
this._languages = languages ?? ["en"]
}
@ -42,18 +42,18 @@ export class ValidateLanguageCompleteness extends DesugaringStep<LayoutConfig> {
.filter(
(t) =>
t.tr.translations[neededLanguage] === undefined &&
t.tr.translations["*"] === undefined,
t.tr.translations["*"] === undefined
)
.forEach((missing) => {
context
.enter(missing.context.split("."))
.err(
`The theme ${obj.id} should be translation-complete for ` +
neededLanguage +
", but it lacks a translation for " +
missing.context +
".\n\tThe known translation is " +
missing.tr.textFor("en"),
neededLanguage +
", but it lacks a translation for " +
missing.context +
".\n\tThe known translation is " +
missing.tr.textFor("en")
)
})
}
@ -70,7 +70,7 @@ export class DoesImageExist extends DesugaringStep<string> {
constructor(
knownImagePaths: Set<string>,
checkExistsSync: (path: string) => boolean = undefined,
ignore?: Set<string>,
ignore?: Set<string>
) {
super("Checks if an image exists", [], "DoesImageExist")
this._ignore = ignore
@ -106,15 +106,15 @@ export class DoesImageExist extends DesugaringStep<string> {
if (!this._knownImagePaths.has(image)) {
if (this.doesPathExist === undefined) {
context.err(
`Image with path ${image} not found or not attributed; it is used in ${context}`,
`Image with path ${image} not found or not attributed; it is used in ${context}`
)
} else if (!this.doesPathExist(image)) {
context.err(
`Image with path ${image} does not exist.\n Check for typo's and missing directories in the path.`,
`Image with path ${image} does not exist.\n Check for typo's and missing directories in the path.`
)
} else {
context.err(
`Image with path ${image} is not attributed (but it exists); execute 'npm run query:licenses' to add the license information and/or run 'npm run generate:licenses' to compile all the license info`,
`Image with path ${image} is not attributed (but it exists); execute 'npm run query:licenses' to add the license information and/or run 'npm run generate:licenses' to compile all the license info`
)
}
}
@ -127,7 +127,7 @@ class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
super(
"Checks that an 'overrideAll' does not override a single override",
[],
"OverrideShadowingCheck",
"OverrideShadowingCheck"
)
}
@ -174,7 +174,11 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
context.err("The theme " + json.id + " has no 'layers' defined")
}
if (!Array.isArray(json.layers)) {
context.enter("layers").err("The 'layers'-field should be an array, but it is not. Did you pase a layer identifier and forget to add the '[' and ']'?")
context
.enter("layers")
.err(
"The 'layers'-field should be an array, but it is not. Did you pase a layer identifier and forget to add the '[' and ']'?"
)
}
if (json.socialImage === "") {
context.warn("Social image for theme " + json.id + " is the emtpy string")
@ -183,9 +187,9 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
context.warn("Obsolete field `clustering` is still around")
}
if(json.layers === undefined){
if (json.layers === undefined) {
context.err("This theme has no layers defined")
}else{
} else {
for (let i = 0; i < json.layers.length; i++) {
const l = json.layers[i]
if (l["override"]?.["source"] === undefined) {
@ -207,7 +211,7 @@ class MiscThemeChecks extends DesugaringStep<LayoutConfigJson> {
context
.enter("overideAll")
.err(
"'overrideAll' is spelled with _two_ `r`s. You only wrote a single one of them.",
"'overrideAll' is spelled with _two_ `r`s. You only wrote a single one of them."
)
}
return json
@ -219,7 +223,7 @@ export class PrevalidateTheme extends Fuse<LayoutConfigJson> {
super(
"Various consistency checks on the raw JSON",
new MiscThemeChecks(),
new OverrideShadowingCheck(),
new OverrideShadowingCheck()
)
}
}
@ -229,7 +233,7 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
super(
"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",
"DetectConflictingAddExtraTags"
)
}
@ -256,7 +260,7 @@ export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingCo
.enters("mappings", i)
.err(
"AddExtraTags overrides a key that is set in the `if`-clause of this mapping. Selecting this answer might thus first set one value (needed to match as answer) and then override it with a different value, resulting in an unsaveable question. The offending `addExtraTags` is " +
duplicateKeys.join(", "),
duplicateKeys.join(", ")
)
}
}
@ -274,13 +278,13 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
super(
"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",
"DetectNonErasedKeysInMappings"
)
}
convert(
json: QuestionableTagRenderingConfigJson,
context: ConversionContext,
context: ConversionContext
): QuestionableTagRenderingConfigJson {
if (json.multiAnswer) {
// No need to check this here, this has its own validation
@ -334,8 +338,8 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
.enters("freeform")
.warn(
"The freeform block does not modify the key `" +
neededKey +
"` which is set in a mapping. Use `addExtraTags` to overwrite it",
neededKey +
"` which is set in a mapping. Use `addExtraTags` to overwrite it"
)
}
}
@ -353,8 +357,8 @@ export class DetectNonErasedKeysInMappings extends DesugaringStep<QuestionableTa
.enters("mappings", i)
.warn(
"This mapping does not modify the key `" +
neededKey +
"` which is set in a mapping or by the freeform block. Use `addExtraTags` to overwrite it",
neededKey +
"` which is set in a mapping or by the freeform block. Use `addExtraTags` to overwrite it"
)
}
}
@ -371,7 +375,7 @@ export class DetectMappingsShadowedByCondition extends DesugaringStep<TagRenderi
super(
"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",
"DetectMappingsShadowedByCondition"
)
this._forceError = forceError
}
@ -443,7 +447,7 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
* DetectShadowedMappings.extractCalculatedTagNames({calculatedTags: ["_abc=js()"]}) // => ["_abc"]
*/
private static extractCalculatedTagNames(
layerConfig?: LayerConfigJson | { calculatedTags: string[] },
layerConfig?: LayerConfigJson | { calculatedTags: string[] }
) {
return (
layerConfig?.calculatedTags?.map((ct) => {
@ -529,16 +533,16 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
json.mappings[i]["hideInAnswer"] !== true
) {
context.warn(
`Mapping ${i} is shadowed by mapping ${j}. However, mapping ${j} has 'hideInAnswer' set, which will result in a different rendering in question-mode.`,
`Mapping ${i} is shadowed by mapping ${j}. However, mapping ${j} has 'hideInAnswer' set, which will result in a different rendering in question-mode.`
)
} else if (doesMatch) {
// The current mapping is shadowed!
context.err(`Mapping ${i} is shadowed by mapping ${j} and will thus never be shown:
The mapping ${parsedConditions[i].asHumanString(
false,
false,
{},
)} is fully matched by a previous mapping (namely ${j}), which matches:
false,
false,
{}
)} is fully matched by a previous mapping (namely ${j}), which matches:
${parsedConditions[j].asHumanString(false, false, {})}.
To fix this problem, you can try to:
@ -563,7 +567,7 @@ export class ValidatePossibleLinks extends DesugaringStep<string | Record<string
super(
"Given a possible set of translations, validates that <a href=... target='_blank'> does have `rel='noopener'` set",
[],
"ValidatePossibleLinks",
"ValidatePossibleLinks"
)
}
@ -593,21 +597,21 @@ export class ValidatePossibleLinks extends DesugaringStep<string | Record<string
convert(
json: string | Record<string, string>,
context: ConversionContext,
context: ConversionContext
): string | Record<string, string> {
if (typeof json === "string") {
if (this.isTabnabbingProne(json)) {
context.err(
"The string " +
json +
" has a link targeting `_blank`, but it doesn't have `rel='noopener'` set. This gives rise to reverse tabnapping",
json +
" has a link targeting `_blank`, but it doesn't have `rel='noopener'` set. This gives rise to reverse tabnapping"
)
}
} else {
for (const k in json) {
if (this.isTabnabbingProne(json[k])) {
context.err(
`The translation for ${k} '${json[k]}' has a link targeting \`_blank\`, but it doesn't have \`rel='noopener'\` set. This gives rise to reverse tabnapping`,
`The translation for ${k} '${json[k]}' has a link targeting \`_blank\`, but it doesn't have \`rel='noopener'\` set. This gives rise to reverse tabnapping`
)
}
}
@ -625,7 +629,7 @@ export class CheckTranslation extends DesugaringStep<Translatable> {
super(
"Checks that a translation is valid and internally consistent",
["*"],
"CheckTranslation",
"CheckTranslation"
)
this._allowUndefined = allowUndefined
}
@ -672,7 +676,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
isBuiltin: boolean,
doesImageExist: DoesImageExist,
studioValidations: boolean = false,
skipDefaultLayers: boolean = false,
skipDefaultLayers: boolean = false
) {
super("Thin wrapper around 'ValidateLayer", [], "ValidateLayerConfig")
this.validator = new ValidateLayer(
@ -680,7 +684,7 @@ export class ValidateLayerConfig extends DesugaringStep<LayerConfigJson> {
isBuiltin,
doesImageExist,
studioValidations,
skipDefaultLayers,
skipDefaultLayers
)
}
@ -708,7 +712,7 @@ export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJ
context
.enter("markers")
.err(
`Detected a field 'markerS' in pointRendering. It is written as a singular case`,
`Detected a field 'markerS' in pointRendering. It is written as a singular case`
)
}
if (json.marker && !Array.isArray(json.marker)) {
@ -718,7 +722,7 @@ export class ValidatePointRendering extends DesugaringStep<PointRenderingConfigJ
context
.enter("location")
.err(
"A pointRendering should have at least one 'location' to defined where it should be rendered. ",
"A pointRendering should have at least one 'location' to defined where it should be rendered. "
)
}
return json
@ -737,26 +741,26 @@ export class ValidateLayer extends Conversion<
isBuiltin: boolean,
doesImageExist: DoesImageExist,
studioValidations: boolean = false,
skipDefaultLayers: boolean = false,
skipDefaultLayers: boolean = false
) {
super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer")
this._prevalidation = new PrevalidateLayer(
path,
isBuiltin,
doesImageExist,
studioValidations,
studioValidations
)
this._skipDefaultLayers = skipDefaultLayers
}
convert(
json: LayerConfigJson,
context: ConversionContext,
context: ConversionContext
): { parsed: LayerConfig; raw: LayerConfigJson } {
context = context.inOperation(this.name)
if (typeof json === "string") {
context.err(
`Not a valid layer: the layerConfig is a string. 'npm run generate:layeroverview' might be needed`,
`Not a valid layer: the layerConfig is a string. 'npm run generate:layeroverview' might be needed`
)
return undefined
}
@ -787,7 +791,7 @@ export class ValidateLayer extends Conversion<
context
.enters("calculatedTags", i)
.err(
`Invalid function definition: the custom javascript is invalid:${e}. The offending javascript code is:\n ${code}`,
`Invalid function definition: the custom javascript is invalid:${e}. The offending javascript code is:\n ${code}`
)
}
}
@ -835,7 +839,7 @@ export class ValidateLayer extends Conversion<
context
.enters("allowMove", "enableAccuracy")
.err(
"`enableAccuracy` is written with two C in the first occurrence and only one in the last",
"`enableAccuracy` is written with two C in the first occurrence and only one in the last"
)
}
@ -866,8 +870,8 @@ export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
.enters("fields", i)
.err(
`Invalid filter: ${type} is not a valid textfield type.\n\tTry one of ${Array.from(
Validators.availableTypes,
).join(",")}`,
Validators.availableTypes
).join(",")}`
)
}
}
@ -884,13 +888,13 @@ export class DetectDuplicateFilters extends DesugaringStep<{
super(
"Tries to detect layers where a shared filter can be used (or where similar filters occur)",
[],
"DetectDuplicateFilters",
"DetectDuplicateFilters"
)
}
convert(
json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] },
context: ConversionContext,
context: ConversionContext
): { layers: LayerConfigJson[]; themes: LayoutConfigJson[] } {
const { layers, themes } = json
const perOsmTag = new Map<
@ -954,7 +958,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{
filter: FilterConfigJson
}[]
>,
layout?: LayoutConfigJson | undefined,
layout?: LayoutConfigJson | undefined
): void {
if (layer.filter === undefined || layer.filter === null) {
return
@ -994,7 +998,7 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
super(
"Detects mappings which have identical (english) names or identical mappings.",
["presets"],
"DetectDuplicatePresets",
"DetectDuplicatePresets"
)
}
@ -1005,13 +1009,13 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
if (new Set(enNames).size != enNames.length) {
const dups = Utils.Duplicates(enNames)
const layersWithDup = json.layers.filter((l) =>
l.presets.some((p) => dups.indexOf(p.title.textFor("en")) >= 0),
l.presets.some((p) => dups.indexOf(p.title.textFor("en")) >= 0)
)
const layerIds = layersWithDup.map((l) => l.id)
context.err(
`This theme has multiple presets which are named:${dups}, namely layers ${layerIds.join(
", ",
)} this is confusing for contributors and is probably the result of reusing the same layer multiple times. Use \`{"override": {"=presets": []}}\` to remove some presets`,
", "
)} this is confusing for contributors and is probably the result of reusing the same layer multiple times. Use \`{"override": {"=presets": []}}\` to remove some presets`
)
}
@ -1026,17 +1030,17 @@ export class DetectDuplicatePresets extends DesugaringStep<LayoutConfig> {
Utils.SameObject(presetATags, presetBTags) &&
Utils.sameList(
presetA.preciseInput.snapToLayers,
presetB.preciseInput.snapToLayers,
presetB.preciseInput.snapToLayers
)
) {
context.err(
`This theme has multiple presets with the same tags: ${presetATags.asHumanString(
false,
false,
{},
{}
)}, namely the preset '${presets[i].title.textFor("en")}' and '${presets[
j
].title.textFor("en")}'`,
].title.textFor("en")}'`
)
}
}
@ -1061,13 +1065,13 @@ export class ValidateThemeEnsemble extends Conversion<
super(
"Validates that all themes together are logical, i.e. no duplicate ids exists within (overriden) themes",
[],
"ValidateThemeEnsemble",
"ValidateThemeEnsemble"
)
}
convert(
json: LayoutConfig[],
context: ConversionContext,
context: ConversionContext
): Map<
string,
{
@ -1118,11 +1122,11 @@ export class ValidateThemeEnsemble extends Conversion<
context.err(
[
"The layer with id '" +
id +
"' is found in multiple themes with different tag definitions:",
id +
"' is found in multiple themes with different tag definitions:",
"\t In theme " + oldTheme + ":\t" + oldTags.asHumanString(false, false, {}),
"\tIn theme " + theme.id + ":\t" + tags.asHumanString(false, false, {}),
].join("\n"),
].join("\n")
)
}
}