Feature: layer validation system now builds a dependency graph and only updates what is needed, makes "refresh:layeroverview" redundant

This commit is contained in:
Pieter Vander Vennet 2025-04-21 23:53:10 +02:00
parent 1bd060df82
commit fda0bc6b2e
19 changed files with 301 additions and 186 deletions

View file

@ -1,5 +1,5 @@
import ThemeConfig from "../Models/ThemeConfig/ThemeConfig"
import favourite from "../assets/generated/layers/favourite.json"
import favourite from "../../public/assets/generated/layers/favourite.json"
import { ThemeConfigJson } from "../Models/ThemeConfig/Json/ThemeConfigJson"
import { AllSharedLayers } from "./AllSharedLayers"
import Constants from "../Models/Constants"

View file

@ -9,7 +9,7 @@ import { PrepareTheme } from "../Models/ThemeConfig/Conversion/PrepareTheme"
import licenses from "../assets/generated/license_info.json"
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
import { FixImages } from "../Models/ThemeConfig/Conversion/FixImages"
import questions from "../assets/generated/layers/questions.json"
import questions from "../../public/assets/generated/layers/questions.json"
import { DoesImageExist, PrevalidateTheme } from "../Models/ThemeConfig/Conversion/Validation"
import { DesugaringContext } from "../Models/ThemeConfig/Conversion/Conversion"
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"

View file

@ -2,7 +2,7 @@ import { BBox } from "../BBox"
import { Feature, Geometry } from "geojson"
import { DefaultPinIcon } from "../../Models/Constants"
import { Store } from "../UIEventSource"
import * as search from "../../assets/generated/layers/search.json"
import * as search from "../../../public/assets/generated/layers/search.json"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
import { GeoOperations } from "../GeoOperations"

View file

@ -10,7 +10,7 @@ import translators from "../../assets/translators.json"
import codeContributors from "../../assets/contributors.json"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
import usersettings from "../../../src/assets/generated/layers/usersettings.json"
import usersettings from "../../../public/assets/generated/layers/usersettings.json"
import Locale from "../../UI/i18n/Locale"
import LinkToWeblate from "../../UI/Base/LinkToWeblate"
import FeatureSwitchState from "./FeatureSwitchState"

View file

@ -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<string, string> }) {
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(/&lt;/g, "<")?.replace(/&gt;/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<string, string>}) {
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(/&lt;/g,'<')?.replace(/&gt;/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'
}
}

View file

@ -239,11 +239,11 @@ export class ExpandFilter extends DesugaringStep<LayerConfigJson> {
)
}
const layer = this._state.sharedLayers.get(split[0])
if (layer === undefined) {
if (!layer) {
context.err("Layer '" + split[0] + "' not found")
}
const expectedId = split[1]
const expandedFilter = (<(FilterConfigJson | string)[]>layer.filter).find(
const expandedFilter = (<(FilterConfigJson | string)[]>layer?.filter)?.find(
(f) => typeof f !== "string" && f.id === expectedId
)
if (expandedFilter === undefined) {

View file

@ -380,15 +380,10 @@ export class ExpandTagRendering extends Conversion<
Utils.NoNull(Array.from(state.sharedLayers.keys())),
(s) => s
)
if (state.sharedLayers.size === 0) {
ctx.warn(
"BOOTSTRAPPING. Rerun generate layeroverview. While reusing tagrendering: " +
name +
": layer " +
layerName +
" not found for now, but ignoring as this is a bootstrapping run. "
)
if (candidates.length === 0) {
ctx.err("While reusing a tagRendering: " + name + "; no candidates in layer " + layerName)
} else {
console.error("Bench was not found...")
ctx.err(
": While reusing tagrendering: " +
name +
@ -400,10 +395,15 @@ export class ExpandTagRendering extends Conversion<
}
continue
}
if (layer.source === "special:stub") {
// We are dealing with a looping import, no error is necessary
continue
}
candidates = Utils.NoNull(layer.tagRenderings.map((tr) => tr["id"])).map(
(id) => layerName + "." + id
)
}
candidates = Utils.sortedByLevenshteinDistance(name, candidates, (i) => i)
ctx.err(
"The tagRendering with identifier " +

View file

@ -1048,6 +1048,11 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
if (json === undefined || json === null) {
throw "Error: prepareLayer got null"
}
if (json.source?.["osmTags"] !== undefined && json.source?.["osmTags"]?.["and"] === undefined) {
json = { ...json }
json.source = <any>{ ...(<object>json.source) }
json.source["osmTags"] = { "and": [json.source["osmTags"]] }
}
return super.convert(json, context)
}
}

View file

@ -78,6 +78,7 @@ export interface LayerConfigJson {
| undefined
| "special"
| "special:library"
| "special:stub" // only used when building looping imports
| {
/**
* question: Which tags must be present on the feature to show it in this layer?

View file

@ -11,14 +11,14 @@ import MetaTagging from "../../Logic/MetaTagging"
import FilteredLayer from "../FilteredLayer"
import LayerConfig from "../ThemeConfig/LayerConfig"
import { LayerConfigJson } from "../ThemeConfig/Json/LayerConfigJson"
import last_click_layerconfig from "../../assets/generated/layers/last_click.json"
import last_click_layerconfig from "../../../public/assets/generated/layers/last_click.json"
import { GeoOperations } from "../../Logic/GeoOperations"
import summaryLayer from "../../assets/generated/layers/summary.json"
import summaryLayer from "../../../public/assets/generated/layers/summary.json"
import { Store, UIEventSource } from "../../Logic/UIEventSource"
import NearbyFeatureSource from "../../Logic/FeatureSource/Sources/NearbyFeatureSource"
import {
SummaryTileSource,
SummaryTileSourceRewriter,
SummaryTileSourceRewriter
} from "../../Logic/FeatureSource/TiledFeatureSource/SummaryTileSource"
import { ShowDataLayerOptions } from "../../UI/Map/ShowDataLayerOptions"
@ -195,7 +195,6 @@ export class WithSpecialLayers extends WithChangesState {
| "range" // handled by UserMapFeatureSwitchState
| "selected_element" // handled by this.drawSelectedElement
>
const empty = []
/**
* A listing which maps the layerId onto the featureSource
*/

View file

@ -26,7 +26,7 @@
import SelectedElementView from "./SelectedElementView.svelte"
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
import type { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
import usersettings from "../../assets/generated/layers/usersettings.json"
import usersettings from "../../../public/assets/generated/layers/usersettings.json"
import UserRelatedState from "../../Logic/State/UserRelatedState"
import ArrowDownTray from "@babeard/svelte-heroicons/mini/ArrowDownTray"
import DownloadPanel from "../DownloadFlow/DownloadPanel.svelte"

View file

@ -19,7 +19,7 @@
import { MapLibreAdaptor } from "../Map/MapLibreAdaptor"
import ShowDataLayer from "../Map/ShowDataLayer"
import StaticFeatureSource from "../../Logic/FeatureSource/Sources/StaticFeatureSource"
import * as geocoded_image from "../../assets/generated/layers/geocoded_image.json"
import * as geocoded_image from "../../../public/assets/generated/layers/geocoded_image.json"
import type { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson"
import { onDestroy } from "svelte"
import { BBox } from "../../Logic/BBox"