Fix: actually search for keywords in theme view

This commit is contained in:
Pieter Vander Vennet 2024-08-27 21:33:47 +02:00
parent 821c1fabd7
commit cdc1e05499
9 changed files with 193 additions and 95 deletions

View file

@ -34,6 +34,10 @@ import Translations from "../src/UI/i18n/Translations"
import { Translatable } from "../src/Models/ThemeConfig/Json/Translatable"
import { ValidateThemeAndLayers } from "../src/Models/ThemeConfig/Conversion/ValidateThemeAndLayers"
import { ExtractImages } from "../src/Models/ThemeConfig/Conversion/FixImages"
import {
MinimalTagRenderingConfigJson,
TagRenderingConfigJson,
} from "../src/Models/ThemeConfig/Json/TagRenderingConfigJson"
// This scripts scans 'src/assets/layers/*.json' for layer definition files and 'src/assets/themes/*.json' for theme definition files.
// It spits out an overview of those to be used to load them
@ -56,7 +60,7 @@ class ParseLayer extends Conversion<
convert(
path: string,
context: ConversionContext
context: ConversionContext,
): {
parsed: LayerConfig
raw: LayerConfigJson
@ -85,7 +89,7 @@ class ParseLayer extends Conversion<
context
.enter("source")
.err(
"No source is configured. (Tags might be automatically derived if presets are given)"
"No source is configured. (Tags might be automatically derived if presets are given)",
)
return undefined
}
@ -116,7 +120,7 @@ class AddIconSummary extends DesugaringStep<{ raw: LayerConfigJson; parsed: Laye
const fixed = json.raw
const layerConfig = json.parsed
const pointRendering: PointRenderingConfig = layerConfig.mapRendering.find((pr) =>
pr.location.has("point")
pr.location.has("point"),
)
const defaultTags = layerConfig.GetBaseTags()
fixed["_layerIcon"] = Utils.NoNull(
@ -131,7 +135,7 @@ class AddIconSummary extends DesugaringStep<{ raw: LayerConfigJson; parsed: Laye
result["color"] = c
}
return result
})
}),
)
return { raw: fixed, parsed: layerConfig }
}
@ -153,7 +157,7 @@ class LayerOverviewUtils extends Script {
private static extractLayerIdsFrom(
themeFile: LayoutConfigJson,
includeInlineLayers = true
includeInlineLayers = true,
): string[] {
const publicLayerIds: string[] = []
if (!Array.isArray(themeFile.layers)) {
@ -220,19 +224,63 @@ class LayerOverviewUtils extends Script {
| LayerConfigJson
| string
| {
builtin
}
)[]
}[]
builtin
}
)[]
}[],
) {
const perId = new Map<string, any>()
for (const theme of themes) {
const keywords: {}[] = []
const keywords: Record<string, string[]> = {}
function addWord(language: string, word: string | string[]) {
if(Array.isArray(word)){
word.forEach(w => addWord(language, w))
return
}
word = Utils.SubstituteKeys(word, {}).trim()
if(!word){
return
}
console.log(language, "--->", word)
if (!keywords[language]) {
keywords[language] = []
}
keywords[language].push(word)
}
function addWords(tr: string | Record<string, string> | Record<string, string[]> | TagRenderingConfigJson) {
if(!tr){
return
}
if (typeof tr === "string") {
addWord("*", tr)
return
}
if (tr["render"] !== undefined || tr["mappings"] !== undefined) {
tr = <TagRenderingConfigJson>tr
addWords(<Translatable>tr.render)
for (let mapping of tr.mappings ?? []) {
if (typeof mapping === "string") {
addWords(mapping)
continue
}
addWords(mapping.then)
}
return
}
for (const lang in tr) {
addWord(lang, tr[lang])
}
}
for (const layer of theme.layers ?? []) {
const l = <LayerConfigJson>layer
keywords.push({ "*": l.id })
keywords.push(l.title)
keywords.push(l.description)
addWord("*", l.id)
addWords(l.title)
addWords(l.description)
addWords(l.searchTerms)
}
const data = {
@ -242,7 +290,7 @@ class LayerOverviewUtils extends Script {
icon: theme.icon,
hideFromOverview: theme.hideFromOverview,
mustHaveLanguage: theme.mustHaveLanguage,
keywords: Utils.NoNull(keywords),
keywords,
}
perId.set(theme.id, data)
}
@ -264,7 +312,7 @@ class LayerOverviewUtils extends Script {
writeFileSync(
"./src/assets/generated/theme_overview.json",
JSON.stringify(sorted, null, " "),
{ encoding: "utf8" }
{ encoding: "utf8" },
)
}
@ -276,7 +324,7 @@ class LayerOverviewUtils extends Script {
writeFileSync(
`${LayerOverviewUtils.themePath}${theme.id}.json`,
JSON.stringify(theme, null, " "),
{ encoding: "utf8" }
{ encoding: "utf8" },
)
}
@ -287,12 +335,12 @@ class LayerOverviewUtils extends Script {
writeFileSync(
`${LayerOverviewUtils.layerPath}${layer.id}.json`,
JSON.stringify(layer, null, " "),
{ encoding: "utf8" }
{ encoding: "utf8" },
)
}
static asDict(
trs: QuestionableTagRenderingConfigJson[]
trs: QuestionableTagRenderingConfigJson[],
): Map<string, QuestionableTagRenderingConfigJson> {
const d = new Map<string, QuestionableTagRenderingConfigJson>()
for (const tr of trs) {
@ -305,12 +353,12 @@ class LayerOverviewUtils extends Script {
getSharedTagRenderings(
doesImageExist: DoesImageExist,
bootstrapTagRenderings: Map<string, QuestionableTagRenderingConfigJson>,
bootstrapTagRenderingsOrder: string[]
bootstrapTagRenderingsOrder: string[],
): QuestionableTagRenderingConfigJson[]
getSharedTagRenderings(
doesImageExist: DoesImageExist,
bootstrapTagRenderings: Map<string, QuestionableTagRenderingConfigJson> = null,
bootstrapTagRenderingsOrder: string[] = []
bootstrapTagRenderingsOrder: string[] = [],
): QuestionableTagRenderingConfigJson[] {
const prepareLayer = new PrepareLayer(
{
@ -321,7 +369,7 @@ class LayerOverviewUtils extends Script {
},
{
addTagRenderingsToContext: true,
}
},
)
const path = "assets/layers/questions/questions.json"
@ -341,7 +389,7 @@ class LayerOverviewUtils extends Script {
return this.getSharedTagRenderings(
doesImageExist,
dict,
sharedQuestions.tagRenderings.map((tr) => tr["id"])
sharedQuestions.tagRenderings.map((tr) => tr["id"]),
)
}
@ -381,8 +429,8 @@ class LayerOverviewUtils extends Script {
if (contents.indexOf("<text") > 0) {
console.warn(
"The SVG at " +
path +
" contains a `text`-tag. This is highly discouraged. Every machine viewing your theme has their own font libary, and the font you choose might not be present, resulting in a different font being rendered. Solution: open your .svg in inkscape (or another program), select the text and convert it to a path"
path +
" contains a `text`-tag. This is highly discouraged. Every machine viewing your theme has their own font libary, and the font you choose might not be present, resulting in a different font being rendered. Solution: open your .svg in inkscape (or another program), select the text and convert it to a path",
)
errCount++
}
@ -398,14 +446,14 @@ class LayerOverviewUtils extends Script {
args
.find((a) => a.startsWith("--themes="))
?.substring("--themes=".length)
?.split(",") ?? []
?.split(",") ?? [],
)
const layerWhitelist = new Set(
args
.find((a) => a.startsWith("--layers="))
?.substring("--layers=".length)
?.split(",") ?? []
?.split(",") ?? [],
)
const forceReload = args.some((a) => a == "--force")
@ -440,11 +488,11 @@ class LayerOverviewUtils extends Script {
sharedLayers,
recompiledThemes,
forceReload,
themeWhitelist
themeWhitelist,
)
new ValidateThemeEnsemble().convertStrict(
Array.from(sharedThemes.values()).map((th) => new LayoutConfig(th, true))
Array.from(sharedThemes.values()).map((th) => new LayoutConfig(th, true)),
)
if (recompiledThemes.length > 0) {
@ -452,7 +500,7 @@ class LayerOverviewUtils extends Script {
"./src/assets/generated/known_layers.json",
JSON.stringify({
layers: Array.from(sharedLayers.values()).filter((l) => l.id !== "favourite"),
})
}),
)
}
@ -473,7 +521,7 @@ class LayerOverviewUtils extends Script {
const proto: LayoutConfigJson = JSON.parse(
readFileSync("./assets/themes/mapcomplete-changes/mapcomplete-changes.proto.json", {
encoding: "utf8",
})
}),
)
const protolayer = <LayerConfigJson>(
proto.layers.filter((l) => l["id"] === "mapcomplete-changes")[0]
@ -490,12 +538,12 @@ class LayerOverviewUtils extends Script {
layers: ScriptUtils.getLayerFiles().map((f) => f.parsed),
themes: ScriptUtils.getThemeFiles().map((f) => f.parsed),
},
ConversionContext.construct([], [])
ConversionContext.construct([], []),
)
for (const [_, theme] of sharedThemes) {
theme.layers = theme.layers.filter(
(l) => Constants.added_by_default.indexOf(l["id"]) < 0
(l) => Constants.added_by_default.indexOf(l["id"]) < 0,
)
}
@ -504,7 +552,7 @@ class LayerOverviewUtils extends Script {
"./src/assets/generated/known_themes.json",
JSON.stringify({
themes: Array.from(sharedThemes.values()),
})
}),
)
}
@ -516,7 +564,7 @@ class LayerOverviewUtils extends Script {
private parseLayer(
doesImageExist: DoesImageExist,
prepLayer: PrepareLayer,
sharedLayerPath: string
sharedLayerPath: string,
): {
raw: LayerConfigJson
parsed: LayerConfig
@ -527,7 +575,7 @@ class LayerOverviewUtils extends Script {
const parsed = parser.convertStrict(sharedLayerPath, context)
const result = AddIconSummary.singleton.convertStrict(
parsed,
context.inOperation("AddIconSummary")
context.inOperation("AddIconSummary"),
)
return { ...result, context }
}
@ -535,7 +583,7 @@ class LayerOverviewUtils extends Script {
private buildLayerIndex(
doesImageExist: DoesImageExist,
forceReload: boolean,
whitelist: Set<string>
whitelist: Set<string>,
): Map<string, LayerConfigJson> {
// First, we expand and validate all builtin layers. These are written to src/assets/generated/layers
// At the same time, an index of available layers is built.
@ -590,17 +638,17 @@ class LayerOverviewUtils extends Script {
console.log(
"Recompiled layers " +
recompiledLayers.join(", ") +
" and skipped " +
skippedLayers.length +
" layers. Detected " +
warningCount +
" warnings"
recompiledLayers.join(", ") +
" and skipped " +
skippedLayers.length +
" layers. Detected " +
warningCount +
" warnings",
)
// We always need the calculated tags of 'usersettings', so we export them separately
this.extractJavascriptCodeForLayer(
state.sharedLayers.get("usersettings"),
"./src/Logic/State/UserSettingsMetaTagging.ts"
"./src/Logic/State/UserSettingsMetaTagging.ts",
)
return sharedLayers
@ -617,8 +665,8 @@ class LayerOverviewUtils extends Script {
private extractJavascriptCode(themeFile: LayoutConfigJson) {
const allCode = [
"import {Feature} from 'geojson'",
'import { ExtraFuncType } from "../../../Logic/ExtraFunctions";',
'import { Utils } from "../../../Utils"',
"import { ExtraFuncType } from \"../../../Logic/ExtraFunctions\";",
"import { Utils } from \"../../../Utils\"",
"export class ThemeMetaTagging {",
" public static readonly themeName = " + JSON.stringify(themeFile.id),
"",
@ -630,8 +678,8 @@ class LayerOverviewUtils extends Script {
allCode.push(
" public metaTaggging_for_" +
id +
"(feat: Feature, helperFunctions: Record<ExtraFuncType, (feature: Feature) => Function>) {"
id +
"(feat: Feature, helperFunctions: Record<ExtraFuncType, (feature: Feature) => Function>) {",
)
allCode.push(" const {" + ExtraFunctions.types.join(", ") + "} = helperFunctions")
for (const line of code) {
@ -642,10 +690,10 @@ class LayerOverviewUtils extends Script {
if (!isStrict) {
allCode.push(
" Utils.AddLazyProperty(feat.properties, '" +
attributeName +
"', () => " +
expression +
" ) "
attributeName +
"', () => " +
expression +
" ) ",
)
} else {
attributeName = attributeName.substring(0, attributeName.length - 1).trim()
@ -690,7 +738,7 @@ class LayerOverviewUtils extends Script {
const code = l.calculatedTags ?? []
allCode.push(
" public metaTaggging_for_" + l.id + "(feat: {properties: Record<string, string>}) {"
" public metaTaggging_for_" + l.id + "(feat: {properties: Record<string, string>}) {",
)
for (const line of code) {
const firstEq = line.indexOf("=")
@ -700,10 +748,10 @@ class LayerOverviewUtils extends Script {
if (!isStrict) {
allCode.push(
" Utils.AddLazyProperty(feat.properties, '" +
attributeName +
"', () => " +
expression +
" ) "
attributeName +
"', () => " +
expression +
" ) ",
)
} else {
attributeName = attributeName.substring(0, attributeName.length - 2).trim()
@ -728,14 +776,14 @@ class LayerOverviewUtils extends Script {
sharedLayers: Map<string, LayerConfigJson>,
recompiledThemes: string[],
forceReload: boolean,
whitelist: Set<string>
whitelist: Set<string>,
): Map<string, LayoutConfigJson> {
console.log(" ---------- VALIDATING BUILTIN THEMES ---------")
const themeFiles = ScriptUtils.getThemeFiles()
const fixed = new Map<string, LayoutConfigJson>()
const publicLayers = LayerOverviewUtils.publicLayerIdsFrom(
themeFiles.map((th) => th.parsed)
themeFiles.map((th) => th.parsed),
)
const trs = this.getSharedTagRenderings(new DoesImageExist(licensePaths, existsSync))
@ -775,15 +823,15 @@ class LayerOverviewUtils extends Script {
LayerOverviewUtils.themePath + "/" + themePath.substring(themePath.lastIndexOf("/"))
const usedLayers = Array.from(
LayerOverviewUtils.extractLayerIdsFrom(themeFile, false)
LayerOverviewUtils.extractLayerIdsFrom(themeFile, false),
).map((id) => LayerOverviewUtils.layerPath + id + ".json")
if (!forceReload && !this.shouldBeUpdated([themePath, ...usedLayers], targetPath)) {
fixed.set(
themeFile.id,
JSON.parse(
readFileSync(LayerOverviewUtils.themePath + themeFile.id + ".json", "utf8")
)
readFileSync(LayerOverviewUtils.themePath + themeFile.id + ".json", "utf8"),
),
)
ScriptUtils.erasableLog("Skipping", themeFile.id)
skippedThemes.push(themeFile.id)
@ -794,23 +842,23 @@ class LayerOverviewUtils extends Script {
new PrevalidateTheme().convertStrict(
themeFile,
ConversionContext.construct([themePath], ["PrepareLayer"])
ConversionContext.construct([themePath], ["PrepareLayer"]),
)
try {
themeFile = new PrepareTheme(convertState, {
skipDefaultLayers: true,
}).convertStrict(
themeFile,
ConversionContext.construct([themePath], ["PrepareLayer"])
ConversionContext.construct([themePath], ["PrepareLayer"]),
)
new ValidateThemeAndLayers(
new DoesImageExist(licensePaths, existsSync, knownTagRenderings),
themePath,
true,
knownTagRenderings
knownTagRenderings,
).convertStrict(
themeFile,
ConversionContext.construct([themePath], ["PrepareLayer"])
ConversionContext.construct([themePath], ["PrepareLayer"]),
)
if (themeFile.icon.endsWith(".svg")) {
@ -860,7 +908,7 @@ class LayerOverviewUtils extends Script {
const usedImages = Utils.Dedup(
new ExtractImages(true, knownTagRenderings)
.convertStrict(themeFile)
.map((x) => x.path)
.map((x) => x.path),
)
usedImages.sort()
@ -886,16 +934,16 @@ class LayerOverviewUtils extends Script {
t.shortDescription ?? new Translation(t.description).FirstSentence(),
mustHaveLanguage: t.mustHaveLanguage?.length > 0,
}
})
}),
)
}
console.log(
"Recompiled themes " +
recompiledThemes.join(", ") +
" and skipped " +
skippedThemes.length +
" themes"
recompiledThemes.join(", ") +
" and skipped " +
skippedThemes.length +
" themes",
)
return fixed