diff --git a/scripts/GenerateSeries.ts b/scripts/GenerateSeries.ts index 3017e8180..12727606b 100644 --- a/scripts/GenerateSeries.ts +++ b/scripts/GenerateSeries.ts @@ -273,7 +273,6 @@ class GenerateSeries extends Script { allFeatures = allFeatures.filter((f) => f.properties.metadata?.theme !== "EMPTY CS") const centerpoints = allFeatures.map((f) => GeoOperations.centerpoint(f)) console.log("Found", centerpoints.length, " changesets in total") - const path = `${targetDir}/all_centerpoints.geojson` const perBbox = GeoOperations.spreadIntoBboxes(centerpoints, options.zoomlevel) diff --git a/scripts/generateContributors.ts b/scripts/generateContributors.ts index c753cd619..aa84645b4 100644 --- a/scripts/generateContributors.ts +++ b/scripts/generateContributors.ts @@ -26,7 +26,7 @@ function asList(hist: Map): ContributorList { } function main() { - exec("git log --pretty='%aN %%!%% %s' ", (error, stdout, stderr) => { + exec("git log --pretty='%aN %%!%% %s' ", (_, stdout) => { const entries = stdout.split("\n").filter((str) => str !== "") const codeContributors = new Map() const translationContributors = new Map() diff --git a/scripts/generateTaginfoProjectFiles.ts b/scripts/generateTaginfoProjectFiles.ts index 187ff46ce..0b65be1e0 100644 --- a/scripts/generateTaginfoProjectFiles.ts +++ b/scripts/generateTaginfoProjectFiles.ts @@ -34,8 +34,6 @@ function generateTagOverview( return overview } -function tagrenderingToTaginfoDescription(tr: TagRenderingConfig) {} - function generateLayerUsage(layer: LayerConfig, layout: LayoutConfig): any[] { if (layer.name === undefined) { return [] // Probably a duplicate or irrelevant layer diff --git a/src/Logic/FeatureSource/Sources/FeatureSourceMerger.ts b/src/Logic/FeatureSource/Sources/FeatureSourceMerger.ts index b3d921188..350feaabc 100644 --- a/src/Logic/FeatureSource/Sources/FeatureSourceMerger.ts +++ b/src/Logic/FeatureSource/Sources/FeatureSourceMerger.ts @@ -82,7 +82,7 @@ export default class FeatureSourceMerger implements IndexedFeatureSource { } const newList = [] - all.forEach((value, key) => { + all.forEach((value) => { newList.push(value) }) this.features.setData(newList) diff --git a/src/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts b/src/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts index f9b7738a9..80b5774e9 100644 --- a/src/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts +++ b/src/Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource.ts @@ -1,7 +1,6 @@ import { OsmNode, OsmObject, OsmWay } from "../../Osm/OsmObject" import { UIEventSource } from "../../UIEventSource" import { BBox } from "../../BBox" -import StaticFeatureSource from "../Sources/StaticFeatureSource" import { Tiles } from "../../../Models/TileRange" export default class FullNodeDatabaseSource { @@ -48,11 +47,7 @@ export default class FullNodeDatabaseSource { src.ping() } } - const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => - osmNode.asGeoJson() - ) - const featureSource = new StaticFeatureSource(asGeojsonFeatures) const tileId = Tiles.tile_index(z, x, y) this.loadedTiles.set(tileId, nodesById) } diff --git a/src/Logic/GeoOperations.ts b/src/Logic/GeoOperations.ts index 9b47e7e72..04c863d8e 100644 --- a/src/Logic/GeoOperations.ts +++ b/src/Logic/GeoOperations.ts @@ -771,7 +771,6 @@ export class GeoOperations { const splitup = turf.lineSplit(>toSplit, boundary) const kept = [] for (const f of splitup.features) { - const ls = >f if (!GeoOperations.inside(GeoOperations.centerpointCoordinates(f), boundary)) { continue } diff --git a/src/Logic/Osm/OsmConnection.ts b/src/Logic/Osm/OsmConnection.ts index b6ddddf0b..0ee8505d1 100644 --- a/src/Logic/Osm/OsmConnection.ts +++ b/src/Logic/Osm/OsmConnection.ts @@ -227,8 +227,6 @@ export class OsmConnection { // details is an XML DOM of user details let userInfo = details.getElementsByTagName("user")[0] - // let moreDetails = new DOMParser().parseFromString(userInfo.innerHTML, "text/xml"); - let data = self.userDetails.data data.loggedIn = true console.log("Login completed, userinfo is ", userInfo) diff --git a/src/Logic/Web/Wikipedia.ts b/src/Logic/Web/Wikipedia.ts index 9d8b6bb09..0cde301db 100644 --- a/src/Logic/Web/Wikipedia.ts +++ b/src/Logic/Web/Wikipedia.ts @@ -73,7 +73,6 @@ export default class Wikipedia { if (cached) { return cached } - console.log("Constructing store for", cachekey) const store = new UIEventSource({}, cachekey) Wikipedia._fullDetailsCache.set(cachekey, store) @@ -123,12 +122,15 @@ export default class Wikipedia { } const wikipedia = new Wikipedia({ language: data.language }) wikipedia.GetArticleHtml(data.pagename).then((article) => { + article = Utils.purify(article) data.fullArticle = article const content = document.createElement("div") content.innerHTML = article const firstParagraph = content.getElementsByTagName("p").item(0) - data.firstParagraph = firstParagraph.innerHTML - content.removeChild(firstParagraph) + if (firstParagraph) { + data.firstParagraph = firstParagraph.innerHTML + content.removeChild(firstParagraph) + } data.restOfArticle = content.innerHTML store.ping() }) @@ -194,53 +196,6 @@ export default class Wikipedia { encodeURIComponent(searchTerm) return (await Utils.downloadJson(url))["query"]["search"] } - - /** - * Searches via 'index.php' and scrapes the result. - * This gives better results then via the API - * @param searchTerm - */ - public async searchViaIndex( - searchTerm: string - ): Promise<{ title: string; snippet: string; url: string }[]> { - const url = `${this.backend}/w/index.php?search=${encodeURIComponent(searchTerm)}&ns0=1` - const result = await Utils.downloadAdvanced(url) - if (result["redirect"]) { - const targetUrl = result["redirect"] - // This is an exact match - return [ - { - title: this.extractPageName(targetUrl)?.trim(), - url: targetUrl, - snippet: "", - }, - ] - } - if (result["error"]) { - throw "Could not download: " + JSON.stringify(result) - } - const el = document.createElement("html") - el.innerHTML = result["content"].replace(/href="\//g, 'href="' + this.backend + "/") - const searchResults = el.getElementsByClassName("mw-search-results") - const individualResults = Array.from( - searchResults[0]?.getElementsByClassName("mw-search-result") ?? [] - ) - return individualResults.map((result) => { - const toRemove = Array.from(result.getElementsByClassName("searchalttitle")) - for (const toRm of toRemove) { - toRm.parentElement.removeChild(toRm) - } - - return { - title: result - .getElementsByClassName("mw-search-result-heading")[0] - .textContent.trim(), - url: result.getElementsByTagName("a")[0].href, - snippet: result.getElementsByClassName("searchresult")[0].textContent, - } - }) - } - /** * Returns the innerHTML for the given article as string. * Some cleanup is applied to this. @@ -262,7 +217,7 @@ export default class Wikipedia { if (response?.parse?.text === undefined) { return undefined } - const html = response["parse"]["text"]["*"] + const html = Utils.purify(response["parse"]["text"]["*"]) if (html === undefined) { return undefined } diff --git a/src/UI/Base/CenterFlexedElement.ts b/src/UI/Base/CenterFlexedElement.ts deleted file mode 100644 index 6e1af34b0..000000000 --- a/src/UI/Base/CenterFlexedElement.ts +++ /dev/null @@ -1,32 +0,0 @@ -import BaseUIElement from "../BaseUIElement" - -export class CenterFlexedElement extends BaseUIElement { - private _html: string - - constructor(html: string) { - super() - this._html = html ?? "" - } - - InnerRender(): string { - return this._html - } - - AsMarkdown(): string { - return this._html - } - - protected InnerConstructElement(): HTMLElement { - const e = document.createElement("div") - e.innerHTML = this._html - e.style.display = "flex" - e.style.height = "100%" - e.style.width = "100%" - e.style.flexDirection = "column" - e.style.flexWrap = "nowrap" - e.style.alignContent = "center" - e.style.justifyContent = "center" - e.style.alignItems = "center" - return e - } -} diff --git a/src/UI/Base/FixedUiElement.ts b/src/UI/Base/FixedUiElement.ts index aa8e41c27..2fc1e46f2 100644 --- a/src/UI/Base/FixedUiElement.ts +++ b/src/UI/Base/FixedUiElement.ts @@ -1,5 +1,8 @@ import BaseUIElement from "../BaseUIElement" - +import { Utils } from "../../Utils" +/** + * @deprecated + */ export class FixedUiElement extends BaseUIElement { public readonly content: string @@ -8,10 +11,6 @@ export class FixedUiElement extends BaseUIElement { this.content = html ?? "" } - InnerRender(): string { - return this.content - } - AsMarkdown(): string { if (this.HasClass("code")) { if (this.content.indexOf("\n") > 0 || this.HasClass("block")) { @@ -27,7 +26,7 @@ export class FixedUiElement extends BaseUIElement { protected InnerConstructElement(): HTMLElement { const e = document.createElement("span") - e.innerHTML = this.content + e.innerHTML = Utils.purify(this.content) return e } } diff --git a/src/UI/Base/FromHtml.svelte b/src/UI/Base/FromHtml.svelte index ee37d88bf..917839055 100644 --- a/src/UI/Base/FromHtml.svelte +++ b/src/UI/Base/FromHtml.svelte @@ -2,18 +2,14 @@ /** * Given an HTML string, properly shows this */ - import DOMPurify from 'dompurify'; + import { Utils } from "../../Utils"; + export let src: string - - let cleaned = DOMPurify.sanitize(src, { USE_PROFILES: { html: true }, - ADD_ATTR: ['target'] // Don't remove target='_blank'. Note that Utils.initDomPurify does add a hook which automatically adds 'rel=noopener' - }); - - + let htmlElem: HTMLElement $: { if (htmlElem) { - htmlElem.innerHTML = cleaned + htmlElem.innerHTML = Utils.purify(src) } } diff --git a/src/UI/Base/VariableUIElement.ts b/src/UI/Base/VariableUIElement.ts index e4cfc4c4f..69d8a8330 100644 --- a/src/UI/Base/VariableUIElement.ts +++ b/src/UI/Base/VariableUIElement.ts @@ -1,7 +1,11 @@ import { Store } from "../../Logic/UIEventSource" import BaseUIElement from "../BaseUIElement" import Combine from "./Combine" +import { Utils } from "../../Utils" +/** + * @deprecated + */ export class VariableUiElement extends BaseUIElement { private readonly _contents?: Store @@ -42,7 +46,7 @@ export class VariableUiElement extends BaseUIElement { return } if (typeof contents === "string") { - el.innerHTML = contents + el.innerHTML = Utils.purify(contents) } else if (contents instanceof Array) { for (const content of contents) { const c = content?.ConstructElement() diff --git a/src/UI/InputElement/Validators/FediverseValidator.ts b/src/UI/InputElement/Validators/FediverseValidator.ts index 11a410bc9..aa56528e3 100644 --- a/src/UI/InputElement/Validators/FediverseValidator.ts +++ b/src/UI/InputElement/Validators/FediverseValidator.ts @@ -40,7 +40,7 @@ export default class FediverseValidator extends Validator { if (match) { const host = match[2] try { - const url = new URL("https://" + host) + new URL("https://" + host) return undefined } catch (e) { return Translations.t.validation.fediverse.invalidHost.Subs({ host }) diff --git a/src/UI/Popup/NoteCommentElement.ts b/src/UI/Popup/NoteCommentElement.ts index 7e03686be..4d4e59c7e 100644 --- a/src/UI/Popup/NoteCommentElement.ts +++ b/src/UI/Popup/NoteCommentElement.ts @@ -56,7 +56,7 @@ export default class NoteCommentElement extends Combine { ) const htmlElement = document.createElement("div") - htmlElement.innerHTML = comment.html + htmlElement.innerHTML = Utils.purify(comment.html) const images = Array.from(htmlElement.getElementsByTagName("a")) .map((link) => link.href) .filter((link) => { diff --git a/src/Utils.ts b/src/Utils.ts index 290c66bb2..c9705240b 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -25,20 +25,6 @@ Remark that the syntax is slightly different then expected; it uses '$' to note Note that these values can be prepare with javascript in the theme by using a [calculatedTag](calculatedTags.md#calculating-tags-with-javascript) ` public static readonly imageExtensions = new Set(["jpg", "png", "svg", "jpeg", ".gif"]) - - public static initDomPurify() { - if (Utils.runningFromConsole) { - return - } - DOMPurify.addHook("afterSanitizeAttributes", function (node) { - // set all elements owning target to target=_blank + add noopener noreferrer - if ("target" in node) { - node.setAttribute("target", "_blank") - node.setAttribute("rel", "noopener noreferrer") - } - }) - } - public static readonly special_visualizations_importRequirementDocs = `#### Importing a dataset into OpenStreetMap: requirements If you want to import a dataset, make sure that: @@ -160,6 +146,26 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be } >() + public static initDomPurify() { + if (Utils.runningFromConsole) { + return + } + DOMPurify.addHook("afterSanitizeAttributes", function (node) { + // set all elements owning target to target=_blank + add noopener noreferrer + if ("target" in node) { + node.setAttribute("target", "_blank") + node.setAttribute("rel", "noopener noreferrer") + } + }) + } + + public static purify(src: string): string { + return DOMPurify.sanitize(src, { + USE_PROFILES: { html: true }, + ADD_ATTR: ["target"], // Don't remove target='_blank'. Note that Utils.initDomPurify does add a hook which automatically adds 'rel=noopener' + }) + } + /** * Parses the arguments for special visualisations */