Search: document 'isNormal' in layerconfig; document autofilter-disable option; disable this in favourites, split out the code

This commit is contained in:
Pieter Vander Vennet 2024-09-15 02:22:31 +02:00
parent 5479b81066
commit 8239820d04
5 changed files with 102 additions and 69 deletions

View file

@ -1,6 +1,7 @@
{ {
"#":"no-translations", "#":"no-translations",
"#dont-translate": "*", "#dont-translate": "*",
"#filter": "no-auto",
"pointRendering": [ "pointRendering": [
{ {
"location": [ "location": [

View file

@ -45,6 +45,7 @@ export class GenerateFavouritesLayer extends Script {
this.addTagRenderings(proto) this.addTagRenderings(proto)
this.addTitle(proto) this.addTitle(proto)
proto.titleIcons = this.generateTitleIcons() proto.titleIcons = this.generateTitleIcons()
delete proto.filter
const targetContent = JSON.stringify(proto, null, " ") const targetContent = JSON.stringify(proto, null, " ")
const path = "./assets/layers/favourite/favourite.json" const path = "./assets/layers/favourite/favourite.json"
if (existsSync(path)) { if (existsSync(path)) {

View file

@ -30,8 +30,72 @@ import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"
import { ConversionContext } from "./ConversionContext" import { ConversionContext } from "./ConversionContext"
import { ExpandRewrite } from "./ExpandRewrite" import { ExpandRewrite } from "./ExpandRewrite"
import { TagUtils } from "../../../Logic/Tags/TagUtils" import { TagUtils } from "../../../Logic/Tags/TagUtils"
import FilterConfig, { FilterConfigOption } from "../FilterConfig"
class AddFiltersFromTagRenderings extends DesugaringStep<LayerConfigJson> {
constructor() {
super("Inspects all the tagRenderings. If some tagRenderings have the `filter` attribute set, introduce those filters. This step might introduce shorthand filter names, thus 'ExpandFilter' should be run afterwards. Can be disabled with \"#filter\":\"no-auto\"", ["filter"], "AddFiltersFromTagRenderings")
}
convert(json: LayerConfigJson, context: ConversionContext): LayerConfigJson {
const noAutoFilters = json["#filter"] === "no-auto"
if(noAutoFilters){
return json
}
if(json.filter?.["sameAs"]){
return json
}
const filters: (FilterConfigJson | string)[] = [...<any>json.filter ?? []]
function filterExists(filterName: string): boolean {
return filters.some((existing) => {
const id: string = existing["id"] ?? existing
return (
filterName === id ||
(filterName.startsWith("filters.") && filterName.endsWith("." + id))
)
})
}
for (let i = 0; i < json.tagRenderings?.length; i++) {
const tagRendering = <TagRenderingConfigJson>json.tagRenderings[i]
if (!tagRendering?.filter) {
continue
}
if (tagRendering.filter === true) {
if (filterExists(tagRendering["id"])) {
continue
}
filters.push(ExpandFilter.buildFilterFromTagRendering(tagRendering, context.enters("tagRenderings", i, "filter")))
continue
}
for (const filterName of tagRendering.filter ?? []) {
if (typeof filterName !== "string") {
context.enters("tagRenderings", i, "filter").err("Not a string: " + filterName)
}
if (filterExists(filterName)) {
// This filter has already been added
continue
}
if (!filterName) {
context.err("Got undefined as filter expansion in " + tagRendering["id"])
continue
}
filters.push(filterName)
}
}
if(filters.length === 0){
return json
}
return { ...json, filter: filters }
}
}
class ExpandFilter extends DesugaringStep<LayerConfigJson> { class ExpandFilter extends DesugaringStep<LayerConfigJson> {
private static readonly predefinedFilters = ExpandFilter.load_filters() private static readonly predefinedFilters = ExpandFilter.load_filters()
private _state: DesugaringContext private _state: DesugaringContext
@ -39,9 +103,7 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
constructor(state: DesugaringContext) { constructor(state: DesugaringContext) {
super( super(
["Expands filters: replaces a shorthand by the value found in 'filters.json'.", ["Expands filters: replaces a shorthand by the value found in 'filters.json'.",
"If the string is formatted 'layername.filtername, it will be looked up into that layer instead.", "If the string is formatted 'layername.filtername, it will be looked up into that layer instead."].join(" "),
"If a tagRendering sets 'filter', this filter will also be included - unless \"#filter\":\"no-auto\" is set",
""].join(" "),
["filter"], ["filter"],
"ExpandFilter", "ExpandFilter",
) )
@ -56,7 +118,7 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
return filters return filters
} }
private static buildFilterFromTagRendering(tr: TagRenderingConfigJson, context: ConversionContext): FilterConfigJson { public static buildFilterFromTagRendering(tr: TagRenderingConfigJson, context: ConversionContext): FilterConfigJson {
if (!(tr.mappings?.length >= 1)) { if (!(tr.mappings?.length >= 1)) {
context.err( context.err(
"Found a matching tagRendering to base a filter on, but this tagRendering does not contain any mappings", "Found a matching tagRendering to base a filter on, but this tagRendering does not contain any mappings",
@ -97,53 +159,10 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
return json // Nothing to change here return json // Nothing to change here
} }
const noAutoFilters = json["#filter"] === "no-auto"
const newFilters: FilterConfigJson[] = [] const newFilters: FilterConfigJson[] = []
const filters = <(FilterConfigJson | string)[]>json.filter const filters = <(FilterConfigJson | string)[]>json.filter
function filterExists(filterName: string): boolean {
return filters.some((existing) => {
const id: string = existing["id"] ?? existing
return (
filterName === id ||
(filterName.startsWith("filters.") && filterName.endsWith("." + id))
)
})
}
if (!noAutoFilters){
/**
* Checks all tagRendering. If a tagrendering has 'filter' set, add this filter to the layer config
*/
for (let i = 0; i < json.tagRenderings?.length; i++) {
const tagRendering = <TagRenderingConfigJson>json.tagRenderings[i]
if (!tagRendering?.filter) {
continue
}
if (tagRendering.filter === true) {
if (filterExists(tagRendering["id"])) {
continue
}
filters.push(ExpandFilter.buildFilterFromTagRendering(tagRendering, context.enters("tagRenderings", i, "filter")))
continue
}
for (const filterName of tagRendering.filter ?? []) {
if (typeof filterName !== "string") {
context.enters("tagRenderings", i, "filter").err("Not a string: " + filterName)
}
if (filterExists(filterName)) {
// This filter has already been added
continue
}
if (!filterName) {
context.err("Got undefined as filter expansion in " + tagRendering["id"])
continue
}
filters.push(filterName)
}
}
}
/** /**
* Create filters based on builtin filters or create them based on the tagRendering * Create filters based on builtin filters or create them based on the tagRendering
@ -168,28 +187,28 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
} }
if (filter.indexOf(".") > 0) { if (filter.indexOf(".") > 0) {
if (this._state.sharedLayers.size > 0) { if (!(this._state.sharedLayers?.size > 0)) {
const split = filter.split(".")
if (split.length > 2) {
context.err(
"invalid filter name: " + filter + ", expected `layername.filterid`",
)
}
const layer = this._state.sharedLayers.get(split[0])
if (layer === undefined) {
context.err("Layer '" + split[0] + "' not found")
}
const expectedId = split[1]
const expandedFilter = (<(FilterConfigJson | string)[]>layer.filter).find(
(f) => typeof f !== "string" && f.id === expectedId,
)
if (expandedFilter === undefined) {
context.err("Did not find filter with name " + filter)
} else {
newFilters.push(<FilterConfigJson>expandedFilter)
}
} else {
// This is a bootstrapping-run, we can safely ignore this // This is a bootstrapping-run, we can safely ignore this
continue
}
const split = filter.split(".")
if (split.length > 2) {
context.err(
"invalid filter name: " + filter + ", expected `layername.filterid`",
)
}
const layer = this._state.sharedLayers.get(split[0])
if (layer === undefined) {
context.err("Layer '" + split[0] + "' not found")
}
const expectedId = split[1]
const expandedFilter = (<(FilterConfigJson | string)[]>layer.filter).find(
(f) => typeof f !== "string" && f.id === expectedId,
)
if (expandedFilter === undefined) {
context.err("Did not find filter with name " + filter)
} else {
newFilters.push(<FilterConfigJson>expandedFilter)
} }
continue continue
} }
@ -1424,6 +1443,7 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
(layer) => (layer) =>
new Concat(new ExpandTagRendering(state, layer, { noHardcodedStrings: true })), new Concat(new ExpandTagRendering(state, layer, { noHardcodedStrings: true })),
), ),
new AddFiltersFromTagRenderings(),
new ExpandFilter(state), new ExpandFilter(state),
) )
} }

View file

@ -447,6 +447,10 @@ export interface LayerConfigJson {
* group: filters * group: filters
*/ */
filter?: (FilterConfigJson | string)[] | { sameAs: string } filter?: (FilterConfigJson | string)[] | { sameAs: string }
/**
* Set this to disable the feature that tagRenderings can introduce filters
*/
"#filter"?: "no-auto"
/** /**
* This block defines under what circumstances the delete dialog is shown for objects of this layer. * This block defines under what circumstances the delete dialog is shown for objects of this layer.

View file

@ -642,6 +642,10 @@ export default class LayerConfig extends WithContextLoader {
return mostShadowed ?? matchingPresets[0] return mostShadowed ?? matchingPresets[0]
} }
/**
* Indicates if this is a normal layer, meaning that it can be toggled by the user in normal circumstances
* Thus: name is set, not a note import layer, not synced with another filter, ...
*/
public isNormal(){ public isNormal(){
if(this.id.startsWith("note_import")){ if(this.id.startsWith("note_import")){
return false return false
@ -653,6 +657,9 @@ export default class LayerConfig extends WithContextLoader {
if(this.filterIsSameAs !== undefined){ if(this.filterIsSameAs !== undefined){
return false return false
} }
if(!this.name ){
return false
}
return true return true
} }
} }