diff --git a/src/Logic/Tags/And.ts b/src/Logic/Tags/And.ts index 0a7b021f2a..378518dd14 100644 --- a/src/Logic/Tags/And.ts +++ b/src/Logic/Tags/And.ts @@ -72,11 +72,17 @@ export class And extends TagsFilter { return allChoices } - asHumanString(linkToWiki: boolean, shorten: boolean, properties) { + asHumanString(linkToWiki: boolean, shorten: boolean, properties: Record) { return this.and - .map((t) => t.asHumanString(linkToWiki, shorten, properties)) + .map((t) => { + let e = t.asHumanString(linkToWiki, shorten, properties) + if (t["or"]) { + e = "(" + e + ")" + } + return e + }) .filter((x) => x !== "") - .join(" &") + .join(" & ") } isUsableAsAnswer(): boolean { diff --git a/src/Logic/Tags/Or.ts b/src/Logic/Tags/Or.ts index 9fe456b559..f7018c40b0 100644 --- a/src/Logic/Tags/Or.ts +++ b/src/Logic/Tags/Or.ts @@ -49,8 +49,16 @@ export class Or extends TagsFilter { return choices } - asHumanString(linkToWiki: boolean, shorten: boolean, properties) { - return this.or.map((t) => t.asHumanString(linkToWiki, shorten, properties)).join(" |") + asHumanString(linkToWiki: boolean, shorten: boolean, properties: Record) { + return this.or + .map((t) => { + let e = t.asHumanString(linkToWiki, shorten, properties) + if (t["and"]) { + e = "(" + e + ")" + } + return e + }) + .join(" | ") } isUsableAsAnswer(): boolean { diff --git a/src/Logic/Tags/Tag.ts b/src/Logic/Tags/Tag.ts index 5142c5c62b..7cb01a9d5e 100644 --- a/src/Logic/Tags/Tag.ts +++ b/src/Logic/Tags/Tag.ts @@ -86,6 +86,11 @@ export class Tag extends TagsFilter { v = Utils.EllipsesAfter(v, 25) } if ((v === "" || v === undefined) && currentProperties !== undefined) { + if (!currentProperties || Object.keys(currentProperties).length === 0) { + // We are probably generating documentation + return this.key + "=" + } + // This tag will be removed if in the properties, so we indicate this with special rendering if ((currentProperties[this.key] ?? "") === "") { // This tag is not present in the current properties, so this tag doesn't change anything diff --git a/src/Models/ThemeConfig/LayerConfig.ts b/src/Models/ThemeConfig/LayerConfig.ts index 387442ee35..57c6bac55a 100644 --- a/src/Models/ThemeConfig/LayerConfig.ts +++ b/src/Models/ThemeConfig/LayerConfig.ts @@ -22,7 +22,6 @@ import { Utils } from "../../Utils" import { TagsFilter } from "../../Logic/Tags/TagsFilter" import Table from "../../UI/Base/Table" import FilterConfigJson from "./Json/FilterConfigJson" -import { And } from "../../Logic/Tags/And" import { Overpass } from "../../Logic/Osm/Overpass" import { FixedUiElement } from "../../UI/Base/FixedUiElement" import Svg from "../../Svg" @@ -458,11 +457,6 @@ export default class LayerConfig extends WithContextLoader { ) } - let neededTags: TagsFilter[] = Utils.NoNull([this.source?.osmTags]) - if (this.source?.osmTags["and"] !== undefined) { - neededTags = this.source.osmTags["and"] - } - const tableRows = Utils.NoNull( this.tagRenderings .map((tr) => tr.FreeformValues()) @@ -523,7 +517,7 @@ export default class LayerConfig extends WithContextLoader { try { overpassLink = new Link( "Execute on overpass", - Overpass.AsOverpassTurboLink(new And(neededTags).optimize()) + Overpass.AsOverpassTurboLink(this.source.osmTags.optimize()) .replaceAll("(", "%28") .replaceAll(")", "%29") ) @@ -540,12 +534,30 @@ export default class LayerConfig extends WithContextLoader { const tagsDescription = [] if (this.source !== null) { - tagsDescription.push( - new Title("Basic tags for this layer", 2), - "Elements must have the all of following tags to be shown on this layer:", - new List(neededTags.map((t) => t.asHumanString(true, false, {}))), - overpassLink - ) + tagsDescription.push(new Title("Basic tags for this layer", 2)) + + const neededTags = this.source.osmTags.optimize() + if (neededTags["and"]) { + const parts = neededTags["and"] + tagsDescription.push( + "Elements must match **all** of the following expressions:", + parts.map((p, i) => i + ". " + p.asHumanString(true, false, {})).join("\n") + ) + } else if (neededTags["or"]) { + const parts = neededTags["or"] + tagsDescription.push( + "Elements must match **any** of the following expressions:", + parts.map((p) => " - " + p.asHumanString(true, false, {})).join("\n") + ) + } else { + tagsDescription.push( + "Elements must match the expression **" + + neededTags.asHumanString(true, false, {}) + + "**" + ) + } + + tagsDescription.push(overpassLink) } else { tagsDescription.push("This is a special layer - data is not sourced from OpenStreetMap") } diff --git a/src/Models/ThemeConfig/TagRenderingConfig.ts b/src/Models/ThemeConfig/TagRenderingConfig.ts index 3040fcf442..d6d3d15a42 100644 --- a/src/Models/ThemeConfig/TagRenderingConfig.ts +++ b/src/Models/ThemeConfig/TagRenderingConfig.ts @@ -746,17 +746,11 @@ export default class TagRenderingConfig { new Combine([ new FixedUiElement(m.then.txt).SetClass("font-bold"), " corresponds with ", - new FixedUiElement(m.if.asHumanString(false, false, {})).SetClass( - "code" - ), + m.if.asHumanString(true, false, {}), ]), ] if (m.hideInAnswer === true) { - msgs.push( - new FixedUiElement( - "This option cannot be chosen as answer" - ).SetClass("italic") - ) + msgs.push("_This option cannot be chosen as answer_") } if (m.ifnot !== undefined) { msgs.push( @@ -774,7 +768,9 @@ export default class TagRenderingConfig { if (this.condition !== undefined && !this.condition?.matchesProperties({})) { condition = new Combine([ "This tagrendering is only visible in the popup if the following condition is met:", - new FixedUiElement(this.condition.asHumanString(false, false, {})).SetClass("code"), + new FixedUiElement( + (this.condition.optimize()).asHumanString(true, false, {}) + ).SetClass("code"), ]) }