forked from MapComplete/MapComplete
Themes: add extra check so that in a mapping cannot override the , fix two such instances
This commit is contained in:
parent
393d4e75d8
commit
56ea1163bb
3 changed files with 145 additions and 92 deletions
|
@ -135,7 +135,6 @@
|
||||||
"de": "Kletterschuhe können hier ausgeliehen werden"
|
"de": "Kletterschuhe können hier ausgeliehen werden"
|
||||||
},
|
},
|
||||||
"addExtraTags": [
|
"addExtraTags": [
|
||||||
"service:climbing_shoes:rental:fee=",
|
|
||||||
"service:climbing_shoes:rental:charge="
|
"service:climbing_shoes:rental:charge="
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -231,12 +231,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"if": {
|
"if": "fee=no",
|
||||||
"and": [
|
|
||||||
"fee=no",
|
|
||||||
"charge="
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"then": {
|
"then": {
|
||||||
"en": "Can be used for free",
|
"en": "Can be used for free",
|
||||||
"id": "Boleh digunakan tanpa bayaran",
|
"id": "Boleh digunakan tanpa bayaran",
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
import { DesugaringStep, Each, Fuse, On } from "./Conversion"
|
import {DesugaringStep, Each, Fuse, On} from "./Conversion"
|
||||||
import { LayerConfigJson } from "../Json/LayerConfigJson"
|
import {LayerConfigJson} from "../Json/LayerConfigJson"
|
||||||
import LayerConfig from "../LayerConfig"
|
import LayerConfig from "../LayerConfig"
|
||||||
import { Utils } from "../../../Utils"
|
import {Utils} from "../../../Utils"
|
||||||
import Constants from "../../Constants"
|
import Constants from "../../Constants"
|
||||||
import { Translation } from "../../../UI/i18n/Translation"
|
import {Translation} from "../../../UI/i18n/Translation"
|
||||||
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
|
import {LayoutConfigJson} from "../Json/LayoutConfigJson"
|
||||||
import LayoutConfig from "../LayoutConfig"
|
import LayoutConfig from "../LayoutConfig"
|
||||||
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
|
import {TagRenderingConfigJson} from "../Json/TagRenderingConfigJson"
|
||||||
import { TagUtils } from "../../../Logic/Tags/TagUtils"
|
import {TagUtils} from "../../../Logic/Tags/TagUtils"
|
||||||
import { ExtractImages } from "./FixImages"
|
import {ExtractImages} from "./FixImages"
|
||||||
import { And } from "../../../Logic/Tags/And"
|
import {And} from "../../../Logic/Tags/And"
|
||||||
import Translations from "../../../UI/i18n/Translations"
|
import Translations from "../../../UI/i18n/Translations"
|
||||||
import Svg from "../../../Svg"
|
import Svg from "../../../Svg"
|
||||||
import FilterConfigJson from "../Json/FilterConfigJson"
|
import FilterConfigJson from "../Json/FilterConfigJson"
|
||||||
import DeleteConfig from "../DeleteConfig"
|
import DeleteConfig from "../DeleteConfig"
|
||||||
import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
|
import {QuestionableTagRenderingConfigJson} from "../Json/QuestionableTagRenderingConfigJson"
|
||||||
import Validators from "../../../UI/InputElement/Validators"
|
import Validators from "../../../UI/InputElement/Validators"
|
||||||
|
import TagRenderingConfig from "../TagRenderingConfig";
|
||||||
|
|
||||||
class ValidateLanguageCompleteness extends DesugaringStep<any> {
|
class ValidateLanguageCompleteness extends DesugaringStep<any> {
|
||||||
private readonly _languages: string[]
|
private readonly _languages: string[]
|
||||||
|
@ -85,7 +86,7 @@ export class DoesImageExist extends DesugaringStep<string> {
|
||||||
context: string
|
context: string
|
||||||
): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } {
|
): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } {
|
||||||
if (this._ignore?.has(image)) {
|
if (this._ignore?.has(image)) {
|
||||||
return { result: image }
|
return {result: image}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errors = []
|
const errors = []
|
||||||
|
@ -93,22 +94,22 @@ export class DoesImageExist extends DesugaringStep<string> {
|
||||||
const information = []
|
const information = []
|
||||||
if (image.indexOf("{") >= 0) {
|
if (image.indexOf("{") >= 0) {
|
||||||
information.push("Ignoring image with { in the path: " + image)
|
information.push("Ignoring image with { in the path: " + image)
|
||||||
return { result: image }
|
return {result: image}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image === "assets/SocialImage.png") {
|
if (image === "assets/SocialImage.png") {
|
||||||
return { result: image }
|
return {result: image}
|
||||||
}
|
}
|
||||||
if (image.match(/[a-z]*/)) {
|
if (image.match(/[a-z]*/)) {
|
||||||
if (Svg.All[image + ".svg"] !== undefined) {
|
if (Svg.All[image + ".svg"] !== undefined) {
|
||||||
// This is a builtin img, e.g. 'checkmark' or 'crosshair'
|
// This is a builtin img, e.g. 'checkmark' or 'crosshair'
|
||||||
return { result: image }
|
return {result: image}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image.startsWith("<") && image.endsWith(">")) {
|
if (image.startsWith("<") && image.endsWith(">")) {
|
||||||
// This is probably HTML, you're on your own here
|
// This is probably HTML, you're on your own here
|
||||||
return { result: image }
|
return {result: image}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._knownImagePaths.has(image)) {
|
if (!this._knownImagePaths.has(image)) {
|
||||||
|
@ -312,7 +313,7 @@ class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
|
||||||
): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } {
|
): { result: LayoutConfigJson; errors?: string[]; warnings?: string[] } {
|
||||||
const overrideAll = json.overrideAll
|
const overrideAll = json.overrideAll
|
||||||
if (overrideAll === undefined) {
|
if (overrideAll === undefined) {
|
||||||
return { result: json }
|
return {result: json}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errors = []
|
const errors = []
|
||||||
|
@ -339,7 +340,7 @@ class OverrideShadowingCheck extends DesugaringStep<LayoutConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { result: json, errors }
|
return {result: json, errors}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +384,51 @@ export class PrevalidateTheme extends Fuse<LayoutConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class DetectConflictingAddExtraTags extends DesugaringStep<TagRenderingConfigJson> {
|
||||||
|
constructor() {
|
||||||
|
super("The `if`-part in a mapping might set some keys. Those key are not allowed to be set in the `addExtraTags`, as this might result in conflicting values", [], "DetectConflictingAddExtraTags");
|
||||||
|
}
|
||||||
|
|
||||||
|
convert(json: TagRenderingConfigJson, context: string): {
|
||||||
|
result: TagRenderingConfigJson;
|
||||||
|
errors?: string[];
|
||||||
|
warnings?: string[];
|
||||||
|
information?: string[]
|
||||||
|
} {
|
||||||
|
|
||||||
|
if (!(json.mappings?.length > 0)) {
|
||||||
|
return {result: json}
|
||||||
|
}
|
||||||
|
|
||||||
|
const tagRendering = new TagRenderingConfig(json)
|
||||||
|
|
||||||
|
const errors = []
|
||||||
|
for (let i = 0; i < tagRendering.mappings.length; i++) {
|
||||||
|
const mapping = tagRendering.mappings[i];
|
||||||
|
if (!mapping.addExtraTags) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const keysInMapping = new Set(mapping.if.usedKeys())
|
||||||
|
|
||||||
|
const keysInAddExtraTags = mapping.addExtraTags.map(t => t.key)
|
||||||
|
|
||||||
|
const duplicateKeys = keysInAddExtraTags.filter(k => keysInMapping.has(k))
|
||||||
|
if (duplicateKeys.length > 0) {
|
||||||
|
errors.push(
|
||||||
|
"At " + context + ".mappings[" + i + "]: 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(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
result: json,
|
||||||
|
errors
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJson> {
|
export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJson> {
|
||||||
private readonly _calculatedTagNames: string[]
|
private readonly _calculatedTagNames: string[]
|
||||||
|
|
||||||
|
@ -449,7 +495,7 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
|
||||||
const errors = []
|
const errors = []
|
||||||
const warnings = []
|
const warnings = []
|
||||||
if (json.mappings === undefined || json.mappings.length === 0) {
|
if (json.mappings === undefined || json.mappings.length === 0) {
|
||||||
return { result: json }
|
return {result: json}
|
||||||
}
|
}
|
||||||
const defaultProperties = {}
|
const defaultProperties = {}
|
||||||
for (const calculatedTagName of this._calculatedTagNames) {
|
for (const calculatedTagName of this._calculatedTagNames) {
|
||||||
|
@ -475,7 +521,7 @@ export class DetectShadowedMappings extends DesugaringStep<TagRenderingConfigJso
|
||||||
}
|
}
|
||||||
const keyValues = parsedConditions[i].asChange(defaultProperties)
|
const keyValues = parsedConditions[i].asChange(defaultProperties)
|
||||||
const properties = {}
|
const properties = {}
|
||||||
keyValues.forEach(({ k, v }) => {
|
keyValues.forEach(({k, v}) => {
|
||||||
properties[k] = v
|
properties[k] = v
|
||||||
})
|
})
|
||||||
for (let j = 0; j < i; j++) {
|
for (let j = 0; j < i; j++) {
|
||||||
|
@ -564,7 +610,7 @@ export class DetectMappingsWithImages extends DesugaringStep<TagRenderingConfigJ
|
||||||
const warnings: string[] = []
|
const warnings: string[] = []
|
||||||
const information: string[] = []
|
const information: string[] = []
|
||||||
if (json.mappings === undefined || json.mappings.length === 0) {
|
if (json.mappings === undefined || json.mappings.length === 0) {
|
||||||
return { result: json }
|
return {result: json}
|
||||||
}
|
}
|
||||||
const ignoreToken = "ignore-image-in-then"
|
const ignoreToken = "ignore-image-in-then"
|
||||||
for (let i = 0; i < json.mappings.length; i++) {
|
for (let i = 0; i < json.mappings.length; i++) {
|
||||||
|
@ -669,6 +715,7 @@ export class ValidateTagRenderings extends Fuse<TagRenderingConfigJson> {
|
||||||
super(
|
super(
|
||||||
"Various validation on tagRenderingConfigs",
|
"Various validation on tagRenderingConfigs",
|
||||||
new DetectShadowedMappings(layerConfig),
|
new DetectShadowedMappings(layerConfig),
|
||||||
|
new DetectConflictingAddExtraTags(),
|
||||||
new DetectMappingsWithImages(doesImageExist),
|
new DetectMappingsWithImages(doesImageExist),
|
||||||
new MiscTagRenderingChecks(options)
|
new MiscTagRenderingChecks(options)
|
||||||
)
|
)
|
||||||
|
@ -865,6 +912,13 @@ export class ValidateLayer extends DesugaringStep<LayerConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (json.filter) {
|
||||||
|
const r = new On("filter", new Each( new ValidateFilter())).convert(json, context)
|
||||||
|
warnings.push(...(r.warnings ?? []))
|
||||||
|
errors.push(...(r.errors ?? []))
|
||||||
|
information.push(...(r.information ?? []))
|
||||||
|
}
|
||||||
|
|
||||||
if (json.tagRenderings !== undefined) {
|
if (json.tagRenderings !== undefined) {
|
||||||
const r = new On(
|
const r = new On(
|
||||||
"tagRenderings",
|
"tagRenderings",
|
||||||
|
@ -903,7 +957,7 @@ export class ValidateLayer extends DesugaringStep<LayerConfigJson> {
|
||||||
const preset = json.presets[i]
|
const preset = json.presets[i]
|
||||||
const tags: { k: string; v: string }[] = new And(
|
const tags: { k: string; v: string }[] = new And(
|
||||||
preset.tags.map((t) => TagUtils.Tag(t))
|
preset.tags.map((t) => TagUtils.Tag(t))
|
||||||
).asChange({ id: "node/-1" })
|
).asChange({id: "node/-1"})
|
||||||
const properties = {}
|
const properties = {}
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
properties[tag.k] = tag.v
|
properties[tag.k] = tag.v
|
||||||
|
@ -949,9 +1003,14 @@ export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
|
||||||
warnings?: string[]
|
warnings?: string[]
|
||||||
information?: string[]
|
information?: string[]
|
||||||
} {
|
} {
|
||||||
|
if (typeof filter === "string") {
|
||||||
|
// Calling another filter, we skip
|
||||||
|
return {result: filter}
|
||||||
|
}
|
||||||
const errors = []
|
const errors = []
|
||||||
for (const option of filter.options) {
|
for (const option of filter.options) {
|
||||||
for (let i = 0; i < option.fields.length; i++) {
|
|
||||||
|
for (let i = 0; i < option.fields?.length ?? 0; i++) {
|
||||||
const field = option.fields[i]
|
const field = option.fields[i]
|
||||||
const type = field.type ?? "string"
|
const type = field.type ?? "string"
|
||||||
if (Validators.availableTypes.find((t) => t === type) === undefined) {
|
if (Validators.availableTypes.find((t) => t === type) === undefined) {
|
||||||
|
@ -962,7 +1021,7 @@ export class ValidateFilter extends DesugaringStep<FilterConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { result: filter, errors }
|
return {result: filter, errors}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,7 +1050,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{
|
||||||
const warnings: string[] = []
|
const warnings: string[] = []
|
||||||
const information: string[] = []
|
const information: string[] = []
|
||||||
|
|
||||||
const { layers, themes } = json
|
const {layers, themes} = json
|
||||||
const perOsmTag = new Map<
|
const perOsmTag = new Map<
|
||||||
string,
|
string,
|
||||||
{
|
{
|
||||||
|
@ -1027,7 +1086,7 @@ export class DetectDuplicateFilters extends DesugaringStep<{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let msg = "Possible duplicate filter: " + key
|
let msg = "Possible duplicate filter: " + key
|
||||||
for (const { filter, layer, layout } of value) {
|
for (const {filter, layer, layout} of value) {
|
||||||
let id = ""
|
let id = ""
|
||||||
if (layout !== undefined) {
|
if (layout !== undefined) {
|
||||||
id = layout.id + ":"
|
id = layout.id + ":"
|
||||||
|
|
Loading…
Add table
Reference in a new issue