Merge develop

This commit is contained in:
Pieter Vander Vennet 2023-10-30 16:32:43 +01:00
commit 29ff09024f
287 changed files with 14955 additions and 4036 deletions

View file

@ -1,6 +1,7 @@
import { LayerConfigJson } from "../Json/LayerConfigJson"
import { Utils } from "../../../Utils"
import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
import ScriptUtils from "../../../../scripts/ScriptUtils"
export interface DesugaringContext {
tagRenderings: Map<string, QuestionableTagRenderingConfigJson>
@ -28,6 +29,9 @@ export class ConversionContext {
this.operation = operation ?? []
// Messages is shared by reference amonst all 'context'-objects for performance
this.messages = messages
if (this.path.some((p) => typeof p === "object" || p === "[object Object]")) {
throw "ConversionMessage: got an object as path entry:" + JSON.stringify(path)
}
}
public static construct(path: (string | number)[], operation: string[]) {
@ -105,6 +109,10 @@ export class ConversionContext {
public hasErrors() {
return this.messages?.find((m) => m.level === "error") !== undefined
}
debug(message: string) {
this.messages.push({ context: this, level: "debug", message })
}
}
export type ConversionMsgLevel = "debug" | "information" | "warning" | "error"
@ -178,14 +186,16 @@ export class Pure<TIn, TOut> extends Conversion<TIn, TOut> {
export class Each<X, Y> extends Conversion<X[], Y[]> {
private readonly _step: Conversion<X, Y>
private readonly _msg: string
constructor(step: Conversion<X, Y>) {
constructor(step: Conversion<X, Y>, msg?: string) {
super(
"Applies the given step on every element of the list",
[],
"OnEach(" + step.name + ")"
)
this._step = step
this._msg = msg
}
convert(values: X[], context: ConversionContext): Y[] {
@ -196,6 +206,9 @@ export class Each<X, Y> extends Conversion<X[], Y[]> {
const result: Y[] = []
const c = context.inOperation("each")
for (let i = 0; i < values.length; i++) {
if (this._msg) {
ScriptUtils.erasableLog(this._msg, `: ${i + 1}/${values.length}`)
}
const context_ = c.enter(i - 1)
const r = step.convert(values[i], context_)
result.push(r)

View file

@ -91,7 +91,7 @@ export class DoesImageExist extends DesugaringStep<string> {
}
if (image.indexOf("{") >= 0) {
context.info("Ignoring image with { in the path: " + image)
context.debug("Ignoring image with { in the path: " + image)
return image
}
@ -275,7 +275,8 @@ export class ValidateThemeAndLayers extends Fuse<LayoutConfigJson> {
doesImageExist: DoesImageExist,
path: string,
isBuiltin: boolean,
sharedTagRenderings?: Set<string>
sharedTagRenderings?: Set<string>,
msg?: string
) {
super(
"Validates a theme and the contained layers",
@ -284,9 +285,10 @@ export class ValidateThemeAndLayers extends Fuse<LayoutConfigJson> {
"layers",
new Each(
new Pipe(
new ValidateLayer(undefined, isBuiltin, doesImageExist),
new ValidateLayer(undefined, isBuiltin, doesImageExist, false, true),
new Pure((x) => x.raw)
)
),
msg
)
)
)
@ -807,18 +809,21 @@ export class ValidateLayer extends Conversion<
private readonly _isBuiltin: boolean
private readonly _doesImageExist: DoesImageExist
private readonly _studioValidations: boolean
private _skipDefaultLayers: boolean
constructor(
path: string,
isBuiltin: boolean,
doesImageExist: DoesImageExist,
studioValidations: boolean = false
studioValidations: boolean = false,
skipDefaultLayers: boolean = false
) {
super("Doesn't change anything, but emits warnings and errors", [], "ValidateLayer")
this._path = path
this._isBuiltin = isBuiltin
this._doesImageExist = doesImageExist
this._studioValidations = studioValidations
this._skipDefaultLayers = skipDefaultLayers
}
convert(
@ -831,6 +836,10 @@ export class ValidateLayer extends Conversion<
return null
}
if (this._skipDefaultLayers && Constants.added_by_default.indexOf(<any>json.id) >= 0) {
return { parsed: undefined, raw: json }
}
if (typeof json === "string") {
context.err(
`Not a valid layer: the layerConfig is a string. 'npm run generate:layeroverview' might be needed`
@ -1102,7 +1111,7 @@ export class ValidateLayer extends Conversion<
).convert(json, context)
}
if (json.pointRendering !== null) {
if (json.pointRendering !== null && json.pointRendering !== undefined) {
if (!Array.isArray(json.pointRendering)) {
throw (
"pointRendering in " +
@ -1111,8 +1120,11 @@ export class ValidateLayer extends Conversion<
typeof json.pointRendering
)
}
for (const pointRendering of json.pointRendering) {
const index = json.pointRendering.indexOf(pointRendering)
for (let i = 0; i < json.pointRendering.length; i++) {
const pointRendering = json.pointRendering[i]
if (pointRendering.marker === undefined) {
continue
}
for (const icon of pointRendering?.marker) {
const indexM = pointRendering?.marker.indexOf(icon)
if (!icon.icon) {
@ -1120,14 +1132,7 @@ export class ValidateLayer extends Conversion<
}
if (icon.icon["condition"]) {
context
.enters(
"pointRendering",
index,
"marker",
indexM,
"icon",
"condition"
)
.enters("pointRendering", i, "marker", indexM, "icon", "condition")
.err(
"Don't set a condition in a marker as this will result in an invisible but clickable element. Use extra filters in the source instead."
)

View file

@ -171,7 +171,11 @@ export default class LayerConfig extends WithContextLoader {
maxSnapDistance: undefined,
}
if (pr["preciseInput"] !== undefined) {
throw "Layer " + this.id + " still uses the old 'preciseInput'-field"
throw (
"Layer " +
this.id +
" still uses the old 'preciseInput'-field. For snapping to layers, use 'snapToLayer' instead"
)
}
if (pr.snapToLayer !== undefined) {
let snapToLayers = pr.snapToLayer
@ -459,7 +463,7 @@ export default class LayerConfig extends WithContextLoader {
neededTags = this.source.osmTags["and"]
}
let tableRows = Utils.NoNull(
const tableRows = Utils.NoNull(
this.tagRenderings
.map((tr) => tr.FreeformValues())
.map((values) => {

View file

@ -101,11 +101,11 @@ export default class LayoutConfig implements LayoutInformation {
}
}
const context = this.id
this.credits = typeof json.credits === "string" ? json.credits : json.credits?.join(", ")
this.language = Array.from(
new Set((json.mustHaveLanguage ?? []).concat(Object.keys(json.title ?? {})))
)
this.credits = Array.isArray(json.credits) ? json.credits.join("; ") : json.credits
if (!json.title) {
throw `The theme ${json.id} does not have a title defined.`
}
this.language = json.mustHaveLanguage ?? Object.keys(json.title)
this.usedImages = Array.from(
new ExtractImages(official, undefined)
.convertStrict(json, ConversionContext.construct([json.id], ["ExtractImages"]))