forked from MapComplete/MapComplete
Feature: allow a fallback value in substituting tags
This commit is contained in:
parent
35c4222466
commit
4d4a7e9d84
3 changed files with 32 additions and 32 deletions
|
@ -126,23 +126,7 @@ export class TagUtils {
|
|||
"\n" +
|
||||
"An assigning tag _cannot_ be used to query OpenStreetMap/Overpass.\n" +
|
||||
"\n" +
|
||||
"If using a key or variable which might not be defined, add a condition in the mapping to hide the option. This is\n" +
|
||||
"because, if `some_other_key` is not defined, one might actually upload the literal text `key={some_other_key}` to OSM -\n" +
|
||||
"which we do not want.\n" +
|
||||
"\n" +
|
||||
"To mitigate this, use:\n" +
|
||||
"\n" +
|
||||
"```json\n" +
|
||||
"{\n" +
|
||||
' "mappings": [\n' +
|
||||
" {\n" +
|
||||
' "if":"key:={some_other_key}",\n' +
|
||||
' "then": "...",\n' +
|
||||
' "hideInAnswer": "some_other_key="\n' +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}\n" +
|
||||
"```\n" +
|
||||
"It is possible to assign a default value with `key_to_assing:={some_other_key??fallback_value}`. If `some_other_key` is not present, then the literal value `fallback_value` will be used instead." +
|
||||
"\n" +
|
||||
"One can use `key!:=prefix-{other_key}-postfix` as well, to match if `key` is _not_ the same\n" +
|
||||
"as `prefix-{other_key}-postfix` (with `other_key` substituted by the value)",
|
||||
|
@ -263,8 +247,8 @@ export class TagUtils {
|
|||
return tags
|
||||
}
|
||||
|
||||
static SplitKeys(tagsFilters: UploadableTag[]): Record<string, string[]> {
|
||||
return this.SplitKeysRegex(tagsFilters, false)
|
||||
static SplitKeys(tagsFilters: UploadableTag[], currentProperties: Tags): Record<string, string[]> {
|
||||
return this.SplitKeysRegex(tagsFilters, false, currentProperties)
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -272,24 +256,31 @@ export class TagUtils {
|
|||
*
|
||||
* TagUtils.SplitKeysRegex([new Tag("isced:level", "bachelor; master")], true) // => {"isced:level": ["bachelor","master"]}
|
||||
*/
|
||||
static SplitKeysRegex(tagsFilters: UploadableTag[], allowRegex: false): Record<string, string[]>
|
||||
static SplitKeysRegex(tagsFilters: ReadonlyArray<UploadableTag>, allowRegex: false,
|
||||
currentProperties: Tags): Record<string, string[]>
|
||||
static SplitKeysRegex(
|
||||
tagsFilters: UploadableTag[],
|
||||
allowRegex: boolean
|
||||
tagsFilters: ReadonlyArray<UploadableTag>,
|
||||
allowRegex: boolean,
|
||||
currentProperties: Tags
|
||||
): Record<string, (string | RegexTag)[]>
|
||||
static SplitKeysRegex(
|
||||
tagsFilters: UploadableTag[],
|
||||
allowRegex: boolean
|
||||
tagsFiltersIn: ReadonlyArray<UploadableTag>,
|
||||
allowRegex: boolean,
|
||||
currentProperties: Tags
|
||||
): Record<string, (string | RegexTag)[]> {
|
||||
const keyValues: Record<string, (string | RegexTag)[]> = {}
|
||||
tagsFilters = [...tagsFilters] // copy all, use as queue
|
||||
const tagsFilters = [...tagsFiltersIn] // copy all, use as queue
|
||||
while (tagsFilters.length > 0) {
|
||||
const tagsFilter = tagsFilters.shift()
|
||||
let tagsFilter = tagsFilters.shift()
|
||||
|
||||
if (tagsFilter === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (tagsFilter instanceof SubstitutingTag) {
|
||||
tagsFilter = (<SubstitutingTag>tagsFilter).asTag(currentProperties)
|
||||
}
|
||||
|
||||
if (tagsFilter instanceof And) {
|
||||
tagsFilters.push(...(<UploadableTag[]>tagsFilter.and))
|
||||
continue
|
||||
|
@ -360,12 +351,12 @@ export class TagUtils {
|
|||
* TagUtils.FlattenMultiAnswer(([new Tag("x","y"), new Tag("a","b")])) // => [new Tag("x","y"), new Tag("a","b")]
|
||||
* TagUtils.FlattenMultiAnswer(([new Tag("x","")])) // => [new Tag("x","")]
|
||||
*/
|
||||
static FlattenMultiAnswer(tagsFilters: UploadableTag[]): UploadableTag[] {
|
||||
static FlattenMultiAnswer(tagsFilters: UploadableTag[], currentProperties: Tags): UploadableTag[] {
|
||||
if (tagsFilters === undefined) {
|
||||
return []
|
||||
}
|
||||
|
||||
const keyValues = TagUtils.SplitKeys(tagsFilters)
|
||||
const keyValues = TagUtils.SplitKeys(tagsFilters, currentProperties)
|
||||
const and: UploadableTag[] = []
|
||||
for (const key in keyValues) {
|
||||
const values = Lists.dedup(keyValues[key]).filter((v) => v !== "")
|
||||
|
@ -387,7 +378,7 @@ export class TagUtils {
|
|||
* TagUtils.MatchesMultiAnswer(new Tag("isced:level","master"), {"isced:level":"bachelor; master"}) // => true
|
||||
*/
|
||||
static MatchesMultiAnswer(tag: UploadableTag, properties: Tags): boolean {
|
||||
const splitted = TagUtils.SplitKeysRegex([tag], true)
|
||||
const splitted = TagUtils.SplitKeysRegex([tag], true, properties)
|
||||
for (const splitKey in splitted) {
|
||||
const neededValues = splitted[splitKey]
|
||||
if (properties[splitKey] === undefined) {
|
||||
|
|
|
@ -897,7 +897,7 @@ export default class TagRenderingConfig {
|
|||
])
|
||||
)
|
||||
}
|
||||
const and = TagUtils.FlattenMultiAnswer([...selectedMappings, ...unselectedMappings])
|
||||
const and = TagUtils.FlattenMultiAnswer([...selectedMappings, ...unselectedMappings], currentProperties)
|
||||
if (and.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
|
|
13
src/Utils.ts
13
src/Utils.ts
|
@ -300,6 +300,10 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
|||
* Utils.SubstituteKeys("abc{def}ghi", {def: '{XYZ}'}) // => "abc{XYZ}ghi"
|
||||
* Utils.SubstituteKeys("abc\n\n{def}ghi", {def: '{XYZ}'}) // => "abc\n\n{XYZ}ghi"
|
||||
*
|
||||
* // Should support a default value
|
||||
* Utils.SubstituteKeys("abc{def??XXX}ghi", {def: 'XYZ'}) // => "abcXYZghi"
|
||||
* Utils.SubstituteKeys("abc{def??XXX}ghi", {randomKey: 'XYZ'}) // => "abcXXXghi"
|
||||
*
|
||||
* @param txt
|
||||
* @param tags
|
||||
* @param useLang
|
||||
|
@ -322,8 +326,13 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
|
|||
}
|
||||
let result = ""
|
||||
while (match) {
|
||||
const [_, normal, key, leftover] = match
|
||||
let v = tags?.[key]
|
||||
const [_, normal, keyFallback, leftover] = match
|
||||
let key = keyFallback
|
||||
let fallback = ""
|
||||
if (keyFallback.indexOf("??") >= 0) {
|
||||
[key, fallback] = keyFallback.split("??")
|
||||
}
|
||||
let v = tags?.[key] ?? fallback
|
||||
if (v !== undefined && v !== null) {
|
||||
if (v["toISOString"] != undefined) {
|
||||
// This is a date, probably the timestamp of the object
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue