Fix generateLayerOverview, drop priviliged 'icons.json' from code
This commit is contained in:
parent
df3ca4cce3
commit
36aed99843
10 changed files with 267 additions and 167 deletions
|
@ -1,5 +1,4 @@
|
||||||
import questions from "../assets/tagRenderings/questions.json"
|
import questions from "../assets/tagRenderings/questions.json"
|
||||||
import icons from "../assets/tagRenderings/icons.json"
|
|
||||||
import { Utils } from "../Utils"
|
import { Utils } from "../Utils"
|
||||||
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
|
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
|
||||||
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"
|
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"
|
||||||
|
@ -14,11 +13,9 @@ export default class SharedTagRenderings {
|
||||||
SharedTagRenderings.generatedSharedFields()
|
SharedTagRenderings.generatedSharedFields()
|
||||||
public static SharedTagRenderingJson: Map<string, TagRenderingConfigJson> =
|
public static SharedTagRenderingJson: Map<string, TagRenderingConfigJson> =
|
||||||
SharedTagRenderings.generatedSharedFieldsJsons()
|
SharedTagRenderings.generatedSharedFieldsJsons()
|
||||||
public static SharedIcons: Map<string, TagRenderingConfig> =
|
|
||||||
SharedTagRenderings.generatedSharedFields(true)
|
|
||||||
|
|
||||||
private static generatedSharedFields(iconsOnly = false): Map<string, TagRenderingConfig> {
|
private static generatedSharedFields(): Map<string, TagRenderingConfig> {
|
||||||
const configJsons = SharedTagRenderings.generatedSharedFieldsJsons(iconsOnly)
|
const configJsons = SharedTagRenderings.generatedSharedFieldsJsons()
|
||||||
const d = new Map<string, TagRenderingConfig>()
|
const d = new Map<string, TagRenderingConfig>()
|
||||||
for (const key of Array.from(configJsons.keys())) {
|
for (const key of Array.from(configJsons.keys())) {
|
||||||
try {
|
try {
|
||||||
|
@ -31,7 +28,7 @@ export default class SharedTagRenderings {
|
||||||
console.error(
|
console.error(
|
||||||
"BUG: could not parse",
|
"BUG: could not parse",
|
||||||
key,
|
key,
|
||||||
" from questions.json or icons.json - this error happened during the build step of the SharedTagRenderings",
|
" from questions.json - this error happened during the build step of the SharedTagRenderings",
|
||||||
e
|
e
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -40,24 +37,14 @@ export default class SharedTagRenderings {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
private static generatedSharedFieldsJsons(
|
private static generatedSharedFieldsJsons(): Map<string, TagRenderingConfigJson> {
|
||||||
iconsOnly = false
|
|
||||||
): Map<string, TagRenderingConfigJson> {
|
|
||||||
const dict = new Map<string, TagRenderingConfigJson>()
|
const dict = new Map<string, TagRenderingConfigJson>()
|
||||||
|
|
||||||
if (!iconsOnly) {
|
for (const key in questions) {
|
||||||
for (const key in questions) {
|
|
||||||
if (key === "id") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dict.set(key, <TagRenderingConfigJson>questions[key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const key in icons) {
|
|
||||||
if (key === "id") {
|
if (key === "id") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
dict.set(key, <TagRenderingConfigJson>icons[key])
|
dict.set(key, <TagRenderingConfigJson>questions[key])
|
||||||
}
|
}
|
||||||
|
|
||||||
dict.forEach((value, key) => {
|
dict.forEach((value, key) => {
|
||||||
|
|
|
@ -194,8 +194,7 @@ export default class DetermineLayout {
|
||||||
let { errors } = new ValidateThemeAndLayers(
|
let { errors } = new ValidateThemeAndLayers(
|
||||||
new DoesImageExist(new Set<string>(), (_) => true),
|
new DoesImageExist(new Set<string>(), (_) => true),
|
||||||
"",
|
"",
|
||||||
false,
|
false
|
||||||
SharedTagRenderings.SharedTagRendering
|
|
||||||
).convert(json, "validation")
|
).convert(json, "validation")
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
throw "Detected errors: " + errors.join("\n")
|
throw "Detected errors: " + errors.join("\n")
|
||||||
|
|
|
@ -5,9 +5,12 @@ import metapaths from "../../../assets/layoutconfigmeta.json"
|
||||||
import tagrenderingmetapaths from "../../../assets/questionabletagrenderingconfigmeta.json"
|
import tagrenderingmetapaths from "../../../assets/questionabletagrenderingconfigmeta.json"
|
||||||
import Translations from "../../../UI/i18n/Translations"
|
import Translations from "../../../UI/i18n/Translations"
|
||||||
|
|
||||||
export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
export class ExtractImages extends Conversion<
|
||||||
|
LayoutConfigJson,
|
||||||
|
{ path: string; context: string }[]
|
||||||
|
> {
|
||||||
private _isOfficial: boolean
|
private _isOfficial: boolean
|
||||||
private _sharedTagRenderings: Map<string, any>
|
private _sharedTagRenderings: Set<string>
|
||||||
|
|
||||||
private static readonly layoutMetaPaths = metapaths.filter(
|
private static readonly layoutMetaPaths = metapaths.filter(
|
||||||
(mp) =>
|
(mp) =>
|
||||||
|
@ -16,7 +19,7 @@ export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
||||||
)
|
)
|
||||||
private static readonly tagRenderingMetaPaths = tagrenderingmetapaths
|
private static readonly tagRenderingMetaPaths = tagrenderingmetapaths
|
||||||
|
|
||||||
constructor(isOfficial: boolean, sharedTagRenderings: Map<string, any>) {
|
constructor(isOfficial: boolean, sharedTagRenderings: Set<string>) {
|
||||||
super("Extract all images from a layoutConfig using the meta paths.", [], "ExctractImages")
|
super("Extract all images from a layoutConfig using the meta paths.", [], "ExctractImages")
|
||||||
this._isOfficial = isOfficial
|
this._isOfficial = isOfficial
|
||||||
this._sharedTagRenderings = sharedTagRenderings
|
this._sharedTagRenderings = sharedTagRenderings
|
||||||
|
@ -79,8 +82,8 @@ export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
||||||
convert(
|
convert(
|
||||||
json: LayoutConfigJson,
|
json: LayoutConfigJson,
|
||||||
context: string
|
context: string
|
||||||
): { result: string[]; errors: string[]; warnings: string[] } {
|
): { result: { path: string; context: string }[]; errors: string[]; warnings: string[] } {
|
||||||
const allFoundImages: string[] = []
|
const allFoundImages: { path: string; context: string }[] = []
|
||||||
const errors = []
|
const errors = []
|
||||||
const warnings = []
|
const warnings = []
|
||||||
for (const metapath of ExtractImages.layoutMetaPaths) {
|
for (const metapath of ExtractImages.layoutMetaPaths) {
|
||||||
|
@ -108,7 +111,7 @@ export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
allFoundImages.push(foundImage)
|
allFoundImages.push({ path: foundImage, context: context + "." + path })
|
||||||
} else {
|
} else {
|
||||||
// This is a tagRendering.
|
// This is a tagRendering.
|
||||||
// Either every rendered value might be an icon
|
// Either every rendered value might be an icon
|
||||||
|
@ -137,7 +140,10 @@ export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
||||||
JSON.stringify(img.leaf)
|
JSON.stringify(img.leaf)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
allFoundImages.push(img.leaf)
|
allFoundImages.push({
|
||||||
|
path: img.leaf,
|
||||||
|
context: context + "." + path,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!allRenderedValuesAreImages && isImage) {
|
if (!allRenderedValuesAreImages && isImage) {
|
||||||
|
@ -146,7 +152,12 @@ export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
||||||
...Translations.T(
|
...Translations.T(
|
||||||
img.leaf,
|
img.leaf,
|
||||||
"extract_images from " + img.path.join(".")
|
"extract_images from " + img.path.join(".")
|
||||||
).ExtractImages(false)
|
)
|
||||||
|
.ExtractImages(false)
|
||||||
|
.map((path) => ({
|
||||||
|
path,
|
||||||
|
context: context + "." + path,
|
||||||
|
}))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,15 +177,19 @@ export class ExtractImages extends Conversion<LayoutConfigJson, string[]> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const splitParts = []
|
const cleanedImages: { path: string; context: string }[] = []
|
||||||
.concat(
|
|
||||||
...Utils.NoNull(allFoundImages)
|
for (const foundImage of allFoundImages) {
|
||||||
.map((img) => img["path"] ?? img)
|
// Split "circle:white;./assets/layers/.../something.svg" into ["circle", "./assets/layers/.../something.svg"]
|
||||||
.map((img) => img.split(";"))
|
const allPaths = Utils.NoNull(
|
||||||
|
Utils.NoEmpty(foundImage.path?.split(";")?.map((part) => part.split(":")[0]))
|
||||||
)
|
)
|
||||||
.map((img) => img.split(":")[0])
|
for (const path of allPaths) {
|
||||||
.filter((img) => img !== "")
|
cleanedImages.push({ path, context: foundImage.context })
|
||||||
return { result: Utils.Dedup(splitParts), errors, warnings }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { result: cleanedImages, errors, warnings }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,29 +7,24 @@ import {
|
||||||
FirstOf,
|
FirstOf,
|
||||||
Fuse,
|
Fuse,
|
||||||
On,
|
On,
|
||||||
SetDefault,
|
SetDefault
|
||||||
} from "./Conversion"
|
} from "./Conversion";
|
||||||
import { LayerConfigJson } from "../Json/LayerConfigJson"
|
import { LayerConfigJson } from "../Json/LayerConfigJson";
|
||||||
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson"
|
import { TagRenderingConfigJson } from "../Json/TagRenderingConfigJson";
|
||||||
import { Utils } from "../../../Utils"
|
import { Utils } from "../../../Utils";
|
||||||
import RewritableConfigJson from "../Json/RewritableConfigJson"
|
import RewritableConfigJson from "../Json/RewritableConfigJson";
|
||||||
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
|
import SpecialVisualizations from "../../../UI/SpecialVisualizations";
|
||||||
import Translations from "../../../UI/i18n/Translations"
|
import Translations from "../../../UI/i18n/Translations";
|
||||||
import { Translation } from "../../../UI/i18n/Translation"
|
import { Translation } from "../../../UI/i18n/Translation";
|
||||||
import tagrenderingconfigmeta from "../../../assets/tagrenderingconfigmeta.json"
|
import tagrenderingconfigmeta from "../../../assets/tagrenderingconfigmeta.json";
|
||||||
import { AddContextToTranslations } from "./AddContextToTranslations"
|
import { AddContextToTranslations } from "./AddContextToTranslations";
|
||||||
import FilterConfigJson from "../Json/FilterConfigJson"
|
import FilterConfigJson from "../Json/FilterConfigJson";
|
||||||
import predifined_filters from "../../../assets/layers/filters/filters.json"
|
import predifined_filters from "../../../assets/layers/filters/filters.json";
|
||||||
|
import { TagConfigJson } from "../Json/TagConfigJson";
|
||||||
|
import PointRenderingConfigJson from "../Json/PointRenderingConfigJson";
|
||||||
|
import LineRenderingConfigJson from "../Json/LineRenderingConfigJson";
|
||||||
|
|
||||||
class ExpandFilter extends DesugaringStep<LayerConfigJson> {
|
class ExpandFilter extends DesugaringStep<LayerConfigJson> {
|
||||||
private static load_filters(): Map<string, FilterConfigJson> {
|
|
||||||
let filters = new Map<string, FilterConfigJson>()
|
|
||||||
for (const filter of <FilterConfigJson[]>predifined_filters.filter) {
|
|
||||||
filters.set(filter.id, filter)
|
|
||||||
}
|
|
||||||
return filters
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly predefinedFilters = ExpandFilter.load_filters()
|
private static readonly predefinedFilters = ExpandFilter.load_filters()
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -40,6 +35,14 @@ class ExpandFilter extends DesugaringStep<LayerConfigJson> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static load_filters(): Map<string, FilterConfigJson> {
|
||||||
|
let filters = new Map<string, FilterConfigJson>()
|
||||||
|
for (const filter of <FilterConfigJson[]>predifined_filters.filter) {
|
||||||
|
filters.set(filter.id, filter)
|
||||||
|
}
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
convert(
|
convert(
|
||||||
json: LayerConfigJson,
|
json: LayerConfigJson,
|
||||||
context: string
|
context: string
|
||||||
|
@ -128,6 +131,37 @@ class ExpandTagRendering extends Conversion<
|
||||||
}
|
}
|
||||||
|
|
||||||
private lookup(name: string): TagRenderingConfigJson[] {
|
private lookup(name: string): TagRenderingConfigJson[] {
|
||||||
|
const direct = this.directLookup(name)
|
||||||
|
if (direct === undefined) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const result: TagRenderingConfigJson[] = []
|
||||||
|
for (const tagRenderingConfigJson of direct) {
|
||||||
|
if (tagRenderingConfigJson["builtin"] !== undefined) {
|
||||||
|
let nm: string | string[] = tagRenderingConfigJson["builtin"]
|
||||||
|
let indirect: TagRenderingConfigJson[]
|
||||||
|
if (typeof nm === "string") {
|
||||||
|
indirect = this.lookup(nm)
|
||||||
|
} else {
|
||||||
|
indirect = [].concat(...nm.map((n) => this.lookup(n)))
|
||||||
|
}
|
||||||
|
for (let foundTr of indirect) {
|
||||||
|
foundTr = Utils.Clone<any>(foundTr)
|
||||||
|
Utils.Merge(tagRenderingConfigJson["override"] ?? {}, foundTr)
|
||||||
|
foundTr.id = tagRenderingConfigJson.id ?? foundTr.id
|
||||||
|
result.push(foundTr)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push(tagRenderingConfigJson)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up a tagRendering based on the name.
|
||||||
|
*/
|
||||||
|
private directLookup(name: string): TagRenderingConfigJson[] {
|
||||||
const state = this._state
|
const state = this._state
|
||||||
if (state.tagRenderings.has(name)) {
|
if (state.tagRenderings.has(name)) {
|
||||||
return [state.tagRenderings.get(name)]
|
return [state.tagRenderings.get(name)]
|
||||||
|
@ -747,6 +781,79 @@ export class RewriteSpecial extends DesugaringStep<TagRenderingConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExpandIconBadges extends DesugaringStep<PointRenderingConfigJson | LineRenderingConfigJson> {
|
||||||
|
private _state: DesugaringContext
|
||||||
|
private _layer: LayerConfigJson
|
||||||
|
private _expand: ExpandTagRendering
|
||||||
|
|
||||||
|
constructor(state: DesugaringContext, layer: LayerConfigJson) {
|
||||||
|
super("Expands shorthand properties on iconBadges", ["iconBadges"], "ExpandIconBadges")
|
||||||
|
this._state = state
|
||||||
|
this._layer = layer
|
||||||
|
this._expand = new ExpandTagRendering(state, layer)
|
||||||
|
}
|
||||||
|
|
||||||
|
convert(
|
||||||
|
json: PointRenderingConfigJson | LineRenderingConfigJson,
|
||||||
|
context: string
|
||||||
|
): {
|
||||||
|
result: PointRenderingConfigJson | LineRenderingConfigJson
|
||||||
|
errors?: string[]
|
||||||
|
warnings?: string[]
|
||||||
|
information?: string[]
|
||||||
|
} {
|
||||||
|
if (!json["iconBadges"]) {
|
||||||
|
return { result: json }
|
||||||
|
}
|
||||||
|
const badgesJson = (<PointRenderingConfigJson>json).iconBadges
|
||||||
|
|
||||||
|
const iconBadges: { if: TagConfigJson; then: string | TagRenderingConfigJson }[] = []
|
||||||
|
|
||||||
|
const errs: string[] = []
|
||||||
|
const warns: string[] = []
|
||||||
|
for (let i = 0; i < badgesJson.length; i++) {
|
||||||
|
const iconBadge: { if: TagConfigJson; then: string | TagRenderingConfigJson } =
|
||||||
|
badgesJson[i]
|
||||||
|
const { errors, result, warnings } = this._expand.convert(
|
||||||
|
iconBadge.then,
|
||||||
|
context + ".iconBadges[" + i + "]"
|
||||||
|
)
|
||||||
|
errs.push(...errors)
|
||||||
|
warns.push(...warnings)
|
||||||
|
if (result === undefined) {
|
||||||
|
iconBadges.push(iconBadge)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
iconBadges.push(
|
||||||
|
...result.map((resolved) => ({
|
||||||
|
if: iconBadge.if,
|
||||||
|
then: resolved,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
result: { ...json, iconBadges },
|
||||||
|
errors: errs,
|
||||||
|
warnings: warns,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreparePointRendering extends Fuse<PointRenderingConfigJson | LineRenderingConfigJson> {
|
||||||
|
constructor(state: DesugaringContext, layer: LayerConfigJson) {
|
||||||
|
super(
|
||||||
|
"Prepares point renderings by expanding 'icon' and 'iconBadges'",
|
||||||
|
new On(
|
||||||
|
"icon",
|
||||||
|
new FirstOf(new ExpandTagRendering(state, layer, { applyCondition: false }))
|
||||||
|
),
|
||||||
|
new ExpandIconBadges(state, layer)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class PrepareLayer extends Fuse<LayerConfigJson> {
|
export class PrepareLayer extends Fuse<LayerConfigJson> {
|
||||||
constructor(state: DesugaringContext) {
|
constructor(state: DesugaringContext) {
|
||||||
super(
|
super(
|
||||||
|
@ -755,19 +862,11 @@ export class PrepareLayer extends Fuse<LayerConfigJson> {
|
||||||
new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
new On("tagRenderings", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
||||||
new On("tagRenderings", (layer) => new Concat(new ExpandTagRendering(state, layer))),
|
new On("tagRenderings", (layer) => new Concat(new ExpandTagRendering(state, layer))),
|
||||||
new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
new On("mapRendering", new Concat(new ExpandRewrite()).andThenF(Utils.Flatten)),
|
||||||
new On(
|
new On<(PointRenderingConfigJson | LineRenderingConfigJson)[], LayerConfigJson>(
|
||||||
"mapRendering",
|
"mapRendering",
|
||||||
(layer) =>
|
(layer) => new Each(new PreparePointRendering(state, layer))
|
||||||
new Each(
|
|
||||||
new On(
|
|
||||||
"icon",
|
|
||||||
new FirstOf(
|
|
||||||
new ExpandTagRendering(state, layer, { applyCondition: false })
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
new SetDefault("titleIcons", ["defaults"]),
|
new SetDefault("titleIcons", ["icons.defaults"]),
|
||||||
new On("titleIcons", (layer) => new Concat(new ExpandTagRendering(state, layer))),
|
new On("titleIcons", (layer) => new Concat(new ExpandTagRendering(state, layer))),
|
||||||
new ExpandFilter()
|
new ExpandFilter()
|
||||||
)
|
)
|
||||||
|
|
|
@ -59,13 +59,16 @@ class ValidateLanguageCompleteness extends DesugaringStep<any> {
|
||||||
|
|
||||||
export class DoesImageExist extends DesugaringStep<string> {
|
export class DoesImageExist extends DesugaringStep<string> {
|
||||||
private readonly _knownImagePaths: Set<string>
|
private readonly _knownImagePaths: Set<string>
|
||||||
|
private readonly _ignore?: Set<string>
|
||||||
private readonly doesPathExist: (path: string) => boolean = undefined
|
private readonly doesPathExist: (path: string) => boolean = undefined
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
knownImagePaths: Set<string>,
|
knownImagePaths: Set<string>,
|
||||||
checkExistsSync: (path: string) => boolean = undefined
|
checkExistsSync: (path: string) => boolean = undefined,
|
||||||
|
ignore?: Set<string>
|
||||||
) {
|
) {
|
||||||
super("Checks if an image exists", [], "DoesImageExist")
|
super("Checks if an image exists", [], "DoesImageExist")
|
||||||
|
this._ignore = ignore
|
||||||
this._knownImagePaths = knownImagePaths
|
this._knownImagePaths = knownImagePaths
|
||||||
this.doesPathExist = checkExistsSync
|
this.doesPathExist = checkExistsSync
|
||||||
}
|
}
|
||||||
|
@ -74,6 +77,10 @@ export class DoesImageExist extends DesugaringStep<string> {
|
||||||
image: string,
|
image: string,
|
||||||
context: string
|
context: string
|
||||||
): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } {
|
): { result: string; errors?: string[]; warnings?: string[]; information?: string[] } {
|
||||||
|
if (this._ignore?.has(image)) {
|
||||||
|
return { result: image }
|
||||||
|
}
|
||||||
|
|
||||||
const errors = []
|
const errors = []
|
||||||
const warnings = []
|
const warnings = []
|
||||||
const information = []
|
const information = []
|
||||||
|
@ -123,20 +130,23 @@ class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
*/
|
*/
|
||||||
private readonly _path?: string
|
private readonly _path?: string
|
||||||
private readonly _isBuiltin: boolean
|
private readonly _isBuiltin: boolean
|
||||||
private _sharedTagRenderings: Map<string, any>
|
//private readonly _sharedTagRenderings: Map<string, any>
|
||||||
private readonly _validateImage: DesugaringStep<string>
|
private readonly _validateImage: DesugaringStep<string>
|
||||||
|
private readonly _extractImages: ExtractImages = undefined
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
doesImageExist: DoesImageExist,
|
doesImageExist: DoesImageExist,
|
||||||
path: string,
|
path: string,
|
||||||
isBuiltin: boolean,
|
isBuiltin: boolean,
|
||||||
sharedTagRenderings: Map<string, any>
|
sharedTagRenderings?: Set<string>
|
||||||
) {
|
) {
|
||||||
super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme")
|
super("Doesn't change anything, but emits warnings and errors", [], "ValidateTheme")
|
||||||
this._validateImage = doesImageExist
|
this._validateImage = doesImageExist
|
||||||
this._path = path
|
this._path = path
|
||||||
this._isBuiltin = isBuiltin
|
this._isBuiltin = isBuiltin
|
||||||
this._sharedTagRenderings = sharedTagRenderings
|
if (sharedTagRenderings) {
|
||||||
|
this._extractImages = new ExtractImages(this._isBuiltin, sharedTagRenderings)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
convert(
|
convert(
|
||||||
|
@ -168,13 +178,10 @@ class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this._isBuiltin) {
|
if (this._isBuiltin && this._extractImages !== undefined) {
|
||||||
// Check images: are they local, are the licenses there, is the theme icon square, ...
|
// Check images: are they local, are the licenses there, is the theme icon square, ...
|
||||||
const images = new ExtractImages(
|
const images = this._extractImages.convertStrict(json, "validation")
|
||||||
this._isBuiltin,
|
const remoteImages = images.filter((img) => img.path.indexOf("http") == 0)
|
||||||
this._sharedTagRenderings
|
|
||||||
).convertStrict(json, "validation")
|
|
||||||
const remoteImages = images.filter((img) => img.indexOf("http") == 0)
|
|
||||||
for (const remoteImage of remoteImages) {
|
for (const remoteImage of remoteImages) {
|
||||||
errors.push(
|
errors.push(
|
||||||
"Found a remote image: " +
|
"Found a remote image: " +
|
||||||
|
@ -186,8 +193,8 @@ class ValidateTheme extends DesugaringStep<LayoutConfigJson> {
|
||||||
}
|
}
|
||||||
for (const image of images) {
|
for (const image of images) {
|
||||||
this._validateImage.convertJoin(
|
this._validateImage.convertJoin(
|
||||||
image,
|
image.path,
|
||||||
context === undefined ? "" : ` in a layer defined in the theme ${context}`,
|
context === undefined ? "" : ` in the theme ${context} at ${image.context}`,
|
||||||
errors,
|
errors,
|
||||||
warnings,
|
warnings,
|
||||||
information
|
information
|
||||||
|
@ -267,7 +274,7 @@ export class ValidateThemeAndLayers extends Fuse<LayoutConfigJson> {
|
||||||
doesImageExist: DoesImageExist,
|
doesImageExist: DoesImageExist,
|
||||||
path: string,
|
path: string,
|
||||||
isBuiltin: boolean,
|
isBuiltin: boolean,
|
||||||
sharedTagRenderings: Map<string, any>
|
sharedTagRenderings?: Set<string>
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
"Validates a theme and the contained layers",
|
"Validates a theme and the contained layers",
|
||||||
|
@ -878,53 +885,6 @@ export class DetectDuplicateFilters extends DesugaringStep<{
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all filter options into 'perOsmTag'
|
|
||||||
*/
|
|
||||||
private addLayerFilters(
|
|
||||||
layer: LayerConfigJson,
|
|
||||||
perOsmTag: Map<
|
|
||||||
string,
|
|
||||||
{
|
|
||||||
layer: LayerConfigJson
|
|
||||||
layout: LayoutConfigJson | undefined
|
|
||||||
filter: FilterConfigJson
|
|
||||||
}[]
|
|
||||||
>,
|
|
||||||
layout?: LayoutConfigJson | undefined
|
|
||||||
): void {
|
|
||||||
if (layer.filter === undefined || layer.filter === null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (layer.filter["sameAs"] !== undefined) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for (const filter of <(string | FilterConfigJson)[]>layer.filter) {
|
|
||||||
if (typeof filter === "string") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter["#"]?.indexOf("ignore-possible-duplicate") >= 0) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const option of filter.options) {
|
|
||||||
if (option.osmTags === undefined) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const key = JSON.stringify(option.osmTags)
|
|
||||||
if (!perOsmTag.has(key)) {
|
|
||||||
perOsmTag.set(key, [])
|
|
||||||
}
|
|
||||||
perOsmTag.get(key).push({
|
|
||||||
layer,
|
|
||||||
filter,
|
|
||||||
layout,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
convert(
|
convert(
|
||||||
json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] },
|
json: { layers: LayerConfigJson[]; themes: LayoutConfigJson[] },
|
||||||
context: string
|
context: string
|
||||||
|
@ -991,4 +951,51 @@ export class DetectDuplicateFilters extends DesugaringStep<{
|
||||||
information,
|
information,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all filter options into 'perOsmTag'
|
||||||
|
*/
|
||||||
|
private addLayerFilters(
|
||||||
|
layer: LayerConfigJson,
|
||||||
|
perOsmTag: Map<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
layer: LayerConfigJson
|
||||||
|
layout: LayoutConfigJson | undefined
|
||||||
|
filter: FilterConfigJson
|
||||||
|
}[]
|
||||||
|
>,
|
||||||
|
layout?: LayoutConfigJson | undefined
|
||||||
|
): void {
|
||||||
|
if (layer.filter === undefined || layer.filter === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (layer.filter["sameAs"] !== undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (const filter of <(string | FilterConfigJson)[]>layer.filter) {
|
||||||
|
if (typeof filter === "string") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter["#"]?.indexOf("ignore-possible-duplicate") >= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const option of filter.options) {
|
||||||
|
if (option.osmTags === undefined) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const key = JSON.stringify(option.osmTags)
|
||||||
|
if (!perOsmTag.has(key)) {
|
||||||
|
perOsmTag.set(key, [])
|
||||||
|
}
|
||||||
|
perOsmTag.get(key).push({
|
||||||
|
layer,
|
||||||
|
filter,
|
||||||
|
layout,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,10 +82,12 @@ export default class LayoutConfig {
|
||||||
this.credits = json.credits
|
this.credits = json.credits
|
||||||
this.language = json.mustHaveLanguage ?? Object.keys(json.title)
|
this.language = json.mustHaveLanguage ?? Object.keys(json.title)
|
||||||
this.usedImages = Array.from(
|
this.usedImages = Array.from(
|
||||||
new ExtractImages(official, undefined).convertStrict(
|
new ExtractImages(official, undefined)
|
||||||
json,
|
.convertStrict(
|
||||||
"while extracting the images of " + json.id + " " + context ?? ""
|
json,
|
||||||
)
|
"while extracting the images of " + json.id + " " + context ?? ""
|
||||||
|
)
|
||||||
|
.map((i) => i.path)
|
||||||
).sort()
|
).sort()
|
||||||
{
|
{
|
||||||
if (typeof json.title === "string") {
|
if (typeof json.title === "string") {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import PointRenderingConfigJson from "./Json/PointRenderingConfigJson"
|
import PointRenderingConfigJson from "./Json/PointRenderingConfigJson"
|
||||||
import TagRenderingConfig from "./TagRenderingConfig"
|
import TagRenderingConfig from "./TagRenderingConfig"
|
||||||
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
|
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
|
||||||
import SharedTagRenderings from "../../Customizations/SharedTagRenderings"
|
|
||||||
import { TagUtils } from "../../Logic/Tags/TagUtils"
|
import { TagUtils } from "../../Logic/Tags/TagUtils"
|
||||||
import { Utils } from "../../Utils"
|
import { Utils } from "../../Utils"
|
||||||
import Svg from "../../Svg"
|
import Svg from "../../Svg"
|
||||||
|
@ -72,18 +71,9 @@ export default class PointRenderingConfig extends WithContextLoader {
|
||||||
}
|
}
|
||||||
this.cssClasses = this.tr("cssClasses", undefined)
|
this.cssClasses = this.tr("cssClasses", undefined)
|
||||||
this.iconBadges = (json.iconBadges ?? []).map((overlay, i) => {
|
this.iconBadges = (json.iconBadges ?? []).map((overlay, i) => {
|
||||||
let tr: TagRenderingConfig
|
|
||||||
if (
|
|
||||||
typeof overlay.then === "string" &&
|
|
||||||
SharedTagRenderings.SharedIcons.get(overlay.then) !== undefined
|
|
||||||
) {
|
|
||||||
tr = SharedTagRenderings.SharedIcons.get(overlay.then)
|
|
||||||
} else {
|
|
||||||
tr = new TagRenderingConfig(overlay.then, `iconBadges.${i}`)
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
if: TagUtils.Tag(overlay.if),
|
if: TagUtils.Tag(overlay.if),
|
||||||
then: tr,
|
then: new TagRenderingConfig(overlay.then, `iconBadges.${i}`),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
"generate:service-worker": "tsc service-worker.ts && git_hash=$(git rev-parse HEAD) && sed -i'.bkp' \"s/GITHUB-COMMIT/$git_hash/\" service-worker.js && rm service-worker.js.bkp",
|
"generate:service-worker": "tsc service-worker.ts && git_hash=$(git rev-parse HEAD) && sed -i'.bkp' \"s/GITHUB-COMMIT/$git_hash/\" service-worker.js && rm service-worker.js.bkp",
|
||||||
"optimize-images": "cd assets/generated/ && find -name '*.png' -exec optipng '{}' \\; && echo 'PNGs are optimized'",
|
"optimize-images": "cd assets/generated/ && find -name '*.png' -exec optipng '{}' \\; && echo 'PNGs are optimized'",
|
||||||
"generate:stats": "vite-node scripts/GenerateSeries.ts",
|
"generate:stats": "vite-node scripts/GenerateSeries.ts",
|
||||||
"reset:layeroverview": "echo {\\\"layers\\\":[], \\\"themes\\\":[]} > ./assets/generated/known_layers_and_themes.json && echo {\\\"layers\\\": []} > ./assets/generated/known_layers.json && rm -f ./assets/generated/layers/*.json && rm -f ./assets/generated/themes/*.json && npm run generate:layeroverview && vite-node scripts/generateLayerOverview.ts --force",
|
"reset:layeroverview": "echo {\\\"layers\\\":[], \\\"themes\\\":[]} > ./assets/generated/known_layers_and_themes.json && echo {\\\"layers\\\": []} > ./assets/generated/known_layers.json && rm -f ./assets/generated/layers/*.json && rm -f ./assets/generated/themes/*.json && npm run generate:layeroverview && vite-node scripts/generateLayerOverview.ts -- --force",
|
||||||
"generate": "mkdir -p ./assets/generated; npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:translations; npm run reset:layeroverview; npm run generate:service-worker",
|
"generate": "mkdir -p ./assets/generated; npm run generate:licenses; npm run generate:images; npm run generate:charging-stations; npm run generate:translations; npm run reset:layeroverview; npm run generate:service-worker",
|
||||||
"generate:charging-stations": "cd ./assets/layers/charging_station && vite-node csvToJson.ts && cd -",
|
"generate:charging-stations": "cd ./assets/layers/charging_station && vite-node csvToJson.ts && cd -",
|
||||||
"prepare-deploy": "npm run generate:service-worker && ./scripts/build.sh",
|
"prepare-deploy": "npm run generate:service-worker && ./scripts/build.sh",
|
||||||
|
|
|
@ -15,7 +15,6 @@ import {
|
||||||
import { Translation } from "../UI/i18n/Translation"
|
import { Translation } from "../UI/i18n/Translation"
|
||||||
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"
|
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"
|
||||||
import questions from "../assets/tagRenderings/questions.json"
|
import questions from "../assets/tagRenderings/questions.json"
|
||||||
import icons from "../assets/tagRenderings/icons.json"
|
|
||||||
import PointRenderingConfigJson from "../Models/ThemeConfig/Json/PointRenderingConfigJson"
|
import PointRenderingConfigJson from "../Models/ThemeConfig/Json/PointRenderingConfigJson"
|
||||||
import { PrepareLayer } from "../Models/ThemeConfig/Conversion/PrepareLayer"
|
import { PrepareLayer } from "../Models/ThemeConfig/Conversion/PrepareLayer"
|
||||||
import { PrepareTheme } from "../Models/ThemeConfig/Conversion/PrepareTheme"
|
import { PrepareTheme } from "../Models/ThemeConfig/Conversion/PrepareTheme"
|
||||||
|
@ -167,21 +166,6 @@ class LayerOverviewUtils {
|
||||||
)
|
)
|
||||||
dict.set(key, config)
|
dict.set(key, config)
|
||||||
}
|
}
|
||||||
for (const key in icons) {
|
|
||||||
if (key === "id") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (typeof icons[key] !== "object") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
icons[key].id = key
|
|
||||||
const config = <TagRenderingConfigJson>icons[key]
|
|
||||||
validator.convertStrict(
|
|
||||||
config,
|
|
||||||
"generate-layer-overview:tagRenderings/icons.json:" + key
|
|
||||||
)
|
|
||||||
dict.set(key, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
dict.forEach((value, key) => {
|
dict.forEach((value, key) => {
|
||||||
if (key === "id") {
|
if (key === "id") {
|
||||||
|
@ -251,7 +235,7 @@ class LayerOverviewUtils {
|
||||||
const sharedLayers = this.buildLayerIndex(doesImageExist, forceReload)
|
const sharedLayers = this.buildLayerIndex(doesImageExist, forceReload)
|
||||||
const recompiledThemes: string[] = []
|
const recompiledThemes: string[] = []
|
||||||
const sharedThemes = this.buildThemeIndex(
|
const sharedThemes = this.buildThemeIndex(
|
||||||
doesImageExist,
|
licensePaths,
|
||||||
sharedLayers,
|
sharedLayers,
|
||||||
recompiledThemes,
|
recompiledThemes,
|
||||||
forceReload
|
forceReload
|
||||||
|
@ -381,7 +365,7 @@ class LayerOverviewUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildThemeIndex(
|
private buildThemeIndex(
|
||||||
doesImageExist: DoesImageExist,
|
licensePaths: Set<string>,
|
||||||
sharedLayers: Map<string, LayerConfigJson>,
|
sharedLayers: Map<string, LayerConfigJson>,
|
||||||
recompiledThemes: string[],
|
recompiledThemes: string[],
|
||||||
forceReload: boolean
|
forceReload: boolean
|
||||||
|
@ -396,9 +380,26 @@ class LayerOverviewUtils {
|
||||||
|
|
||||||
const convertState: DesugaringContext = {
|
const convertState: DesugaringContext = {
|
||||||
sharedLayers,
|
sharedLayers,
|
||||||
tagRenderings: this.getSharedTagRenderings(doesImageExist),
|
tagRenderings: this.getSharedTagRenderings(
|
||||||
|
new DoesImageExist(licensePaths, existsSync)
|
||||||
|
),
|
||||||
publicLayers,
|
publicLayers,
|
||||||
}
|
}
|
||||||
|
const knownTagRenderings = new Set<string>()
|
||||||
|
convertState.tagRenderings.forEach((_, key) => knownTagRenderings.add(key))
|
||||||
|
sharedLayers.forEach((layer) => {
|
||||||
|
for (const tagRendering of layer.tagRenderings ?? []) {
|
||||||
|
if (tagRendering["id"]) {
|
||||||
|
knownTagRenderings.add(layer.id + "." + tagRendering["id"])
|
||||||
|
}
|
||||||
|
if (tagRendering["labels"]) {
|
||||||
|
for (const label of tagRendering["labels"]) {
|
||||||
|
knownTagRenderings.add(layer.id + "." + label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const skippedThemes: string[] = []
|
const skippedThemes: string[] = []
|
||||||
for (const themeInfo of themeFiles) {
|
for (const themeInfo of themeFiles) {
|
||||||
const themePath = themeInfo.path
|
const themePath = themeInfo.path
|
||||||
|
@ -433,10 +434,10 @@ class LayerOverviewUtils {
|
||||||
themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath)
|
themeFile = new PrepareTheme(convertState).convertStrict(themeFile, themePath)
|
||||||
|
|
||||||
new ValidateThemeAndLayers(
|
new ValidateThemeAndLayers(
|
||||||
doesImageExist,
|
new DoesImageExist(licensePaths, existsSync, knownTagRenderings),
|
||||||
themePath,
|
themePath,
|
||||||
true,
|
true,
|
||||||
convertState.tagRenderings
|
knownTagRenderings
|
||||||
).convertStrict(themeFile, themePath)
|
).convertStrict(themeFile, themePath)
|
||||||
|
|
||||||
if (themeFile.icon.endsWith(".svg")) {
|
if (themeFile.icon.endsWith(".svg")) {
|
||||||
|
|
|
@ -143,7 +143,7 @@ describe("PrepareTheme", () => {
|
||||||
describe("ExtractImages", () => {
|
describe("ExtractImages", () => {
|
||||||
it("should find all images in a themefile", () => {
|
it("should find all images in a themefile", () => {
|
||||||
const images = new Set(
|
const images = new Set(
|
||||||
new ExtractImages(true, new Map<string, any>()).convertStrict(<any>cyclofix, "test")
|
new ExtractImages(true, new Set<string>()).convertStrict(<any>cyclofix, "test")
|
||||||
)
|
)
|
||||||
const expectedValues = [
|
const expectedValues = [
|
||||||
"./assets/layers/bike_repair_station/repair_station.svg",
|
"./assets/layers/bike_repair_station/repair_station.svg",
|
||||||
|
|
Loading…
Reference in a new issue