From b4817f7a7faafffe716619a4d6908c013d58efd6 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 31 Oct 2024 10:49:30 +0100 Subject: [PATCH] Fix: better support for complicated regex tags --- src/Logic/State/UserSettingsMetaTagging.ts | 48 +++++----------------- src/Logic/Tags/RegexTag.ts | 24 +++++++---- src/Logic/Tags/TagUtils.ts | 25 +++++++---- 3 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/Logic/State/UserSettingsMetaTagging.ts b/src/Logic/State/UserSettingsMetaTagging.ts index 6e568c5c3..33a5ae85b 100644 --- a/src/Logic/State/UserSettingsMetaTagging.ts +++ b/src/Logic/State/UserSettingsMetaTagging.ts @@ -1,42 +1,14 @@ import { Utils } from "../../Utils" /** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */ export class ThemeMetaTagging { - public static readonly themeName = "usersettings" + public static readonly themeName = "usersettings" - public metaTaggging_for_usersettings(feat: { properties: Record }) { - Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () => - feat.properties._description - .match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/) - ?.at(1) - ) - Utils.AddLazyProperty( - feat.properties, - "_d", - () => feat.properties._description?.replace(/</g, "<")?.replace(/>/g, ">") ?? "" - ) - Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () => - ((feat) => { - const e = document.createElement("div") - e.innerHTML = feat.properties._d - return Array.from(e.getElementsByTagName("a")).filter( - (a) => a.href.match(/mastodon|en.osm.town/) !== null - )[0]?.href - })(feat) - ) - Utils.AddLazyProperty(feat.properties, "_mastodon_link", () => - ((feat) => { - const e = document.createElement("div") - e.innerHTML = feat.properties._d - return Array.from(e.getElementsByTagName("a")).filter( - (a) => a.getAttribute("rel")?.indexOf("me") >= 0 - )[0]?.href - })(feat) - ) - Utils.AddLazyProperty( - feat.properties, - "_mastodon_candidate", - () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a - ) - feat.properties["__current_backgroun"] = "initial_value" - } -} + public metaTaggging_for_usersettings(feat: {properties: Record}) { + Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) ) + Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/</g,'<')?.replace(/>/g,'>') ?? '' ) + Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) ) + Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) ) + Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a ) + feat.properties['__current_backgroun'] = 'initial_value' + } +} \ No newline at end of file diff --git a/src/Logic/Tags/RegexTag.ts b/src/Logic/Tags/RegexTag.ts index 69c3fa568..8178645d5 100644 --- a/src/Logic/Tags/RegexTag.ts +++ b/src/Logic/Tags/RegexTag.ts @@ -109,19 +109,29 @@ export class RegexTag extends TagsFilter { * * const t = TagUtils.Tag("a~i~b") * t.asJson() // => "a~i~b" + * + * const t = TagUtils.Tag("service:bicycle:.*~~*") + * t.asJson() // => "service:bicycle:.*~~.+" */ asJson(): TagConfigJson { const v = RegexTag.source(this.value, false) const valueIsString = typeof this.value === "string" - if(typeof this.key === "string" && valueIsString){ - return `${this.key}${this.invert ? "!" : ""}=${v}` - } const caseInvariant = typeof this.value !== "string" && this.value.ignoreCase - if (typeof this.key === "string" && !caseInvariant) { - return `${this.key}${this.invert ? "!" : ""}~${v}` + const invert = this.invert ? "!" : "" + if (typeof this.key === "string") { + if (valueIsString) { + return `${this.key}${invert}=${v}` + } + + if (!caseInvariant) { + return `${this.key}${invert}~${v}` + } + return `${this.key}${invert}~i~${v}` + } - const k = typeof this.key === "string" ? this.key : this.key.source - return `${k}${this.invert ? "!" : ""}~${caseInvariant ? "i": ""}~${v}` + + const key :string = RegexTag.source(this.key, false) + return `${key}${invert}~${caseInvariant ? "i~" : ""}~${v}` } isUsableAsAnswer(): boolean { diff --git a/src/Logic/Tags/TagUtils.ts b/src/Logic/Tags/TagUtils.ts index bcd73cc58..3347f5ada 100644 --- a/src/Logic/Tags/TagUtils.ts +++ b/src/Logic/Tags/TagUtils.ts @@ -99,6 +99,16 @@ export class TagUtils { overpassSupport: true, docs: "Both the `key` and `value` part of this specification are interpreted as regexes, both the key and value musth completely match their respective regexes", }, + "~i~~": { + name: "Key and value should match a given regex; value is case-invariant", + overpassSupport: true, + docs: "Similar to ~~, except that the value is case-invariant" + }, + "!~i~~": { + name: "Key and value should match a given regex; value is case-invariant", + overpassSupport: true, + docs: "Similar to !~~, except that the value is case-invariant" + }, ":=": { name: "Substitute `... {some_key} ...` and match `key`", overpassSupport: false, @@ -469,7 +479,7 @@ export class TagUtils { * TagUtils.Tag("survey:date:={_date:now}") // => new SubstitutingTag("survey:date", "{_date:now}") * TagUtils.Tag("xyz!~\\[\\]") // => new RegexTag("xyz", /^(\[\])$/s, true) * TagUtils.Tag("tags~(.*;)?amenity=public_bookcase(;.*)?") // => new RegexTag("tags", /^((.*;)?amenity=public_bookcase(;.*)?)$/s) - * TagUtils.Tag("service:bicycle:.*~~*") // => new RegexTag(/^(service:bicycle:.*)$/, /.+/si) + * TagUtils.Tag("service:bicycle:.*~i~~*") // => new RegexTag(/^(service:bicycle:.*)$/, /.+/s) * TagUtils.Tag("_first_comment~.*{search}.*") // => new RegexTag('_first_comment', /^(.*{search}.*)$/s) * * TagUtils.Tag("xyz<5").matchesProperties({xyz: 4}) // => true @@ -572,7 +582,7 @@ export class TagUtils { } /** - * Parses the various parts of a regex tag + * Parses the various parts of a regex tag. The key is never considered a regex * * TagUtils.parseRegexOperator("key~value") // => {invert: false, key: "key", value: "value", modifier: ""} * TagUtils.parseRegexOperator("key!~value") // => {invert: true, key: "key", value: "value", modifier: ""} @@ -590,7 +600,7 @@ export class TagUtils { value: string modifier: "i" | "" } | null { - const match = tag.match(/^([_|a-zA-Z0-9: -]+)(!)?~([i]~)?(.*)$/) + const match = tag.match(/^([_|a-zA-Z0-9.: -]+)(!)?~([i]~)?(.*)$/) if (match == null) { return null } @@ -790,8 +800,9 @@ export class TagUtils { } } - if (tag.indexOf("~~") >= 0) { - const split = Utils.SplitFirst(tag, "~~") + if (tag.indexOf("~~") >= 0 || tag.indexOf("~i~~") >= 0) { + const caseInvariant = tag.indexOf("~i~~") >= 0 + const split = Utils.SplitFirst(tag, caseInvariant ? "~i~~" : "~~") let keyRegex: RegExp if (split[0] === "*") { keyRegex = new RegExp(".+", "i") @@ -800,9 +811,9 @@ export class TagUtils { } let valueRegex: RegExp if (split[1] === "*") { - valueRegex = new RegExp(".+", "si") + valueRegex = new RegExp(".+", "s") } else { - valueRegex = new RegExp("^(" + split[1] + ")$", "s") + valueRegex = new RegExp("^(" + split[1] + ")$",caseInvariant ? "si": "s" ) } return new RegexTag(keyRegex, valueRegex) }