2022-04-13 00:31:13 +02:00
import {
Concat ,
Conversion ,
2023-10-11 04:16:52 +02:00
ConversionContext ,
2022-04-13 00:31:13 +02:00
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
2023-10-11 04:16:52 +02:00
convert ( json : string | LayerConfigJson , context : ConversionContext ) : LayerConfigJson [ ] {
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 "
2023-10-11 04:16:52 +02:00
context . err ( ` The layer with name ${ name } was not found as a builtin layer. Perhaps you meant ${ ids [ 0 ] } , ${ ids [ 1 ] } or ${ ids [ 2 ] } ?
2022-02-04 00:44:09 +01:00
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 )
2023-10-11 04:16:52 +02:00
return null
2022-01-21 01:57:16 +01:00
}
2023-10-11 04:16:52 +02:00
return [ found ]
2022-01-21 01:57:16 +01:00
}
2023-10-11 04:16:52 +02:00
if ( json [ "builtin" ] === undefined ) {
return [ json ]
}
2022-04-13 00:31:13 +02:00
2023-10-11 04:16:52 +02:00
let names = json [ "builtin" ]
if ( typeof names === "string" ) {
names = [ names ]
}
const layers = [ ]
2022-04-13 00:31:13 +02:00
2023-10-11 04:16:52 +02:00
for ( const name of names ) {
const found = Utils . Clone ( state . sharedLayers . get ( name ) )
if ( found === undefined ) {
reportNotFound ( name )
continue
}
if (
json [ "override" ] [ "tagRenderings" ] !== undefined &&
( found [ "tagRenderings" ] ? ? [ ] ) . length > 0
) {
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. `
)
}
try {
Utils . Merge ( json [ "override" ] , found )
layers . push ( found )
} catch ( e ) {
context . err (
` Could not apply an override due to: ${ e } . \ nThe override is: ${ JSON . stringify (
json [ "override" ]
) } `
)
}
2022-02-08 02:23:38 +01:00
2023-10-11 04:16:52 +02:00
if ( json [ "hideTagRenderingsWithLabels" ] ) {
const hideLabels : Set < string > = new Set ( json [ "hideTagRenderingsWithLabels" ] )
// These labels caused at least one deletion
const usedLabels : Set < string > = new Set < string > ( )
const filtered = [ ]
for ( const tr of found . tagRenderings ) {
const labels = tr [ "labels" ]
if ( labels !== undefined ) {
const forbiddenLabel = labels . findIndex ( ( l ) = > hideLabels . has ( l ) )
if ( forbiddenLabel >= 0 ) {
usedLabels . add ( labels [ forbiddenLabel ] )
context . info (
"Dropping tagRendering " +
2022-04-13 00:31:13 +02:00
tr [ "id" ] +
2023-10-11 04:16:52 +02:00
" as it has a forbidden label: " +
labels [ forbiddenLabel ]
2022-04-13 00:31:13 +02:00
)
2022-02-08 02:23:38 +01:00
continue
}
2023-10-11 04:16:52 +02:00
}
2022-02-08 02:23:38 +01:00
2023-10-11 04:16:52 +02:00
if ( hideLabels . has ( tr [ "id" ] ) ) {
usedLabels . add ( tr [ "id" ] )
context . info (
"Dropping tagRendering " + tr [ "id" ] + " as its id is a forbidden label"
)
continue
2022-02-08 02:23:38 +01:00
}
2023-10-11 04:16:52 +02:00
if ( hideLabels . has ( tr [ "group" ] ) ) {
usedLabels . add ( tr [ "group" ] )
context . info (
"Dropping tagRendering " +
tr [ "id" ] +
" as its group `" +
tr [ "group" ] +
"` is a forbidden label"
2022-04-13 00:31:13 +02:00
)
2023-10-11 04:16:52 +02:00
continue
2022-02-08 02:23:38 +01:00
}
2023-10-11 04:16:52 +02:00
filtered . push ( tr )
2022-02-08 02:23:38 +01:00
}
2023-10-11 04:16:52 +02:00
const unused = Array . from ( hideLabels ) . filter ( ( l ) = > ! usedLabels . has ( l ) )
if ( unused . length > 0 ) {
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: " +
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"
)
}
found . tagRenderings = filtered
2022-01-21 01:57:16 +01:00
}
}
2023-10-11 04:16:52 +02:00
return layers
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
}
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
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 ) {
2023-10-11 04:16:52 +02:00
context . err ( "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 ) ) {
2023-10-11 04:16:52 +02:00
context . warn (
2022-04-13 00:31:13 +02:00
"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 )
}
2023-10-11 04:16:52 +02:00
return json
2022-01-21 01:57:16 +01:00
}
}
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
}
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
2022-05-06 12:41:24 +02:00
if ( ! ( json . enableNoteImports ? ? true ) ) {
2023-10-11 04:16:52 +02:00
context . info (
"Not creating a note import layers for theme " + json . id + " as they are disabled"
)
return json
2022-05-06 12:41:24 +02:00
}
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 ,
2023-10-11 04:16:52 +02:00
context . inOperation ( this . name ) . enter ( i1 )
2022-05-06 12:41:24 +02:00
)
2023-10-11 04:16:52 +02:00
if ( importLayerResult !== undefined ) {
json . layers . push ( importLayerResult )
2022-01-21 01:57:16 +01:00
}
2022-05-06 12:41:24 +02:00
} catch ( e ) {
2023-10-11 04:16:52 +02:00
context . err ( "Could not generate an import-layer for " + layer . id + " due to " + e )
2022-01-21 01:57:16 +01:00
}
}
2023-10-11 04:16:52 +02:00
return json
2022-01-21 01:57:16 +01:00
}
}
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
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
2022-04-06 17:28:51 +02:00
const conversion = new AddContextToTranslations < LayoutConfigJson > ( "themes:" )
2023-10-11 04:16:52 +02:00
return conversion . convert ( json , context )
2022-04-06 17:28:51 +02:00
}
}
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
}
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
2022-01-24 00:59:23 +01:00
const overrideAll = json . overrideAll
if ( overrideAll === undefined ) {
2023-10-11 04:16:52 +02:00
return json
2022-01-24 00:59:23 +01:00
}
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
2023-10-11 04:16:52 +02:00
return json
2022-01-24 00:59:23 +01:00
}
}
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
}
2023-10-11 04:16:52 +02:00
convert ( theme : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
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
const layers : LayerConfigJson [ ] = < LayerConfigJson [ ] > theme . layers // Layers should be expanded at this point
knownTagRenderings . forEach ( ( value , key ) = > {
2023-10-11 04:16:52 +02:00
value [ "id" ] = key
2022-01-21 01:57:16 +01:00
} )
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 ) {
2023-10-11 04:16:52 +02:00
context . info (
"Added " + dependency . config . id + " to the theme. " + dependency . reason
2022-04-23 15:20:54 +02:00
)
}
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 {
2023-10-11 04:16:52 +02:00
. . . theme ,
layers : layers ,
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
}
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
2022-04-13 00:31:13 +02:00
if ( json . id !== "personal" ) {
2023-10-11 04:16:52 +02:00
return json
2022-02-14 15:41:14 +01:00
}
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 ) )
2023-10-11 04:16:52 +02:00
context . info ( "The personal theme has " + json . layers . length + " public layers" )
return json
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
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
2022-04-13 00:31:13 +02:00
if ( json . hideFromOverview === true ) {
2023-10-11 04:16:52 +02:00
return json
2022-03-24 19:59:46 +01:00
}
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
2023-10-11 04:16:52 +02:00
context . warn (
2022-04-13 00:31:13 +02:00
"The theme " +
2023-10-11 04:16:52 +02:00
json . id +
" has an inline layer: " +
layer [ "id" ] +
". This is discouraged."
)
2022-03-24 19:59:46 +01:00
}
2023-10-11 04:16:52 +02:00
return json
2022-03-24 19:59:46 +01:00
}
}
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
2023-10-11 04:16:52 +02:00
convert ( json : LayoutConfigJson , context : ConversionContext ) : LayoutConfigJson {
2023-03-29 18:54:00 +02:00
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
2023-10-11 04:16:52 +02:00
const needsNodeDatabase = result . layers ? . some ( ( l : LayerConfigJson ) = >
l . tagRenderings ? . some ( ( tr ) = >
ValidationUtils . getSpecialVisualisations ( < any > tr ) ? . some (
2023-03-29 18:54:00 +02:00
( special ) = > special . needsNodeDatabase
)
)
)
if ( needsNodeDatabase ) {
2023-10-11 04:16:52 +02:00
context . info (
"Setting 'enableNodeDatabase' as this theme uses a special visualisation which needs to keep track of _all_ nodes"
2023-03-29 18:54:00 +02:00
)
2023-10-11 04:16:52 +02:00
result . enableNodeDatabase = true
2023-03-29 18:54:00 +02:00
}
return result
}
2022-01-21 01:57:16 +01:00
}