2022-04-13 00:31:13 +02:00
import {
Concat ,
Conversion ,
DesugaringContext ,
DesugaringStep ,
Each ,
Fuse ,
On ,
Pass ,
SetDefault ,
} from "./Conversion"
2022-01-21 01:57:16 +01:00
import { LayoutConfigJson } from "../Json/LayoutConfigJson"
2023-04-14 02:42:57 +02:00
import { PrepareLayer } from "./PrepareLayer"
2022-01-21 01:57:16 +01:00
import { LayerConfigJson } from "../Json/LayerConfigJson"
import { Utils } from "../../../Utils"
import Constants from "../../Constants"
import CreateNoteImportLayer from "./CreateNoteImportLayer"
import LayerConfig from "../LayerConfig"
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
import DependencyCalculator from "../DependencyCalculator"
2022-04-08 21:53:08 +02:00
import { AddContextToTranslations } from "./AddContextToTranslations"
2023-03-29 17:56:42 +02:00
import ValidationUtils from "./ValidationUtils"
2022-09-08 21:40:48 +02:00
2022-01-21 01:57:16 +01:00
class SubstituteLayer extends Conversion < string | LayerConfigJson , LayerConfigJson [ ] > {
2022-02-04 01:05:35 +01:00
private readonly _state : DesugaringContext
2022-04-13 00:31:13 +02:00
2022-02-04 01:05:35 +01:00
constructor ( state : DesugaringContext ) {
2022-04-13 00:31:13 +02:00
super (
"Converts the identifier of a builtin layer into the actual layer, or converts a 'builtin' syntax with override in the fully expanded form" ,
[ ] ,
"SubstituteLayer"
2022-09-08 21:40:48 +02:00
)
2022-02-04 01:05:35 +01:00
this . _state = state
2022-01-21 01:57:16 +01:00
}
2022-04-13 00:31:13 +02:00
2022-02-10 23:16:14 +01:00
convert (
json : string | LayerConfigJson ,
context : string
) : { result : LayerConfigJson [ ] ; errors : string [ ] ; information? : string [ ] } {
2022-01-21 01:57:16 +01:00
const errors = [ ]
2022-02-10 23:16:14 +01:00
const information = [ ]
2022-04-13 00:31:13 +02:00
const state = this . _state
function reportNotFound ( name : string ) {
2022-02-04 00:44:09 +01:00
const knownLayers = Array . from ( state . sharedLayers . keys ( ) )
2022-04-13 00:31:13 +02:00
const withDistance = knownLayers . map ( ( lname ) = > [
lname ,
Utils . levenshteinDistance ( name , lname ) ,
] )
2022-02-04 00:44:09 +01:00
withDistance . sort ( ( a , b ) = > a [ 1 ] - b [ 1 ] )
const ids = withDistance . map ( ( n ) = > n [ 0 ] )
2022-04-13 00:31:13 +02:00
// Known builtin layers are "+.join(",")+"\n For more information, see "
2022-02-04 00:44:09 +01:00
errors . push ( ` ${ context } : The layer with name ${ name } was not found as a builtin layer. Perhaps you meant ${ ids [ 0 ] } , ${ ids [ 1 ] } or ${ ids [ 2 ] } ?
For an overview of all available layers , refer to https : //github.com/pietervdvn/MapComplete/blob/develop/Docs/BuiltinLayers.md`)
}
2022-04-13 00:31:13 +02:00
2022-01-21 01:57:16 +01:00
if ( typeof json === "string" ) {
const found = state . sharedLayers . get ( json )
if ( found === undefined ) {
2022-02-04 00:44:09 +01:00
reportNotFound ( json )
2022-01-21 01:57:16 +01:00
return {
result : null ,
2022-02-04 00:44:09 +01:00
errors ,
2022-01-21 01:57:16 +01:00
}
}
return {
result : [ found ] ,
2022-02-04 01:05:35 +01:00
errors ,
2022-01-21 01:57:16 +01:00
}
}
if ( json [ "builtin" ] !== undefined ) {
let names = json [ "builtin" ]
if ( typeof names === "string" ) {
names = [ names ]
}
const layers = [ ]
2022-02-08 02:23:38 +01:00
2022-01-21 01:57:16 +01:00
for ( const name of names ) {
const found = Utils . Clone ( state . sharedLayers . get ( name ) )
if ( found === undefined ) {
2022-02-04 00:44:09 +01:00
reportNotFound ( name )
2022-01-21 01:57:16 +01:00
continue
}
if (
json [ "override" ] [ "tagRenderings" ] !== undefined &&
( found [ "tagRenderings" ] ? ? [ ] ) . length > 0
) {
errors . push (
` At ${ context } : 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 {
Utils . Merge ( json [ "override" ] , found )
layers . push ( found )
} catch ( e ) {
errors . push (
` At ${ context } : could not apply an override due to: ${ e } . \ nThe override is: ${ JSON . stringify (
json [ "override" ]
) } `
)
}
2022-04-13 00:31:13 +02:00
if ( json [ "hideTagRenderingsWithLabels" ] ) {
2022-02-08 02:23:38 +01:00
const hideLabels : Set < string > = new Set ( json [ "hideTagRenderingsWithLabels" ] )
// These labels caused at least one deletion
2022-04-13 00:31:13 +02:00
const usedLabels : Set < string > = new Set < string > ( )
2022-02-08 02:23:38 +01:00
const filtered = [ ]
for ( const tr of found . tagRenderings ) {
const labels = tr [ "labels" ]
2022-04-13 00:31:13 +02:00
if ( labels !== undefined ) {
2022-02-08 02:23:38 +01:00
const forbiddenLabel = labels . findIndex ( ( l ) = > hideLabels . has ( l ) )
2022-04-13 00:31:13 +02:00
if ( forbiddenLabel >= 0 ) {
2022-02-08 02:23:38 +01:00
usedLabels . add ( labels [ forbiddenLabel ] )
2022-04-13 00:31:13 +02:00
information . push (
context +
": Dropping tagRendering " +
tr [ "id" ] +
" as it has a forbidden label: " +
labels [ forbiddenLabel ]
)
2022-02-08 02:23:38 +01:00
continue
}
}
2022-04-13 00:31:13 +02:00
if ( hideLabels . has ( tr [ "id" ] ) ) {
2022-02-08 02:23:38 +01:00
usedLabels . add ( tr [ "id" ] )
2022-04-13 00:31:13 +02:00
information . push (
context +
": Dropping tagRendering " +
tr [ "id" ] +
" as its id is a forbidden label"
)
2022-02-08 02:23:38 +01:00
continue
}
2022-04-13 00:31:13 +02:00
if ( hideLabels . has ( tr [ "group" ] ) ) {
2022-02-08 02:23:38 +01:00
usedLabels . add ( tr [ "group" ] )
2022-04-13 00:31:13 +02:00
information . push (
context +
": Dropping tagRendering " +
tr [ "id" ] +
" as its group `" +
tr [ "group" ] +
"` is a forbidden label"
)
2022-02-08 02:23:38 +01:00
continue
}
filtered . push ( tr )
}
const unused = Array . from ( hideLabels ) . filter ( ( l ) = > ! usedLabels . has ( l ) )
2022-04-13 00:31:13 +02:00
if ( unused . length > 0 ) {
errors . push (
"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 ( ", " ) +
"\n This means that this label can be removed or that the original tagRendering that should be deleted does not have this label anymore"
)
2022-02-08 02:23:38 +01:00
}
found . tagRenderings = filtered
}
2022-01-21 01:57:16 +01:00
}
return {
result : layers ,
2022-02-08 02:23:38 +01:00
errors ,
2022-02-10 23:16:14 +01:00
information ,
2022-01-21 01:57:16 +01:00
}
}
return {
result : [ json ] ,
2022-02-04 01:05:35 +01:00
errors ,
2022-01-21 01:57:16 +01:00
}
}
}
class AddDefaultLayers extends DesugaringStep < LayoutConfigJson > {
2023-03-24 19:21:15 +01:00
private readonly _state : DesugaringContext
2022-01-21 01:57:16 +01:00
2022-02-04 01:05:35 +01:00
constructor ( state : DesugaringContext ) {
2022-04-13 00:31:13 +02:00
super (
"Adds the default layers, namely: " + Constants . added_by_default . join ( ", " ) ,
[ "layers" ] ,
"AddDefaultLayers"
2022-09-08 21:40:48 +02:00
)
2022-02-04 01:05:35 +01:00
this . _state = state
2022-01-21 01:57:16 +01:00
}
2022-02-04 01:05:35 +01:00
convert (
json : LayoutConfigJson ,
context : string
) : { result : LayoutConfigJson ; errors : string [ ] ; warnings : string [ ] } {
2022-01-21 01:57:16 +01:00
const errors = [ ]
const warnings = [ ]
2022-02-04 01:05:35 +01:00
const state = this . _state
2022-01-21 01:57:16 +01:00
json . layers = [ . . . json . layers ]
2022-01-31 14:34:06 +01:00
const alreadyLoaded = new Set ( json . layers . map ( ( l ) = > l [ "id" ] ) )
2022-01-21 01:57:16 +01:00
for ( const layerName of Constants . added_by_default ) {
const v = state . sharedLayers . get ( layerName )
if ( v === undefined ) {
errors . push ( "Default layer " + layerName + " not found" )
2022-03-18 13:04:12 +01:00
continue
2022-01-21 01:57:16 +01:00
}
2022-04-13 00:31:13 +02:00
if ( alreadyLoaded . has ( v . id ) ) {
warnings . push (
"Layout " +
context +
" already has a layer with name " +
v . id +
"; skipping inclusion of this builtin layer"
)
2022-01-31 14:34:06 +01:00
continue
}
2022-01-21 01:57:16 +01:00
json . layers . push ( v )
}
return {
result : json ,
errors ,
warnings ,
}
}
}
class AddImportLayers extends DesugaringStep < LayoutConfigJson > {
constructor ( ) {
2022-04-13 00:31:13 +02:00
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)" ,
[ "layers" ] ,
"AddImportLayers"
2022-09-08 21:40:48 +02:00
)
2022-01-21 01:57:16 +01:00
}
2022-05-06 12:41:24 +02:00
convert (
json : LayoutConfigJson ,
context : string
) : { result : LayoutConfigJson ; errors? : string [ ] ; warnings? : string [ ] } {
if ( ! ( json . enableNoteImports ? ? true ) ) {
return {
warnings : [
"Not creating a note import layers for theme " +
json . id +
" as they are disabled" ,
] ,
result : json ,
}
}
2022-01-21 01:57:16 +01:00
const errors = [ ]
2022-01-26 21:40:38 +01:00
2022-01-21 01:57:16 +01:00
json = { . . . json }
const allLayers : LayerConfigJson [ ] = < LayerConfigJson [ ] > json . layers
json . layers = [ . . . json . layers ]
2022-05-06 12:41:24 +02:00
const creator = new CreateNoteImportLayer ( )
for ( let i1 = 0 ; i1 < allLayers . length ; i1 ++ ) {
const layer = allLayers [ i1 ]
2023-03-25 02:48:24 +01:00
if ( layer . source === undefined ) {
2022-05-06 12:41:24 +02:00
// Priviliged layers are skipped
continue
}
2022-01-21 01:57:16 +01:00
2022-05-06 12:41:24 +02:00
if ( layer . source [ "geoJson" ] !== undefined ) {
// Layer which don't get their data from OSM are skipped
continue
}
2022-01-21 01:57:16 +01:00
2022-05-06 12:41:24 +02:00
if ( layer . title === undefined || layer . name === undefined ) {
// Anonymous layers and layers without popup are skipped
continue
}
2022-01-21 01:57:16 +01:00
2022-05-06 12:41:24 +02:00
if ( layer . presets === undefined || layer . presets . length == 0 ) {
// A preset is needed to be able to generate a new point
continue
}
2022-01-21 01:57:16 +01:00
2022-05-06 12:41:24 +02:00
try {
const importLayerResult = creator . convert (
layer ,
context + ".(noteimportlayer)[" + i1 + "]"
)
if ( importLayerResult . result !== undefined ) {
json . layers . push ( importLayerResult . result )
2022-01-21 01:57:16 +01:00
}
2022-05-06 12:41:24 +02:00
} catch ( e ) {
errors . push ( "Could not generate an import-layer for " + layer . id + " due to " + e )
2022-01-21 01:57:16 +01:00
}
}
return {
errors ,
result : json ,
}
}
}
2023-03-29 18:54:00 +02:00
class AddContextToTranslationsInLayout extends DesugaringStep < LayoutConfigJson > {
2022-04-06 17:28:51 +02:00
constructor ( ) {
2022-04-13 00:31:13 +02:00
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" ,
[ "_context" ] ,
"AddContextToTranlationsInLayout"
2022-09-08 21:40:48 +02:00
)
2022-04-06 17:28:51 +02:00
}
2022-04-13 00:31:13 +02:00
2022-04-06 17:28:51 +02:00
convert (
json : LayoutConfigJson ,
context : string
) : {
result : LayoutConfigJson
errors? : string [ ]
warnings? : string [ ]
information? : string [ ]
} {
const conversion = new AddContextToTranslations < LayoutConfigJson > ( "themes:" )
return conversion . convert ( json , json . id )
}
}
2022-01-24 00:59:23 +01:00
class ApplyOverrideAll extends DesugaringStep < LayoutConfigJson > {
constructor ( ) {
2022-04-13 00:31:13 +02:00
super (
"Applies 'overrideAll' onto every 'layer'. The 'overrideAll'-field is removed afterwards" ,
[ "overrideAll" , "layers" ] ,
"ApplyOverrideAll"
2022-09-08 21:40:48 +02:00
)
2022-01-24 00:59:23 +01:00
}
2022-02-04 01:05:35 +01:00
convert (
json : LayoutConfigJson ,
context : string
) : { result : LayoutConfigJson ; errors : string [ ] ; warnings : string [ ] } {
2022-01-24 00:59:23 +01:00
const overrideAll = json . overrideAll
if ( overrideAll === undefined ) {
return { result : json , warnings : [ ] , errors : [ ] }
}
json = { . . . json }
delete json . overrideAll
const newLayers = [ ]
for ( let layer of json . layers ) {
2022-02-24 03:48:28 +01:00
layer = Utils . Clone ( < LayerConfigJson > layer )
2022-01-24 00:59:23 +01:00
Utils . Merge ( overrideAll , layer )
newLayers . push ( layer )
}
json . layers = newLayers
return { result : json , warnings : [ ] , errors : [ ] }
}
}
2022-01-21 01:57:16 +01:00
class AddDependencyLayersToTheme extends DesugaringStep < LayoutConfigJson > {
2022-02-04 01:05:35 +01:00
private readonly _state : DesugaringContext
2022-04-13 00:31:13 +02:00
constructor ( state : DesugaringContext ) {
2022-04-23 15:20:54 +02:00
super (
` If a layer has a dependency on another layer, these layers are added automatically on the theme. (For example: defibrillator depends on 'walls_and_buildings' to snap onto. This layer is added automatically)
2023-03-24 19:21:15 +01:00
2022-04-23 15:20:54 +02:00
Note that these layers are added _at the start_ of the layer list , meaning that they will see _every_ feature .
Furthermore , \ ` passAllFeatures \` will be set, so that they won't steal away features from further layers.
Some layers ( e . g . \ ` all_buildings_and_walls \ ' or \ 'streets_with_a_name \ ') are invisible, so by default, \ 'force_load \ ' is set too.
` ,
[ "layers" ] ,
"AddDependencyLayersToTheme"
2022-09-08 21:40:48 +02:00
)
2022-02-04 01:05:35 +01:00
this . _state = state
2022-01-21 01:57:16 +01:00
}
2022-04-23 15:20:54 +02:00
private static CalculateDependencies (
alreadyLoaded : LayerConfigJson [ ] ,
allKnownLayers : Map < string , LayerConfigJson > ,
themeId : string
) : { config : LayerConfigJson ; reason : string } [ ] {
const dependenciesToAdd : { config : LayerConfigJson ; reason : string } [ ] = [ ]
2022-01-21 01:57:16 +01:00
const loadedLayerIds : Set < string > = new Set < string > ( alreadyLoaded . map ( ( l ) = > l . id ) )
// Verify cross-dependencies
let unmetDependencies : {
neededLayer : string
neededBy : string
reason : string
context? : string
} [ ] = [ ]
do {
const dependencies : {
neededLayer : string
reason : string
context? : string
neededBy : string
} [ ] = [ ]
for ( const layerConfig of alreadyLoaded ) {
2022-04-13 00:31:13 +02:00
try {
2022-07-18 02:00:32 +02:00
const layerDeps = DependencyCalculator . getLayerDependencies (
new LayerConfig ( layerConfig , themeId + "(dependencies)" )
2022-09-08 21:40:48 +02:00
)
2022-04-06 17:28:51 +02:00
dependencies . push ( . . . layerDeps )
2022-04-13 00:31:13 +02:00
} catch ( e ) {
2022-04-06 17:28:51 +02:00
console . error ( e )
2022-04-13 00:31:13 +02:00
throw (
"Detecting layer dependencies for " + layerConfig . id + " failed due to " + e
2022-09-08 21:40:48 +02:00
)
2022-04-06 17:28:51 +02:00
}
2022-01-21 01:57:16 +01:00
}
2022-02-07 01:59:07 +01:00
for ( const dependency of dependencies ) {
2022-04-13 00:31:13 +02:00
if ( loadedLayerIds . has ( dependency . neededLayer ) ) {
2022-02-07 01:59:07 +01:00
// We mark the needed layer as 'mustLoad'
alreadyLoaded . find ( ( l ) = > l . id === dependency . neededLayer ) . forceLoad = true
}
}
2022-01-21 01:57:16 +01:00
// During the generate script, builtin layers are verified but not loaded - so we have to add them manually here
2022-04-23 15:20:54 +02:00
// Their existence is checked elsewhere, so this is fine
2022-01-21 01:57:16 +01:00
unmetDependencies = dependencies . filter ( ( dep ) = > ! loadedLayerIds . has ( dep . neededLayer ) )
for ( const unmetDependency of unmetDependencies ) {
if ( loadedLayerIds . has ( unmetDependency . neededLayer ) ) {
continue
}
2022-04-23 15:20:54 +02:00
const dep = Utils . Clone ( allKnownLayers . get ( unmetDependency . neededLayer ) )
const reason =
"This layer is needed by " +
unmetDependency . neededBy +
" because " +
unmetDependency . reason +
" (at " +
unmetDependency . context +
")"
2022-01-21 01:57:16 +01:00
if ( dep === undefined ) {
const message = [
"Loading a dependency failed: layer " +
unmetDependency . neededLayer +
" is not found, neither as layer of " +
themeId +
" nor as builtin layer." ,
2022-04-23 15:20:54 +02:00
reason ,
2022-01-21 01:57:16 +01:00
"Loaded layers are: " + alreadyLoaded . map ( ( l ) = > l . id ) . join ( "," ) ,
]
throw message . join ( "\n\t" )
}
2022-09-08 21:40:48 +02:00
2022-04-23 15:20:54 +02:00
dep . forceLoad = true
dep . passAllFeatures = true
dep . description = reason
dependenciesToAdd . unshift ( {
config : dep ,
reason ,
} )
2022-01-21 01:57:16 +01:00
loadedLayerIds . add ( dep . id )
unmetDependencies = unmetDependencies . filter (
( d ) = > d . neededLayer !== unmetDependency . neededLayer
2022-09-08 21:40:48 +02:00
)
2022-01-21 01:57:16 +01:00
}
} while ( unmetDependencies . length > 0 )
2022-04-13 00:31:13 +02:00
2022-04-23 15:20:54 +02:00
return dependenciesToAdd
2022-01-21 01:57:16 +01:00
}
2022-02-10 23:16:14 +01:00
convert (
theme : LayoutConfigJson ,
context : string
) : { result : LayoutConfigJson ; information : string [ ] } {
2022-02-04 01:05:35 +01:00
const state = this . _state
2022-01-21 01:57:16 +01:00
const allKnownLayers : Map < string , LayerConfigJson > = state . sharedLayers
const knownTagRenderings : Map < string , TagRenderingConfigJson > = state . tagRenderings
2022-02-10 23:16:14 +01:00
const information = [ ]
2022-01-21 01:57:16 +01:00
const layers : LayerConfigJson [ ] = < LayerConfigJson [ ] > theme . layers // Layers should be expanded at this point
knownTagRenderings . forEach ( ( value , key ) = > {
value . id = key
} )
const dependencies = AddDependencyLayersToTheme . CalculateDependencies (
layers ,
allKnownLayers ,
theme . id
2022-09-08 21:40:48 +02:00
)
2022-04-23 15:20:54 +02:00
for ( const dependency of dependencies ) {
}
2022-01-21 01:57:16 +01:00
if ( dependencies . length > 0 ) {
2022-04-23 15:20:54 +02:00
for ( const dependency of dependencies ) {
information . push (
context +
": added " +
dependency . config . id +
" to the theme. " +
dependency . reason
)
}
2022-01-21 01:57:16 +01:00
}
2022-04-23 15:20:54 +02:00
layers . unshift ( . . . dependencies . map ( ( l ) = > l . config ) )
2022-01-21 01:57:16 +01:00
return {
result : {
. . . theme ,
layers : layers ,
} ,
2022-02-10 23:16:14 +01:00
information ,
2022-01-21 01:57:16 +01:00
}
}
}
2022-02-14 15:41:14 +01:00
class PreparePersonalTheme extends DesugaringStep < LayoutConfigJson > {
private readonly _state : DesugaringContext
2022-04-13 00:31:13 +02:00
2022-02-14 15:41:14 +01:00
constructor ( state : DesugaringContext ) {
2022-04-13 00:31:13 +02:00
super ( "Adds every public layer to the personal theme" , [ "layers" ] , "PreparePersonalTheme" )
2022-02-14 15:41:14 +01:00
this . _state = state
}
convert (
json : LayoutConfigJson ,
context : string
) : {
result : LayoutConfigJson
errors? : string [ ]
warnings? : string [ ]
information? : string [ ]
} {
2022-04-13 00:31:13 +02:00
if ( json . id !== "personal" ) {
2022-02-14 15:41:14 +01:00
return { result : json }
}
2022-09-08 21:40:48 +02:00
2022-06-13 03:13:42 +02:00
// The only thing this _really_ does, is adding the layer-ids into 'layers'
// All other preparations are done by the 'override-all'-block in personal.json
json . layers = Array . from ( this . _state . sharedLayers . keys ( ) )
2023-03-25 02:48:24 +01:00
. filter ( ( l ) = > this . _state . sharedLayers . get ( l ) . source !== null )
2022-06-13 03:13:42 +02:00
. filter ( ( l ) = > this . _state . publicLayers . has ( l ) )
return {
result : json ,
information : [ "The personal theme has " + json . layers . length + " public layers" ] ,
2022-09-08 21:40:48 +02:00
}
2022-02-14 15:41:14 +01:00
}
}
2022-01-21 01:57:16 +01:00
2022-04-13 00:31:13 +02:00
class WarnForUnsubstitutedLayersInTheme extends DesugaringStep < LayoutConfigJson > {
2022-03-24 19:59:46 +01:00
constructor ( ) {
2022-04-13 00:31:13 +02:00
super (
"Generates a warning if a theme uses an unsubstituted layer" ,
[ "layers" ] ,
"WarnForUnsubstitutedLayersInTheme"
2022-09-08 21:40:48 +02:00
)
2022-03-24 19:59:46 +01:00
}
2022-04-13 00:31:13 +02:00
2022-03-24 19:59:46 +01:00
convert (
json : LayoutConfigJson ,
context : string
) : {
result : LayoutConfigJson
errors? : string [ ]
warnings? : string [ ]
information? : string [ ]
} {
2022-04-13 00:31:13 +02:00
if ( json . hideFromOverview === true ) {
2022-03-24 19:59:46 +01:00
return { result : json }
}
const warnings = [ ]
for ( const layer of json . layers ) {
2022-04-13 00:31:13 +02:00
if ( typeof layer === "string" ) {
2022-03-24 19:59:46 +01:00
continue
}
2022-04-13 00:31:13 +02:00
if ( layer [ "builtin" ] !== undefined ) {
2022-03-24 19:59:46 +01:00
continue
}
2022-04-13 00:31:13 +02:00
if ( layer [ "source" ] [ "geojson" ] !== undefined ) {
2022-03-24 19:59:46 +01:00
// We turn a blind eye for import layers
continue
}
2022-04-13 00:31:13 +02:00
const wrn =
"The theme " +
json . id +
" has an inline layer: " +
layer [ "id" ] +
". This is discouraged."
2022-03-24 19:59:46 +01:00
warnings . push ( wrn )
}
return {
result : json ,
warnings ,
}
}
}
2022-01-21 01:57:16 +01:00
export class PrepareTheme extends Fuse < LayoutConfigJson > {
2023-06-20 03:49:12 +02:00
private state : DesugaringContext
2022-04-13 00:31:13 +02:00
constructor (
state : DesugaringContext ,
options ? : {
skipDefaultLayers : false | boolean
}
) {
2022-01-21 01:57:16 +01:00
super (
"Fully prepares and expands a theme" ,
2022-04-22 03:17:40 +02:00
2023-03-29 18:54:00 +02:00
new AddContextToTranslationsInLayout ( ) ,
2022-02-14 15:41:14 +01:00
new PreparePersonalTheme ( state ) ,
2022-03-31 02:54:17 +02:00
new WarnForUnsubstitutedLayersInTheme ( ) ,
2022-04-06 03:06:50 +02:00
new On ( "layers" , new Concat ( new SubstituteLayer ( state ) ) ) ,
2022-01-21 01:57:16 +01:00
new SetDefault ( "socialImage" , "assets/SocialImage.png" , true ) ,
2022-02-18 23:10:27 +01:00
// We expand all tagrenderings first...
2022-04-06 03:06:50 +02:00
new On ( "layers" , new Each ( new PrepareLayer ( state ) ) ) ,
2022-02-18 23:10:27 +01:00
// Then we apply the override all
2022-01-24 00:59:23 +01:00
new ApplyOverrideAll ( ) ,
2022-02-18 23:10:27 +01:00
// And then we prepare all the layers _again_ in case that an override all contained unexpanded tagrenderings!
2022-04-06 03:06:50 +02:00
new On ( "layers" , new Each ( new PrepareLayer ( state ) ) ) ,
2022-04-13 00:31:13 +02:00
options ? . skipDefaultLayers
? new Pass ( "AddDefaultLayers is disabled due to the set flag" )
: new AddDefaultLayers ( state ) ,
2022-02-04 01:05:35 +01:00
new AddDependencyLayersToTheme ( state ) ,
2023-04-14 02:42:57 +02:00
new AddImportLayers ( )
2022-01-21 01:57:16 +01:00
)
2023-06-20 03:49:12 +02:00
this . state = state
2022-01-21 01:57:16 +01:00
}
2023-03-29 18:54:00 +02:00
convert (
json : LayoutConfigJson ,
context : string
) : { result : LayoutConfigJson ; errors : string [ ] ; warnings : string [ ] ; information : string [ ] } {
const result = super . convert ( json , context )
2023-06-20 03:49:12 +02:00
if ( this . state . publicLayers . size === 0 ) {
// THis is a bootstrapping run, no need to already set this flag
return result
}
2023-03-29 18:54:00 +02:00
const needsNodeDatabase = result . result . layers ? . some ( ( l : LayerConfigJson ) = >
l . tagRenderings ? . some ( ( tr : TagRenderingConfigJson ) = >
ValidationUtils . getSpecialVisualisations ( tr ) ? . some (
( special ) = > special . needsNodeDatabase
)
)
)
if ( needsNodeDatabase ) {
result . information . push (
context +
": setting 'enableNodeDatabase' as this theme uses a special visualisation which needs to keep track of _all_ nodes"
)
result . result . enableNodeDatabase = true
}
return result
}
2022-01-21 01:57:16 +01:00
}