2022-07-02 01:59:26 +02:00
/ * * *
* Parses presets from the iD repository and extracts some usefull tags from them
* /
2022-07-11 09:14:26 +02:00
import ScriptUtils from "../ScriptUtils"
2022-07-02 01:59:26 +02:00
import { existsSync , readFileSync , writeFileSync } from "fs"
2023-10-01 13:13:07 +02:00
import known_languages from "../../src/assets/language_native.json"
import { LayerConfigJson } from "../../src/Models/ThemeConfig/Json/LayerConfigJson"
import { MappingConfigJson } from "../../src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import SmallLicense from "../../src/Models/smallLicense"
2024-07-29 03:47:20 +02:00
import Script from "../Script"
2022-07-02 01:59:26 +02:00
interface IconThief {
steal ( iconName : string ) : boolean
}
2022-07-02 02:45:59 +02:00
interface IdPresetJson {
2022-07-02 01:59:26 +02:00
icon : string
geometry : ( "point" | "line" | "area" ) [ ]
/ * *
* Extra search terms
* /
terms : string [ ]
tags : Record < string , string >
name : string
2022-07-02 02:45:59 +02:00
searchable? : boolean
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
class IdPreset implements IdPresetJson {
2024-07-29 03:47:20 +02:00
private readonly _preset : IdPresetJson
2022-07-02 02:45:59 +02:00
constructor ( preset : IdPresetJson ) {
this . _preset = preset
}
public get searchable ( ) : boolean {
return this . _preset . searchable
}
public get name() {
return this . _preset . name
}
public get terms() {
return this . _preset . terms
}
public get tags() {
return this . _preset . tags
}
public get geometry() {
return this . _preset . geometry
}
public get icon ( ) : string {
return this . _preset . icon
}
static fromFile ( file : string ) : IdPreset {
return new IdPreset ( JSON . parse ( readFileSync ( file , "utf8" ) ) )
}
public parseTags ( ) : string | { and : string [ ] } {
const preset = this . _preset
const tagKeys = Object . keys ( preset . tags )
if ( tagKeys . length === 1 ) {
return tagKeys [ 0 ] + "=" + preset . tags [ tagKeys [ 0 ] ]
} else {
return {
and : tagKeys.map ( ( key ) = > key + "=" + preset . tags [ key ] ) ,
}
}
}
}
class MakiThief implements IconThief {
public readonly _prefix : string
2022-07-02 01:59:26 +02:00
private readonly _directory : string
2022-07-02 02:45:59 +02:00
private readonly _license : SmallLicense
2022-07-02 01:59:26 +02:00
private readonly _targetDir : string
2022-09-08 21:40:48 +02:00
2022-07-02 02:45:59 +02:00
constructor (
directory : string ,
targetDir : string ,
license : SmallLicense ,
prefix : string = "maki-"
) {
this . _license = license
2022-07-02 01:59:26 +02:00
this . _directory = directory
this . _targetDir = targetDir
2022-07-02 02:45:59 +02:00
this . _prefix = prefix
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
public steal ( iconName : string ) : boolean {
const target = this . _targetDir + iconName + ".svg"
if ( existsSync ( target ) ) {
return true
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
try {
const file = readFileSync ( this . _directory + iconName + ".svg" , "utf8" )
writeFileSync ( target , file , "utf8" )
2022-07-02 01:59:26 +02:00
2022-07-02 02:45:59 +02:00
writeFileSync (
target + ".license_info.json" ,
JSON . stringify ( { . . . this . _license , path : this._prefix + iconName + ".svg" } ) ,
"utf8"
)
console . log ( "Successfully stolen " + iconName )
2022-07-02 01:59:26 +02:00
return true
2022-07-02 02:45:59 +02:00
} catch ( e ) {
console . log ( "Could not steal " + iconName + " due to " + e . message )
return false
}
}
}
class AggregateIconThief implements IconThief {
private readonly makiThiefs : MakiThief [ ]
constructor ( makiThiefs : MakiThief [ ] ) {
this . makiThiefs = makiThiefs
}
public steal ( iconName : string ) : boolean {
for ( const makiThief1 of this . makiThiefs ) {
if ( iconName . startsWith ( makiThief1 . _prefix ) ) {
return makiThief1 . steal ( iconName . substr ( makiThief1 . _prefix . length ) )
}
2022-07-02 01:59:26 +02:00
}
return false
}
}
class IdThief {
private readonly _idPresetsRepository : string
private readonly _tranlationFiles : Record < string , object > = { }
private readonly _knownLanguages : string [ ]
private readonly _iconThief : IconThief
public constructor ( idPresetsRepository : string , iconThief : IconThief ) {
this . _idPresetsRepository = idPresetsRepository
this . _iconThief = iconThief
const knownById = ScriptUtils . readDirRecSync (
` ${ this . _idPresetsRepository } /dist/translations/ `
)
. map ( ( pth ) = > pth . substring ( pth . lastIndexOf ( "/" ) + 1 , pth . length - ".json" . length ) )
. filter ( ( lng ) = > ! lng . endsWith ( ".min" ) )
2022-07-02 02:45:59 +02:00
const missing = Object . keys ( known_languages ) . filter (
( lng ) = > knownById . indexOf ( lng . replace ( "-" , "_" ) ) < 0
2022-09-08 21:40:48 +02:00
)
2022-07-02 01:59:26 +02:00
this . _knownLanguages = knownById . filter ( ( lng ) = > known_languages [ lng ] !== undefined )
console . log (
"Id knows following languages:" ,
this . _knownLanguages . join ( ", " ) ,
"missing:" ,
missing
)
}
2022-07-03 13:18:34 +02:00
public getTranslation ( language : string , . . . path : string [ ] ) : string {
2022-07-02 01:59:26 +02:00
let obj = this . loadTranslationFile ( language ) [ language ]
for ( const p of path ) {
obj = obj [ p ]
if ( obj === undefined ) {
return undefined
}
}
return obj
}
2022-07-02 02:45:59 +02:00
/ * *
* Creates a mapRendering - mapping for the 'shop' theme
* /
public readShopIcons ( ) : { if : string | { and : string [ ] } ; then : string } [ ] {
const dir = this . _idPresetsRepository + "/data/presets/shop"
const mappings : {
if : string | { and : string [ ] }
then : string
} [ ] = [ ]
const files = ScriptUtils . readDirRecSync ( dir , 1 )
for ( const file of files ) {
const preset = IdPreset . fromFile ( file )
if ( ! this . _iconThief . steal ( preset . icon ) ) {
continue
}
const mapping = {
if : preset . parseTags ( ) ,
2023-10-06 23:56:50 +02:00
then : "./assets/layers/id_presets/" + preset . icon + ".svg" ,
2022-07-02 02:45:59 +02:00
}
mappings . push ( mapping )
}
return mappings
}
2022-07-02 01:59:26 +02:00
/ * *
* Creates a tagRenderingConfigJson for the 'shop' theme
* /
2022-07-03 13:18:34 +02:00
public readShopPresets ( ) : MappingConfigJson [ ] {
2022-07-02 01:59:26 +02:00
const dir = this . _idPresetsRepository + "/data/presets/shop"
2022-07-03 13:18:34 +02:00
const mappings : MappingConfigJson [ ] = [ ]
2022-07-02 01:59:26 +02:00
const files = ScriptUtils . readDirRecSync ( dir , 1 )
for ( const file of files ) {
2022-07-02 02:45:59 +02:00
const name = file . substring ( file . lastIndexOf ( "/" ) + 1 , file . length - ".json" . length )
const preset = IdPreset . fromFile ( file )
2022-07-02 01:59:26 +02:00
2022-07-02 02:45:59 +02:00
if ( preset . searchable === false ) {
2022-07-02 01:59:26 +02:00
continue
}
2022-07-02 02:45:59 +02:00
2024-08-09 16:58:48 +02:00
if ( preset . tags [ "shop" ] === "vacant" ) {
2024-07-29 03:47:20 +02:00
console . log ( "Skipping 'vacant'" )
continue
}
2022-07-02 02:45:59 +02:00
console . log ( ` ${ name } (shop= ${ preset . tags [ "shop" ] } ), ${ preset . icon } ` )
const thenClause : Record < string , string > = {
2022-07-02 01:59:26 +02:00
en : preset.name ,
}
2022-07-03 13:18:34 +02:00
const terms : Record < string , string [ ] > = {
en : preset.terms ,
}
2022-07-02 01:59:26 +02:00
for ( const lng of this . _knownLanguages ) {
2022-07-03 13:18:34 +02:00
const lngMc = lng . replace ( "-" , "_" )
2022-07-02 02:45:59 +02:00
const tr = this . getTranslation ( lng , "presets" , "presets" , "shop/" + name , "name" )
2022-07-03 13:18:34 +02:00
if ( tr !== undefined ) {
thenClause [ lngMc ] = tr
2022-07-02 01:59:26 +02:00
}
2022-07-03 13:18:34 +02:00
const termsTr = this . getTranslation (
lng ,
"presets" ,
"presets" ,
"shop/" + name ,
"terms"
)
if ( termsTr !== undefined ) {
terms [ lngMc ] = termsTr . split ( "," )
}
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
2024-07-29 03:47:20 +02:00
const tag = preset . parseTags ( )
2022-07-03 13:18:34 +02:00
const mapping : MappingConfigJson = {
2022-07-02 01:59:26 +02:00
if : tag ,
2022-07-03 13:18:34 +02:00
then : thenClause ,
searchTerms : terms ,
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
if ( preset . tags [ "shop" ] == "yes" ) {
2022-07-02 01:59:26 +02:00
mapping [ "hideInAnswer" ] = true
mapping . if [ "en" ] = "Unspecified shop"
}
2022-07-02 02:45:59 +02:00
if ( this . _iconThief . steal ( preset . icon ) ) {
2022-07-02 01:59:26 +02:00
mapping [ "icon" ] = {
2022-07-03 13:18:34 +02:00
path : "./assets/layers/id_presets/" + preset . icon + ".svg" ,
2022-07-02 02:45:59 +02:00
class : "medium" ,
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
} else {
console . log ( preset . icon + " could not be stolen :(" )
2022-07-02 01:59:26 +02:00
}
2022-07-02 02:45:59 +02:00
2022-07-02 01:59:26 +02:00
mappings . push ( mapping )
}
return mappings
}
private loadTranslationFile ( language : string ) : object {
const cached = this . _tranlationFiles [ language ]
if ( cached ) {
return cached
}
return ( this . _tranlationFiles [ language ] = JSON . parse (
readFileSync ( ` ${ this . _idPresetsRepository } /dist/translations/ ${ language } .json ` , "utf8" )
) )
}
}
2024-08-09 16:58:48 +02:00
class ReadIdPresets extends Script {
2024-07-29 03:47:20 +02:00
constructor ( ) {
2024-08-09 16:58:48 +02:00
super (
"Reads the id-tagging-schema repository and steals the presets; which will be written into 'id_presets.json'\n\nArguments: [path-to-repository] [path-to-target]\n" +
"Note that default arguments are used"
)
2024-07-29 03:47:20 +02:00
}
async main ( args : string [ ] ) : Promise < void > {
const targetDir = args [ 1 ] ? ? "./assets/layers/id_presets/"
const makiThief = new MakiThief (
"../maki/icons/" ,
targetDir + "maki-" ,
{
authors : [ "Maki icon set" ] ,
license : "CC0" ,
path : null ,
sources : [ "https://github.com/mapbox/maki" ] ,
} ,
"maki-"
)
const temakiThief = new MakiThief (
"../temaki/icons/" ,
targetDir + "temaki-" ,
{
authors : [ "Temaki icon set" ] ,
license : "CC0" ,
path : null ,
sources : [ "https://github.com/ideditor/temaki" ] ,
} ,
"temaki-"
)
const fasThief = new MakiThief (
"../Font-Awesome/svgs/solid/" ,
targetDir + "fas-" ,
{
authors : [ "Font-Awesome icon set" ] ,
license : "CC-BY 4.0" ,
path : null ,
sources : [ "https://github.com/FortAwesome/Font-Awesome" ] ,
} ,
"fas-"
)
const iconThief = new AggregateIconThief ( [ makiThief , temakiThief , fasThief ] )
const thief = new IdThief ( args [ 0 ] ? ? "../id-tagging-schema/" , iconThief )
const id_presets_path = targetDir + "id_presets.json"
const idPresets = < LayerConfigJson > JSON . parse ( readFileSync ( id_presets_path , "utf8" ) )
idPresets . tagRenderings = [
{
id : "shop_types" ,
mappings : thief.readShopPresets ( ) ,
} ,
{
id : "shop_rendering" ,
mappings : thief.readShopIcons ( ) ,
} ,
]
console . log ( "Writing id presets to" , id_presets_path )
writeFileSync ( id_presets_path , JSON . stringify ( idPresets , null , " " ) , "utf8" )
}
}
new ReadIdPresets ( ) . run ( )