2021-04-10 03:18:32 +02:00
import ScriptUtils from "./ScriptUtils" ;
import { Utils } from "../Utils" ;
import { lstatSync , readdirSync , readFileSync , writeFileSync } from "fs" ;
Utils . runningFromConsole = true
import LayerConfig from "../Customizations/JSON/LayerConfig" ;
import { error } from "util" ;
import * as licenses from "../assets/generated/license_info.json"
import SmallLicense from "../Models/smallLicense" ;
import LayoutConfig from "../Customizations/JSON/LayoutConfig" ;
2021-04-10 03:50:44 +02:00
import { LayerConfigJson } from "../Customizations/JSON/LayerConfigJson" ;
2021-04-10 16:01:14 +02:00
import { Layer } from "leaflet" ;
2021-04-10 03:18:32 +02:00
// This scripts scans 'assets/layers/*.json' for layer definition files and 'assets/themes/*.json' for theme definition files.
// It spits out an overview of those to be used to load them
// First, remove the old file. It might be buggy!
writeFileSync ( "./assets/generated/known_layers_and_themes.json" , JSON . stringify ( {
"layers" : [ ] ,
"themes" : [ ]
} ) )
const layerFiles = ScriptUtils . readDirRecSync ( "./assets/layers" )
. filter ( path = > path . indexOf ( ".json" ) > 0 )
. filter ( path = > path . indexOf ( "license_info.json" ) < 0 )
. map ( path = > {
try {
const parsed = JSON . parse ( readFileSync ( path , "UTF8" ) ) ;
return parsed
} catch ( e ) {
console . error ( "Could not parse file " , path , "due to " , e )
}
} )
2021-04-10 03:50:44 +02:00
const themeFiles : any [ ] = ScriptUtils . readDirRecSync ( "./assets/themes" )
2021-04-10 03:18:32 +02:00
. filter ( path = > path . indexOf ( ".json" ) > 0 )
. filter ( path = > path . indexOf ( "license_info.json" ) < 0 )
. map ( path = > {
return JSON . parse ( readFileSync ( path , "UTF8" ) ) ;
} )
writeFileSync ( "./assets/generated/known_layers_and_themes.json" , JSON . stringify ( {
"layers" : layerFiles ,
"themes" : themeFiles
} ) )
console . log ( "Discovered " , layerFiles . length , "layers and " , themeFiles . length , "themes\n" )
console . log ( " ---------- VALIDATING ---------" )
// ------------- VALIDATION --------------
const licensePaths = [ ]
for ( const i in licenses ) {
licensePaths . push ( licenses [ i ] . path )
}
const knownPaths = new Set < string > ( licensePaths )
2021-04-11 03:05:24 +02:00
const linuxHints = [ ]
2021-04-10 16:01:14 +02:00
function validateLayer ( layerJson : LayerConfigJson , context? : string ) : string [ ] {
let errorCount = [ ] ;
2021-04-10 03:50:44 +02:00
if ( layerJson [ "overpassTags" ] !== undefined ) {
2021-04-11 03:17:59 +02:00
errorCount . push ( "Layer " + layerJson . id + "still uses the old 'overpassTags'-format. Please use \"source\": {\"osmTags\": <tags>}' instead of \"overpassTags\": <tags> (note: this isn't your fault, the custom theme generator still spits out the old format)" )
2021-04-10 03:18:32 +02:00
}
2021-04-10 03:50:44 +02:00
try {
const layer = new LayerConfig ( layerJson , "test" , true )
const images = Array . from ( layer . ExtractImages ( ) )
const remoteImages = images . filter ( img = > img . indexOf ( "http" ) == 0 )
for ( const remoteImage of remoteImages ) {
2021-04-11 03:05:24 +02:00
errorCount . push ( "Found a remote image: " + remoteImage + " in layer " + layer . id + ", please download it." )
2021-04-11 03:08:29 +02:00
const path = remoteImage . substring ( remoteImage . lastIndexOf ( "/" ) + 1 )
2021-04-11 03:17:59 +02:00
linuxHints . push ( "wget " + remoteImage )
2021-04-11 03:05:24 +02:00
linuxHints . push ( ` echo '{"path":" ${ path } ", "license": "<insert license here>", "authors": [ "<insert author(s) here"], "sources": [ ${ remoteImage } ] ` )
2021-04-10 03:18:32 +02:00
}
2021-04-10 03:50:44 +02:00
for ( const image of images ) {
if ( ! knownPaths . has ( image ) ) {
2021-04-10 16:01:14 +02:00
const ctx = context === undefined ? "" : ` in a layer defined in the theme ${ context } `
errorCount . push ( ` Image with path ${ image } not found or not attributed; it is used in ${ layer . id } ${ ctx } ` )
2021-04-10 03:50:44 +02:00
}
}
2021-04-10 14:25:06 +02:00
2021-04-10 03:50:44 +02:00
} catch ( e ) {
2021-04-11 01:58:51 +02:00
return [ ` Layer ${ layerJson . id } ` ? ? JSON . stringify ( layerJson ) . substring ( 0 , 50 ) + " is invalid: " + e ]
2021-04-10 03:18:32 +02:00
}
return errorCount
}
2021-04-10 03:50:44 +02:00
2021-04-10 16:01:14 +02:00
let layerErrorCount = [ ]
2021-04-10 03:18:32 +02:00
const knownLayerIds = new Set < string > ( ) ;
for ( const layerFile of layerFiles ) {
knownLayerIds . add ( layerFile . id )
2021-04-11 01:58:51 +02:00
layerErrorCount . push ( . . . validateLayer ( layerFile ) )
2021-04-10 03:18:32 +02:00
}
2021-04-10 16:01:14 +02:00
let themeErrorCount = [ ]
2021-04-10 03:18:32 +02:00
for ( const themeFile of themeFiles ) {
for ( const layer of themeFile . layers ) {
2021-04-10 03:50:44 +02:00
if ( typeof layer === "string" ) {
if ( ! knownLayerIds . has ( layer ) ) {
2021-04-11 01:58:51 +02:00
themeErrorCount . push ( "Unknown layer id: " + layer )
2021-04-10 03:18:32 +02:00
}
2021-04-10 15:53:47 +02:00
} else {
if ( layer . builtin !== undefined ) {
if ( ! knownLayerIds . has ( layer . builtin ) ) {
2021-04-11 01:58:51 +02:00
themeErrorCount . push ( "Unknown layer id: " + layer . builtin + "(which uses inheritance)" )
}
2021-04-10 15:53:47 +02:00
} else {
// layer.builtin contains layer overrides - we can skip those
2021-04-11 01:58:51 +02:00
layerErrorCount . push ( . . . validateLayer ( layer , themeFile . id ) )
2021-04-10 15:53:47 +02:00
}
2021-04-10 03:18:32 +02:00
}
}
2021-04-10 03:50:44 +02:00
2021-04-10 15:53:47 +02:00
themeFile . layers = themeFile . layers
. filter ( l = > typeof l != "string" ) // We remove all the builtin layer references as they don't work with ts-node for some weird reason
. filter ( l = > l . builtin === undefined )
2021-04-10 03:50:44 +02:00
2021-04-10 03:18:32 +02:00
try {
2021-04-10 03:50:44 +02:00
const theme = new LayoutConfig ( themeFile , true , "test" )
2021-04-10 14:25:06 +02:00
if ( theme . id !== theme . id . toLowerCase ( ) ) {
2021-04-11 01:58:51 +02:00
themeErrorCount . push ( "Theme ids should be in lowercase, but it is " + theme . id )
2021-04-10 03:18:32 +02:00
}
} catch ( e ) {
2021-04-11 01:58:51 +02:00
themeErrorCount . push ( "Could not parse theme " + themeFile [ "id" ] + "due to" , e )
2021-04-10 03:18:32 +02:00
}
}
2021-04-10 16:06:01 +02:00
2021-04-10 16:01:14 +02:00
if ( layerErrorCount . length + themeErrorCount . length == 0 ) {
2021-04-10 14:25:06 +02:00
console . log ( "All good!" )
} else {
2021-04-10 16:01:14 +02:00
const errors = layerErrorCount . concat ( themeErrorCount ) . join ( "\n" )
console . log ( errors )
2021-04-11 03:05:24 +02:00
const msg = ( ` Found ${ layerErrorCount . length } errors in the layers; ${ themeErrorCount . length } errors in the themes ` )
2021-04-11 01:58:51 +02:00
console . log ( msg )
if ( process . argv . indexOf ( "--report" ) >= 0 ) {
2021-04-11 03:17:59 +02:00
console . log ( "Writing report!" )
2021-04-10 16:06:01 +02:00
writeFileSync ( "layer_report.txt" , errors )
2021-04-11 01:58:51 +02:00
}
2021-04-11 03:17:59 +02:00
2021-04-11 01:58:51 +02:00
if ( process . argv . indexOf ( "--no-fail" ) < 0 ) {
2021-04-10 15:01:28 +02:00
throw msg ;
}
2021-04-10 14:25:06 +02:00
}