forked from MapComplete/MapComplete
Themes: move tagRenderings+ above leftover-questions
This commit is contained in:
parent
f2d470ff2e
commit
f2f041f9d0
1 changed files with 83 additions and 61 deletions
|
@ -1,14 +1,4 @@
|
||||||
import {
|
import { Concat, Conversion, DesugaringContext, DesugaringStep, Each, Fuse, On, Pass, SetDefault } from "./Conversion"
|
||||||
Concat,
|
|
||||||
Conversion,
|
|
||||||
DesugaringContext,
|
|
||||||
DesugaringStep,
|
|
||||||
Each,
|
|
||||||
Fuse,
|
|
||||||
On,
|
|
||||||
Pass,
|
|
||||||
SetDefault,
|
|
||||||
} from "./Conversion"
|
|
||||||
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
|
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
|
||||||
import { PrepareLayer } from "./PrepareLayer"
|
import { PrepareLayer } from "./PrepareLayer"
|
||||||
import { LayerConfigJson } from "../Json/LayerConfigJson"
|
import { LayerConfigJson } from "../Json/LayerConfigJson"
|
||||||
|
@ -27,9 +17,9 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
|
|
||||||
constructor(state: DesugaringContext) {
|
constructor(state: DesugaringContext) {
|
||||||
super(
|
super(
|
||||||
"Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form",
|
"Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form. Note that 'tagRenderings+' will be inserted before 'leftover-questions'",
|
||||||
[],
|
[],
|
||||||
"SubstituteLayer"
|
"SubstituteLayer",
|
||||||
)
|
)
|
||||||
this._state = state
|
this._state = state
|
||||||
}
|
}
|
||||||
|
@ -80,23 +70,34 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
(found["tagRenderings"] ?? []).length > 0
|
(found["tagRenderings"] ?? []).length > 0
|
||||||
) {
|
) {
|
||||||
context.err(
|
context.err(
|
||||||
`When overriding a layer, an override is not allowed to override into tagRenderings. Use "+tagRenderings" or "tagRenderings+" instead to prepend or append some questions.`
|
`When overriding a layer, an override is not allowed to override into tagRenderings. Use "+tagRenderings" or "tagRenderings+" instead to prepend or append some questions.`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
const trPlus = json["override"]["tagRenderings+"]
|
||||||
|
if(trPlus){
|
||||||
|
let index = found.tagRenderings.findIndex(tr => tr["id"] === "leftover-questions")
|
||||||
|
if(index < 0){
|
||||||
|
index = found.tagRenderings.length
|
||||||
|
}
|
||||||
|
found.tagRenderings.splice(index, 0, ...trPlus)
|
||||||
|
delete json["override"]["tagRenderings+"]
|
||||||
|
}
|
||||||
|
|
||||||
Utils.Merge(json["override"], found)
|
Utils.Merge(json["override"], found)
|
||||||
layers.push(found)
|
layers.push(found)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.err(
|
context.err(
|
||||||
`Could not apply an override due to: ${e}.\nThe override is: ${JSON.stringify(
|
`Could not apply an override due to: ${e}.\nThe override is: ${JSON.stringify(
|
||||||
json["override"]
|
json["override"],
|
||||||
)}`
|
)}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json["hideTagRenderingsWithLabels"]) {
|
if (json["hideTagRenderingsWithLabels"]) {
|
||||||
if(typeof json["hideTagRenderingsWithLabels"] === "string"){
|
if (typeof json["hideTagRenderingsWithLabels"] === "string") {
|
||||||
throw "At "+context+".hideTagRenderingsWithLabels should be a list containing strings, you specified a string"
|
throw "At " + context + ".hideTagRenderingsWithLabels should be a list containing strings, you specified a string"
|
||||||
}
|
}
|
||||||
const hideLabels: Set<string> = new Set(json["hideTagRenderingsWithLabels"])
|
const hideLabels: Set<string> = new Set(json["hideTagRenderingsWithLabels"])
|
||||||
// These labels caused at least one deletion
|
// These labels caused at least one deletion
|
||||||
|
@ -110,9 +111,9 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
usedLabels.add(labels[forbiddenLabel])
|
usedLabels.add(labels[forbiddenLabel])
|
||||||
context.info(
|
context.info(
|
||||||
"Dropping tagRendering " +
|
"Dropping tagRendering " +
|
||||||
tr["id"] +
|
tr["id"] +
|
||||||
" as it has a forbidden label: " +
|
" as it has a forbidden label: " +
|
||||||
labels[forbiddenLabel]
|
labels[forbiddenLabel],
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -121,7 +122,7 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
if (hideLabels.has(tr["id"])) {
|
if (hideLabels.has(tr["id"])) {
|
||||||
usedLabels.add(tr["id"])
|
usedLabels.add(tr["id"])
|
||||||
context.info(
|
context.info(
|
||||||
"Dropping tagRendering " + tr["id"] + " as its id is a forbidden label"
|
"Dropping tagRendering " + tr["id"] + " as its id is a forbidden label",
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -130,10 +131,10 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
usedLabels.add(tr["group"])
|
usedLabels.add(tr["group"])
|
||||||
context.info(
|
context.info(
|
||||||
"Dropping tagRendering " +
|
"Dropping tagRendering " +
|
||||||
tr["id"] +
|
tr["id"] +
|
||||||
" as its group `" +
|
" as its group `" +
|
||||||
tr["group"] +
|
tr["group"] +
|
||||||
"` is a forbidden label"
|
"` is a forbidden label",
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -144,8 +145,8 @@ class SubstituteLayer extends Conversion<string | LayerConfigJson, LayerConfigJs
|
||||||
if (unused.length > 0) {
|
if (unused.length > 0) {
|
||||||
context.err(
|
context.err(
|
||||||
"This theme specifies that certain tagrenderings have to be removed based on forbidden layers. One or more of these layers did not match any tagRenderings and caused no deletions: " +
|
"This theme specifies that certain tagrenderings have to be removed based on forbidden layers. One or more of these layers did not match any tagRenderings and caused no deletions: " +
|
||||||
unused.join(", ") +
|
unused.join(", ") +
|
||||||
"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore"
|
"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
found.tagRenderings = filtered
|
found.tagRenderings = filtered
|
||||||
|
@ -162,7 +163,7 @@ class AddDefaultLayers extends DesugaringStep<LayoutConfigJson> {
|
||||||
super(
|
super(
|
||||||
"Adds the default layers, namely: " + Constants.added_by_default.join(", "),
|
"Adds the default layers, namely: " + Constants.added_by_default.join(", "),
|
||||||
["layers"],
|
["layers"],
|
||||||
"AddDefaultLayers"
|
"AddDefaultLayers",
|
||||||
)
|
)
|
||||||
this._state = state
|
this._state = state
|
||||||
}
|
}
|
||||||
|
@ -186,10 +187,10 @@ class AddDefaultLayers extends DesugaringStep<LayoutConfigJson> {
|
||||||
if (alreadyLoaded.has(v.id)) {
|
if (alreadyLoaded.has(v.id)) {
|
||||||
context.warn(
|
context.warn(
|
||||||
"Layout " +
|
"Layout " +
|
||||||
context +
|
context +
|
||||||
" already has a layer with name " +
|
" already has a layer with name " +
|
||||||
v.id +
|
v.id +
|
||||||
"; skipping inclusion of this builtin layer"
|
"; skipping inclusion of this builtin layer",
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -205,14 +206,14 @@ class AddImportLayers extends DesugaringStep<LayoutConfigJson> {
|
||||||
super(
|
super(
|
||||||
"For every layer in the 'layers'-list, create a new layer which'll import notes. (Note that priviliged layers and layers which have a geojson-source set are ignored)",
|
"For every layer in the 'layers'-list, create a new layer which'll import notes. (Note that priviliged layers and layers which have a geojson-source set are ignored)",
|
||||||
["layers"],
|
["layers"],
|
||||||
"AddImportLayers"
|
"AddImportLayers",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
|
convert(json: LayoutConfigJson, context: ConversionContext): LayoutConfigJson {
|
||||||
if (!(json.enableNoteImports ?? true)) {
|
if (!(json.enableNoteImports ?? true)) {
|
||||||
context.info(
|
context.info(
|
||||||
"Not creating a note import layers for theme " + json.id + " as they are disabled"
|
"Not creating a note import layers for theme " + json.id + " as they are disabled",
|
||||||
)
|
)
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
@ -247,7 +248,7 @@ class AddImportLayers extends DesugaringStep<LayoutConfigJson> {
|
||||||
try {
|
try {
|
||||||
const importLayerResult = creator.convert(
|
const importLayerResult = creator.convert(
|
||||||
layer,
|
layer,
|
||||||
context.inOperation(this.name).enter(i1)
|
context.inOperation(this.name).enter(i1),
|
||||||
)
|
)
|
||||||
if (importLayerResult !== undefined) {
|
if (importLayerResult !== undefined) {
|
||||||
json.layers.push(importLayerResult)
|
json.layers.push(importLayerResult)
|
||||||
|
@ -266,7 +267,7 @@ class AddContextToTranslationsInLayout extends DesugaringStep<LayoutConfigJson>
|
||||||
super(
|
super(
|
||||||
"Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too",
|
"Adds context to translations, including the prefix 'themes:json.id'; this is to make sure terms in an 'overrides' or inline layer are linkable too",
|
||||||
["_context"],
|
["_context"],
|
||||||
"AddContextToTranlationsInLayout"
|
"AddContextToTranlationsInLayout",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +282,7 @@ class ApplyOverrideAll extends DesugaringStep<LayoutConfigJson> {
|
||||||
super(
|
super(
|
||||||
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards",
|
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards",
|
||||||
["overrideAll", "layers"],
|
["overrideAll", "layers"],
|
||||||
"ApplyOverrideAll"
|
"ApplyOverrideAll",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,9 +296,29 @@ class ApplyOverrideAll extends DesugaringStep<LayoutConfigJson> {
|
||||||
|
|
||||||
delete json.overrideAll
|
delete json.overrideAll
|
||||||
const newLayers = []
|
const newLayers = []
|
||||||
|
|
||||||
|
let tagRenderingsPlus = undefined
|
||||||
|
if (overrideAll["tagRenderings+"] !== undefined) {
|
||||||
|
tagRenderingsPlus = overrideAll["tagRenderings+"]
|
||||||
|
delete overrideAll["tagRenderings+"]
|
||||||
|
}
|
||||||
|
|
||||||
for (let layer of json.layers) {
|
for (let layer of json.layers) {
|
||||||
layer = Utils.Clone(<LayerConfigJson>layer)
|
layer = Utils.Clone(<LayerConfigJson>layer)
|
||||||
Utils.Merge(overrideAll, layer)
|
Utils.Merge(overrideAll, layer)
|
||||||
|
if (tagRenderingsPlus) {
|
||||||
|
if (!layer.tagRenderings) {
|
||||||
|
layer.tagRenderings = tagRenderingsPlus
|
||||||
|
} else {
|
||||||
|
|
||||||
|
let index = layer.tagRenderings.findIndex(tr => tr["id"] === "leftover-questions")
|
||||||
|
if (index < 0) {
|
||||||
|
index = layer.tagRenderings.length - 1
|
||||||
|
}
|
||||||
|
layer.tagRenderings.splice(index, 0, ...tagRenderingsPlus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newLayers.push(layer)
|
newLayers.push(layer)
|
||||||
}
|
}
|
||||||
json.layers = newLayers
|
json.layers = newLayers
|
||||||
|
@ -317,7 +338,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
Some layers (e.g. \`all_buildings_and_walls\' or \'streets_with_a_name\') are invisible, so by default, \'force_load\' is set too.
|
Some layers (e.g. \`all_buildings_and_walls\' or \'streets_with_a_name\') are invisible, so by default, \'force_load\' is set too.
|
||||||
`,
|
`,
|
||||||
["layers"],
|
["layers"],
|
||||||
"AddDependencyLayersToTheme"
|
"AddDependencyLayersToTheme",
|
||||||
)
|
)
|
||||||
this._state = state
|
this._state = state
|
||||||
}
|
}
|
||||||
|
@ -325,7 +346,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
private static CalculateDependencies(
|
private static CalculateDependencies(
|
||||||
alreadyLoaded: LayerConfigJson[],
|
alreadyLoaded: LayerConfigJson[],
|
||||||
allKnownLayers: Map<string, LayerConfigJson>,
|
allKnownLayers: Map<string, LayerConfigJson>,
|
||||||
themeId: string
|
themeId: string,
|
||||||
): { config: LayerConfigJson; reason: string }[] {
|
): { config: LayerConfigJson; reason: string }[] {
|
||||||
const dependenciesToAdd: { config: LayerConfigJson; reason: string }[] = []
|
const dependenciesToAdd: { config: LayerConfigJson; reason: string }[] = []
|
||||||
const loadedLayerIds: Set<string> = new Set<string>(alreadyLoaded.map((l) => l.id))
|
const loadedLayerIds: Set<string> = new Set<string>(alreadyLoaded.map((l) => l.id))
|
||||||
|
@ -348,7 +369,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
for (const layerConfig of alreadyLoaded) {
|
for (const layerConfig of alreadyLoaded) {
|
||||||
try {
|
try {
|
||||||
const layerDeps = DependencyCalculator.getLayerDependencies(
|
const layerDeps = DependencyCalculator.getLayerDependencies(
|
||||||
new LayerConfig(layerConfig, themeId + "(dependencies)")
|
new LayerConfig(layerConfig, themeId + "(dependencies)"),
|
||||||
)
|
)
|
||||||
dependencies.push(...layerDeps)
|
dependencies.push(...layerDeps)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -385,10 +406,10 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
if (dep === undefined) {
|
if (dep === undefined) {
|
||||||
const message = [
|
const message = [
|
||||||
"Loading a dependency failed: layer " +
|
"Loading a dependency failed: layer " +
|
||||||
unmetDependency.neededLayer +
|
unmetDependency.neededLayer +
|
||||||
" is not found, neither as layer of " +
|
" is not found, neither as layer of " +
|
||||||
themeId +
|
themeId +
|
||||||
" nor as builtin layer.",
|
" nor as builtin layer.",
|
||||||
reason,
|
reason,
|
||||||
"Loaded layers are: " + alreadyLoaded.map((l) => l.id).join(","),
|
"Loaded layers are: " + alreadyLoaded.map((l) => l.id).join(","),
|
||||||
]
|
]
|
||||||
|
@ -404,7 +425,7 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
})
|
})
|
||||||
loadedLayerIds.add(dep.id)
|
loadedLayerIds.add(dep.id)
|
||||||
unmetDependencies = unmetDependencies.filter(
|
unmetDependencies = unmetDependencies.filter(
|
||||||
(d) => d.neededLayer !== unmetDependency.neededLayer
|
(d) => d.neededLayer !== unmetDependency.neededLayer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} while (unmetDependencies.length > 0)
|
} while (unmetDependencies.length > 0)
|
||||||
|
@ -425,14 +446,14 @@ class AddDependencyLayersToTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
const dependencies = AddDependencyLayersToTheme.CalculateDependencies(
|
const dependencies = AddDependencyLayersToTheme.CalculateDependencies(
|
||||||
layers,
|
layers,
|
||||||
allKnownLayers,
|
allKnownLayers,
|
||||||
theme.id
|
theme.id,
|
||||||
)
|
)
|
||||||
for (const dependency of dependencies) {
|
for (const dependency of dependencies) {
|
||||||
}
|
}
|
||||||
if (dependencies.length > 0) {
|
if (dependencies.length > 0) {
|
||||||
for (const dependency of dependencies) {
|
for (const dependency of dependencies) {
|
||||||
context.info(
|
context.info(
|
||||||
"Added " + dependency.config.id + " to the theme. " + dependency.reason
|
"Added " + dependency.config.id + " to the theme. " + dependency.reason,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,7 +495,7 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson>
|
||||||
super(
|
super(
|
||||||
"Generates a warning if a theme uses an unsubstituted layer",
|
"Generates a warning if a theme uses an unsubstituted layer",
|
||||||
["layers"],
|
["layers"],
|
||||||
"WarnForUnsubstitutedLayersInTheme"
|
"WarnForUnsubstitutedLayersInTheme",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,7 +507,7 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson>
|
||||||
context
|
context
|
||||||
.enter("layers")
|
.enter("layers")
|
||||||
.err(
|
.err(
|
||||||
"No layers are defined. You must define at least one layer to have a valid theme"
|
"No layers are defined. You must define at least one layer to have a valid theme",
|
||||||
)
|
)
|
||||||
return json
|
return json
|
||||||
}
|
}
|
||||||
|
@ -510,10 +531,10 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson>
|
||||||
|
|
||||||
context.warn(
|
context.warn(
|
||||||
"The theme " +
|
"The theme " +
|
||||||
json.id +
|
json.id +
|
||||||
" has an inline layer: " +
|
" has an inline layer: " +
|
||||||
layer["id"] +
|
layer["id"] +
|
||||||
". This is discouraged."
|
". This is discouraged.",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return json
|
return json
|
||||||
|
@ -522,11 +543,12 @@ class WarnForUnsubstitutedLayersInTheme extends DesugaringStep<LayoutConfigJson>
|
||||||
|
|
||||||
export class PrepareTheme extends Fuse<LayoutConfigJson> {
|
export class PrepareTheme extends Fuse<LayoutConfigJson> {
|
||||||
private state: DesugaringContext
|
private state: DesugaringContext
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
state: DesugaringContext,
|
state: DesugaringContext,
|
||||||
options?: {
|
options?: {
|
||||||
skipDefaultLayers: false | boolean
|
skipDefaultLayers: false | boolean
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
"Fully prepares and expands a theme",
|
"Fully prepares and expands a theme",
|
||||||
|
@ -538,7 +560,7 @@ export class PrepareTheme extends Fuse<LayoutConfigJson> {
|
||||||
new SetDefault("socialImage", "assets/SocialImage.png", true),
|
new SetDefault("socialImage", "assets/SocialImage.png", true),
|
||||||
// We expand all tagrenderings first...
|
// We expand all tagrenderings first...
|
||||||
new On("layers", new Each(new PrepareLayer(state))),
|
new On("layers", new Each(new PrepareLayer(state))),
|
||||||
// Then we apply the override all
|
// Then we apply the override all. Note that it'll cheat with tagRenderings+
|
||||||
new ApplyOverrideAll(),
|
new ApplyOverrideAll(),
|
||||||
// And then we prepare all the layers _again_ in case that an override all contained unexpanded tagrenderings!
|
// And then we prepare all the layers _again_ in case that an override all contained unexpanded tagrenderings!
|
||||||
new On("layers", new Each(new PrepareLayer(state))),
|
new On("layers", new Each(new PrepareLayer(state))),
|
||||||
|
@ -546,7 +568,7 @@ export class PrepareTheme extends Fuse<LayoutConfigJson> {
|
||||||
? new Pass("AddDefaultLayers is disabled due to the set flag")
|
? new Pass("AddDefaultLayers is disabled due to the set flag")
|
||||||
: new AddDefaultLayers(state),
|
: new AddDefaultLayers(state),
|
||||||
new AddDependencyLayersToTheme(state),
|
new AddDependencyLayersToTheme(state),
|
||||||
new AddImportLayers()
|
new AddImportLayers(),
|
||||||
)
|
)
|
||||||
this.state = state
|
this.state = state
|
||||||
}
|
}
|
||||||
|
@ -561,13 +583,13 @@ export class PrepareTheme extends Fuse<LayoutConfigJson> {
|
||||||
const needsNodeDatabase = result.layers?.some((l: LayerConfigJson) =>
|
const needsNodeDatabase = result.layers?.some((l: LayerConfigJson) =>
|
||||||
l.tagRenderings?.some((tr) =>
|
l.tagRenderings?.some((tr) =>
|
||||||
ValidationUtils.getSpecialVisualisations(<any>tr)?.some(
|
ValidationUtils.getSpecialVisualisations(<any>tr)?.some(
|
||||||
(special) => special.needsNodeDatabase
|
(special) => special.needsNodeDatabase,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
if (needsNodeDatabase) {
|
if (needsNodeDatabase) {
|
||||||
context.info(
|
context.info(
|
||||||
"Setting 'enableNodeDatabase' as this theme uses a special visualisation which needs to keep track of _all_ nodes"
|
"Setting 'enableNodeDatabase' as this theme uses a special visualisation which needs to keep track of _all_ nodes",
|
||||||
)
|
)
|
||||||
result.enableNodeDatabase = true
|
result.enableNodeDatabase = true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue