diff --git a/AllTranslationAssets.ts b/AllTranslationAssets.ts index a39c7c1..78be5c6 100644 --- a/AllTranslationAssets.ts +++ b/AllTranslationAssets.ts @@ -102,7 +102,7 @@ export default class AllTranslationAssets { getStartedNewAccount: new Translation( {"en":" or create a new account","nl":" of maak een nieuwe account aan ","fr":" ou enregistrez-vous","es":" o crea una nueva cuenta","ca":" o crea un nou compte","gl":" ou crea unha nova conta","de":" oder ein neues Konto anlegen"} ), noTagsSelected: new Translation( {"en":"No tags selected","es":"No se han seleccionado etiquetas","ca":"No s'han seleccionat etiquetes","gl":"Non se seleccionaron etiquetas","nl":"Geen tags geselecteerd","fr":"Aucune balise sélectionnée","de":"Keine Tags ausgewählt"} ), customThemeIntro: new Translation( {"en":"

Custom themes

These are previously visited user-generated themes.","nl":"

Onofficiële thema's

De onderstaande thema's heb je eerder bezocht en zijn gemaakt door andere OpenStreetMappers.","fr":"

Thèmes personnalisés

Vous avez déjà visité ces thèmes personnalisés.","gl":"

Temas personalizados

Estes son temas xerados por usuarios previamente visitados.","de":"

Kundenspezifische Themen

Dies sind zuvor besuchte benutzergenerierte Themen"} ), - aboutMapcomplete: new Translation( {"en":"

About MapComplete

With MapComplete you can enrich OpenStreetMap with information on a single theme. Answer a few questions, and within minutes your contributions will be available around the globe! The theme maintainer defines elements, questions and languages for the theme.

Find out more

MapComplete always offers the next step to learn more about OpenStreetMap.


Did you notice an issue? Do you have a feature request? Want to help translate? Head over to the source code or issue tracker.

Want to see your progress? Follow the edit count on OsmCha.

","nl":"

Over MapComplete

Met MapComplete kun je OpenStreetMap verrijken met informatie over een bepaald thema. Beantwoord enkele vragen, en binnen een paar minuten is jouw bijdrage wereldwijd beschikbaar! De maker van het thema bepaalt de elementen, vragen en taalversies voor het thema.

Ontdek meer

MapComplete biedt altijd de volgende stap naar meer OpenStreetMap:

Merk je een bug of wil je een extra feature? Wil je helpen vertalen? Bezoek dan de broncode en issue tracker.

Wil je je vorderingen zien? Volg de edits op OsmCha.

","de":"

Über MapComplete

MapComplete ist ein OpenStreetMap-Editor, der jedem helfen soll, auf einfache Weise Informationen zu einem Einzelthema hinzuzufügen.

Nur Merkmale, die für ein einzelnes Thema relevant sind, werden mit einigen vordefinierten Fragen gezeigt, um die Dinge einfach und extrem benutzerfreundlich zu halten.Der Themen-Betreuer kann auch eine Sprache für die Schnittstelle wählen, Elemente deaktivieren oder sogar in eine andere Website ohne jegliches UI-Element einbetten.

Ein weiterer wichtiger Teil von MapComplete ist jedoch, immer den nächsten Schritt anzubietenum mehr über OpenStreetMap zu erfahren:

Fällt Ihnen ein Problem mit MapComplete auf? Haben Sie einen Feature-Wunsch? Wollen Sie beim Übersetzen helfen? Gehen Sie zum Quellcode oder zur Problemverfolgung.

"} ), + aboutMapcomplete: new Translation( {"en":"

About MapComplete

With MapComplete you can enrich OpenStreetMap with information on a single theme. Answer a few questions, and within minutes your contributions will be available around the globe! The theme maintainer defines elements, questions and languages for the theme.

Find out more

MapComplete always offers the next step to learn more about OpenStreetMap.


Did you notice an issue? Do you have a feature request? Want to help translate? Head over to the source code or issue tracker.

Want to see your progress? Follow the edit count on OsmCha.

","nl":"

Over MapComplete

Met MapComplete kun je OpenStreetMap verrijken met informatie over een bepaald thema. Beantwoord enkele vragen, en binnen een paar minuten is jouw bijdrage wereldwijd beschikbaar! De maker van het thema bepaalt de elementen, vragen en taalversies voor het thema.

Ontdek meer

MapComplete biedt altijd de volgende stap naar meer OpenStreetMap:

Merk je een bug of wil je een extra feature? Wil je helpen vertalen? Bezoek dan de broncode en issue tracker.

Wil je je vorderingen zien? Volg de edits op OsmCha.

","de":"

Über MapComplete

MapComplete ist ein OpenStreetMap-Editor, der jedem helfen soll, auf einfache Weise Informationen zu einem Einzelthema hinzuzufügen.

Nur Merkmale, die für ein einzelnes Thema relevant sind, werden mit einigen vordefinierten Fragen gezeigt, um die Dinge einfach und extrem benutzerfreundlich zu halten.Der Themen-Betreuer kann auch eine Sprache für die Schnittstelle wählen, Elemente deaktivieren oder sogar in eine andere Website ohne jegliches UI-Element einbetten.

Ein weiterer wichtiger Teil von MapComplete ist jedoch, immer den nächsten Schritt anzubietenum mehr über OpenStreetMap zu erfahren:

Fällt Ihnen ein Problem mit MapComplete auf? Haben Sie einen Feature-Wunsch? Wollen Sie beim Übersetzen helfen? Gehen Sie zum Quellcode oder zur Problemverfolgung.

"} ), backgroundMap: new Translation( {"en":"Background map","ca":"Mapa de fons","es":"Mapa de fondo","nl":"Achtergrondkaart","fr":"Carte de fonds","de":"Hintergrundkarte"} ), layerSelection: { zoomInToSeeThisLayer: new Translation( {"en":"Zoom in to see this layer","ca":"Amplia per veure aquesta capa","es":"Amplía para ver esta capa","nl":"Vergroot de kaart om deze laag te zien","fr":"Aggrandissez la carte pour voir cette couche","de":"Vergrößern, um diese Ebene zu sehen"} ), title: new Translation( {"en":"Select layers","nl":"Selecteer lagen"} ), diff --git a/Customizations/AllKnownLayouts.ts b/Customizations/AllKnownLayouts.ts index 87d42f1..65c76e2 100644 --- a/Customizations/AllKnownLayouts.ts +++ b/Customizations/AllKnownLayouts.ts @@ -10,7 +10,7 @@ export class AllKnownLayouts { public static layoutsList: LayoutConfig[] = AllKnownLayouts.GenerateOrderedList(AllKnownLayouts.allKnownLayouts); private static GenerateOrderedList(allKnownLayouts: Map): LayoutConfig[] { - const keys = ["personal", "cyclofix", "bookcases", "toilets", "aed"] + const keys = ["personal", "cyclofix", "hailhydrant", "bookcases", "toilets", "aed"] const list = [] for (const key of keys) { list.push(allKnownLayouts.get(key)) diff --git a/Customizations/JSON/LayerConfig.ts b/Customizations/JSON/LayerConfig.ts index c65a556..6e87f2b 100644 --- a/Customizations/JSON/LayerConfig.ts +++ b/Customizations/JSON/LayerConfig.ts @@ -456,5 +456,4 @@ export default class LayerConfig { return allIcons; } - } \ No newline at end of file diff --git a/Customizations/JSON/LayoutConfig.ts b/Customizations/JSON/LayoutConfig.ts index 64cfc84..91e4d56 100644 --- a/Customizations/JSON/LayoutConfig.ts +++ b/Customizations/JSON/LayoutConfig.ts @@ -40,11 +40,11 @@ export default class LayoutConfig { public readonly enableLayers: boolean; public readonly enableSearch: boolean; public readonly enableGeolocation: boolean; - private readonly _official : boolean; public readonly enableBackgroundLayerSelection: boolean; public readonly customCss?: string; + private readonly _official: boolean; - constructor(json: LayoutConfigJson, official=true, context?: string) { + constructor(json: LayoutConfigJson, official = true, context?: string) { this._official = official; this.id = json.id; context = (context ?? "") + "." + this.id; @@ -108,7 +108,7 @@ export default class LayoutConfig { } // @ts-ignore - return new LayerConfig(layer,`${this.id}.layers[${i}]`, official) + return new LayerConfig(layer, `${this.id}.layers[${i}]`, official) }); // ALl the layers are constructed, let them share tags in now! @@ -170,13 +170,13 @@ export default class LayoutConfig { } public CustomCodeSnippets(): string[] { - if(this._official){ + if (this._official) { return []; } const msg = "
This layout uses custom javascript, loaded for the wide internet. The code is printed below, please report suspicious code on the issue tracker of MapComplete:
" const custom = []; for (const layer of this.layers) { - custom.push(...layer.CustomCodeSnippets().map(code => code+"
")) + custom.push(...layer.CustomCodeSnippets().map(code => code + "
")) } if (custom.length === 0) { return custom; @@ -184,8 +184,8 @@ export default class LayoutConfig { custom.splice(0, 0, msg); return custom; } - - public ExtractImages() : Set{ + + public ExtractImages(): Set { const icons = new Set() for (const layer of this.layers) { layer.ExtractImages().forEach(icons.add, icons) @@ -194,4 +194,53 @@ export default class LayoutConfig { icons.add(this.socialImage) return icons } + + /** + * Replaces all the relative image-urls with a fixed image url + * This is to fix loading from external sources + * + * It should be passed the location where the original theme file is hosted. + * + * If no images are rewritten, the same object is returned, otherwise a new copy is returned + */ + public patchImages(originalURL: string, originalJson: string): LayoutConfig { + const allImages = Array.from(this.ExtractImages()) + const rewriting = new Map() + + // Needed for absolute urls: note that it doesn't contain a trailing slash + const origin = new URL(originalURL).origin + let path = new URL(originalURL).href + path = path.substring(0, path.lastIndexOf("/")) + for (const image of allImages) { + if(image == "" || image == undefined){ + continue + } + if (image.startsWith("http://") || image.startsWith("https://")) { + continue + } + if (image.startsWith("/")) { + // This is an absolute path + rewriting.set(image, origin + image) + } else if (image.startsWith("./assets/themes")) { + // Legacy workaround + rewriting.set(image, path + image.substring(image.lastIndexOf("/"))) + } else if (image.startsWith("./")) { + // This is a relative url + rewriting.set(image, path + image.substring(1)) + } else { + // This is a relative URL with only the path + rewriting.set(image, path + image) + } + } + if (rewriting.size == 0) { + return this; + } + rewriting.forEach((value, key) => { + console.log("Rewriting",key, "==>", value) + + originalJson = originalJson.replace(new RegExp(key, "g"), value) + }) + return new LayoutConfig(JSON.parse(originalJson), false, "Layout rewriting") + } + } \ No newline at end of file diff --git a/Docs/URL_Parameters.md b/Docs/URL_Parameters.md index 4952640..0d71e0b 100644 --- a/Docs/URL_Parameters.md +++ b/Docs/URL_Parameters.md @@ -1,3 +1,24 @@ +URL-parameters and URL-hash +============================ + +This document gives an overview of which URL-parameters can be used to influence MapComplete. + +What is a URL parameter? +------------------------ + +URL-parameters are extra parts of the URL used to set the state. + +For example, if the url is `https://mapcomplete.osm.be/cyclofix?lat=51.0&lon=4.3&z=5&test=true#node/1234`, +the URL-parameters are stated in the part between the `?` and the `#`. There are multiple, all seperated by `&`, namely: + +- The url-parameter `lat` is `51.0` in this instance +- The url-parameter `lon` is `4.3` in this instance +- The url-parameter `z` is `5` in this instance +- The url-parameter `test` is `true` in this instance + +Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case. + + custom-css ------------ If specified, the custom css from the given link will be loaded additionaly @@ -14,6 +35,13 @@ The layout to load into MapComplete userlayout ------------ +If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: + +- The hash of the URL contains a base64-encoded .json-file containing the theme definition +- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator +- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme + The default value is _false_ + The default value is _false_ layer-control-toggle diff --git a/README.md b/README.md index cce053c..3082939 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ > Let a thousand flowers bloom - -MapComplete attempts to be a webversion crossover of StreetComplete and MapContrib. It tries to be just as easy to use as StreetComplete, but it allows to focus on one single theme per instance (e.g. nature, bicycle infrastructure, ...) +MapComplete is an OpenStreetMap viewer and editor. It shows map features on a certain topic, and allows to see, edit and add new features to the map. +It can be seen as a webversion crossover of StreetComplete and MapContrib. It tries to be just as easy to use as StreetComplete, but it allows to focus on one single theme per instance (e.g. nature, bicycle infrastructure, ...) The design goals of MapComplete are to be: @@ -155,12 +155,10 @@ Geolocation is available on mobile only throught hte device's GPS location (so n TODO: erase cookies of third party websites and API's -# Attribution +# Attribution and Copyright -Data from OpenStreetMap +The code is available under GPL; all map data comes from OpenStreetMap (both foreground and background maps). Background layer selection: curated by https://github.com/osmlab/editor-layer-index Icons are attributed in various 'license_info.json'-files and can be found in the app. - - diff --git a/index.css b/index.css index cca5fe6..0ebf81a 100644 --- a/index.css +++ b/index.css @@ -101,6 +101,7 @@ svg, img { box-sizing: content-box; width: 100%; height: 100%; + display: unset; } diff --git a/index.ts b/index.ts index d145cd1..b85cf1d 100644 --- a/index.ts +++ b/index.ts @@ -67,7 +67,7 @@ defaultLayout = QueryParameters.GetQueryParameter("layout", defaultLayout, "The let layoutToUse: LayoutConfig = AllKnownLayouts.allKnownLayouts.get(defaultLayout.toLowerCase()); -const userLayoutParam = QueryParameters.GetQueryParameter("userlayout", "false"); +const userLayoutParam = QueryParameters.GetQueryParameter("userlayout", "false", "If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: \n\n- The hash of the URL contains a base64-encoded .json-file containing the theme definition\n- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator\n- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme"); const layoutFromBase64 = decodeURIComponent(userLayoutParam.data); document.getElementById('centermessage').innerText = ''; document.getElementById("decoration-desktop").remove(); @@ -87,7 +87,7 @@ if (layoutFromBase64.startsWith("http")) { const parsed = JSON.parse(data); // Overwrite the id to the wiki:value parsed.id = link; - const layout = new LayoutConfig(parsed, false); + const layout = new LayoutConfig(parsed, false).patchImages(link, data); InitUiElements.InitAll(layout, layoutFromBase64, testing, layoutFromBase64, btoa(data)); } catch (e) { new FixedUiElement(`${link} is invalid:
${e}
Go back")`)