Merge develop

This commit is contained in:
Pieter Vander Vennet 2023-10-14 22:41:52 +02:00
commit 2001ef09bf
50 changed files with 1443 additions and 1341 deletions

View file

@ -61,9 +61,9 @@ async function createSocialImage(layout: LayoutConfig, template: "" | "Wide"): P
if (!layout.icon.endsWith(".svg")) {
console.warn(
"Not creating a social image for " +
layout.id +
" as it is _not_ a .svg: " +
layout.icon
layout.id +
" as it is _not_ a .svg: " +
layout.icon,
)
return undefined
}
@ -85,7 +85,7 @@ async function createSocialImage(layout: LayoutConfig, template: "" | "Wide"): P
delete svg["defs"]
delete svg["$"]
let templateSvg = await ScriptUtils.ReadSvg(
"./public/assets/SocialImageTemplate" + template + ".svg"
"./public/assets/SocialImageTemplate" + template + ".svg",
)
templateSvg = Utils.WalkJson(
templateSvg,
@ -104,7 +104,7 @@ async function createSocialImage(layout: LayoutConfig, template: "" | "Wide"): P
return false
}
return mightBeTokenToReplace.circle[0]?.$?.style?.indexOf("fill:#ff00ff") >= 0
}
},
)
const builder = new xml2js.Builder()
@ -116,7 +116,7 @@ async function createSocialImage(layout: LayoutConfig, template: "" | "Wide"): P
async function createManifest(
layout: LayoutConfig,
alreadyWritten: string[]
alreadyWritten: string[],
): Promise<{
manifest: any
whiteIcons: string[]
@ -210,19 +210,17 @@ function asLangSpan(t: Translation, tag = "span"): string {
let previousSrc: Set<string> = new Set<string>()
let eliUrlsCached: string[]
function eliUrls(): string[] {
async function eliUrls(): Promise<string[]> {
if (eliUrlsCached) {
return eliUrlsCached
}
const urls: string[] = []
const regex = /{switch:([^}]+)}/
const rasterLayers = [
...AvailableRasterLayers.vectorLayers,
...eli.features,
...eli_global.layers.map((properties) => ({ properties })),
]
const rasterLayers = [AvailableRasterLayers.maptilerDefaultLayer, ...eli.features, ...eli_global.layers.map(properties => ({ properties }))]
for (const feature of rasterLayers) {
const url = (<RasterLayerPolygon>feature).properties.url
const f = <RasterLayerPolygon>feature
const url = f.properties.url
const match = url.match(regex)
if (match) {
const domains = match[1].split(",")
@ -231,17 +229,43 @@ function eliUrls(): string[] {
} else {
urls.push(url)
}
if (f.properties.type === "vector") {
// We also need to whitelist eventual sources
const styleSpec = await Utils.downloadJsonCached(f.properties.url, 1000 * 120)
for (const key of Object.keys(styleSpec.sources)) {
const url = styleSpec.sources[key].url
if(!url){
continue
}
let urlClipped = url
if(url.indexOf("?") > 0){
urlClipped = url?.substring(0, url.indexOf("?"))
}
console.log("Source url ",key,url)
urls.push(url)
if(urlClipped.endsWith(".json")){
const tileInfo = await Utils.downloadJsonCached(url, 1000*120)
urls.push(tileInfo["tiles"] ?? [])
}
}
urls.push(...(styleSpec["tiles"] ?? []))
urls.push(styleSpec["sprite"])
urls.push(styleSpec["glyphs"])
}
}
eliUrlsCached = urls
return urls
return Utils.NoNull(urls).sort()
}
function generateCsp(
async function generateCsp(
layout: LayoutConfig,
options: {
scriptSrcs: string[]
}
): string {
},
): Promise<string> {
const apiUrls: string[] = [
"'self'",
...Constants.defaultOverpassUrls,
@ -251,12 +275,12 @@ function generateCsp(
"https://pietervdvn.goatcounter.com",
]
.concat(...SpecialVisualizations.specialVisualizations.map((sv) => sv.needsUrls))
.concat(...eliUrls())
.concat(...await eliUrls())
const geojsonSources: string[] = layout.layers.map((l) => l.source?.geojsonSource)
const hosts = new Set<string>()
const eliLayers: RasterLayerPolygon[] = AvailableRasterLayers.layersAvailableAt(
new ImmutableStore({ lon: 0, lat: 0 })
new ImmutableStore({ lon: 0, lat: 0 }),
).data
const vectorLayers = eliLayers.filter((l) => l.properties.type === "vector")
const vectorSources = vectorLayers.map((l) => l.properties.url)
@ -283,14 +307,14 @@ function generateCsp(
"connect-src items for theme",
layout.id,
"(extra sources: ",
newSrcs.join(" ") + ")"
newSrcs.join(" ") + ")",
)
previousSrc = hosts
const csp: Record<string, string> = {
"default-src": "'self'",
"script-src": ["'self'", "https://gc.zgo.at/count.js", ...(options?.scriptSrcs ?? [])].join(
" "
" ",
),
"img-src": "* data:", // maplibre depends on 'data:' to load
"connect-src": connectSrc.join(" "),
@ -320,12 +344,12 @@ const removeOtherLanguagesHash = crypto
async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alreadyWritten) {
Locale.language.setData(layout.language[0])
const targetLanguage = layout.language[0]
const ogTitle = Translations.T(layout.title).textFor(targetLanguage).replace(/"/g, '\\"')
const ogTitle = Translations.T(layout.title).textFor(targetLanguage).replace(/"/g, "\\\"")
const ogDescr = Translations.T(
layout.shortDescription ?? "Easily add and edit geodata with OpenStreetMap"
layout.shortDescription ?? "Easily add and edit geodata with OpenStreetMap",
)
.textFor(targetLanguage)
.replace(/"/g, '\\"')
.replace(/"/g, "\\\"")
let ogImage = layout.socialImage
let twitterImage = ogImage
if (ogImage === LayoutConfig.defaultSocialImage && layout.official) {
@ -390,34 +414,34 @@ async function createLandingPage(layout: LayoutConfig, manifest, whiteIcons, alr
const loadingText = Translations.t.general.loadingTheme.Subs({ theme: layout.title })
const templateLines = template.split("\n")
const removeOtherLanguagesReference = templateLines.find(
(line) => line.indexOf("./src/UI/RemoveOtherLanguages.js") >= 0
(line) => line.indexOf("./src/UI/RemoveOtherLanguages.js") >= 0,
)
let output = template
.replace("Loading MapComplete, hang on...", asLangSpan(loadingText, "h1"))
.replace(
"Made with OpenStreetMap",
Translations.t.general.poweredByOsm.textFor(targetLanguage)
Translations.t.general.poweredByOsm.textFor(targetLanguage),
)
.replace(/<!-- THEME-SPECIFIC -->.*<!-- THEME-SPECIFIC-END-->/s, themeSpecific)
.replace(
/<!-- CSP -->/,
generateCsp(layout, {
await generateCsp(layout, {
scriptSrcs: [`'sha256-${removeOtherLanguagesHash}'`],
})
}),
)
.replace(removeOtherLanguagesReference, "<script>" + removeOtherLanguages + "</script>")
.replace(
/<!-- DESCRIPTION START -->.*<!-- DESCRIPTION END -->/s,
asLangSpan(layout.shortDescription)
asLangSpan(layout.shortDescription),
)
.replace(
/<!-- IMAGE-START -->.*<!-- IMAGE-END -->/s,
"<img class='p-8 h-32 w-32 self-start' src='" + icon + "' />"
"<img class='p-8 h-32 w-32 self-start' src='" + icon + "' />",
)
.replace(
/.*\/src\/index\.ts.*/,
`<script type="module" src="./index_${layout.id}.ts"></script>`
`<script type="module" src="./index_${layout.id}.ts"></script>`,
)
return output
@ -508,13 +532,14 @@ async function main(): Promise<void> {
title: { en: "MapComplete" },
description: { en: "A thematic map viewer and editor based on OpenStreetMap" },
}),
alreadyWritten
alreadyWritten,
)
const manif = JSON.stringify(manifest, undefined, 2)
writeFileSync("public/index.webmanifest", manif)
}
ScriptUtils.fixUtils()
main().then(() => {
console.log("All done!")
})