diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1560ebe5c..dc1523536 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,10 +41,13 @@ _Breaking developer changes, which may affect downstream projects or sites that
# Unreleased
+#### :bug: Bugfixes
+* Fix rendering of HTML content in KeepRight and ImproveOSM issues ([#8928])
#### :hammer: Development
* Switch build system to [esbuild](https://esbuild.github.io/) for much faster builds ([#8774], thanks [@ mbrzakovic] and [@bhousel])
[#8774]: https://github.com/openstreetmap/iD/pull/8774
+[#8928]: https://github.com/openstreetmap/iD/pull/8928
# 2.20.3
diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js
index 045788591..a0561794f 100644
--- a/modules/services/improveOSM.js
+++ b/modules/services/improveOSM.js
@@ -57,11 +57,11 @@ function updateRtree(item, replace) {
}
function linkErrorObject(d) {
- return `${d}`;
+ return { html: `${d}` };
}
function linkEntity(d) {
- return `${d}`;
+ return { html: `${d}` };
}
function pointAverage(points) {
diff --git a/modules/services/keepRight.js b/modules/services/keepRight.js
index 375256550..927728224 100644
--- a/modules/services/keepRight.js
+++ b/modules/services/keepRight.js
@@ -2,6 +2,7 @@ import RBush from 'rbush';
import { dispatch as d3_dispatch } from 'd3-dispatch';
import { json as d3_json } from 'd3-fetch';
+import { unescape } from 'lodash-es';
import { fileFetcher } from '../core/file_fetcher';
import { geoExtent, geoVecAdd } from '../geo';
@@ -65,7 +66,6 @@ function updateRtree(item, replace) {
function tokenReplacements(d) {
if (!(d instanceof QAItem)) return;
- const htmlRegex = new RegExp(/<\/[a-z][\s\S]*>/);
const replacements = {};
const issueTemplate = _krData.errorTypes[d.whichType];
@@ -99,12 +99,12 @@ function tokenReplacements(d) {
idType = 'IDs' in issueTemplate ? issueTemplate.IDs[i-1] : '';
if (idType && capture) { // link IDs if present in the capture
capture = parseError(capture, idType);
- } else if (htmlRegex.test(capture)) { // escape any html in non-IDs
- capture = '\\' + capture + '\\';
} else {
const compare = capture.toLowerCase();
if (_krData.localizeStrings[compare]) { // some replacement strings can be localized
capture = t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
+ } else {
+ capture = unescape(capture);
}
}
@@ -160,15 +160,15 @@ function parseError(capture, idType) {
function linkErrorObject(d) {
- return `${d}`;
+ return { html: `${d}` };
}
function linkEntity(d) {
- return `${d}`;
+ return { html: `${d}` };
}
function linkURL(d) {
- return `${d}`;
+ return { html: `${d}` };
}
// arbitrary node list of form: #ID, #ID, #ID...
diff --git a/modules/ui/improveOSM_details.js b/modules/ui/improveOSM_details.js
index e8e23cd33..9f8c3e543 100644
--- a/modules/ui/improveOSM_details.js
+++ b/modules/ui/improveOSM_details.js
@@ -15,7 +15,7 @@ export function uiImproveOsmDetails(context) {
if (d.desc) return d.desc;
const issueKey = d.issueKey;
d.replacements = d.replacements || {};
- d.replacements.default = t.html('inspector.unknown'); // special key `default` works as a fallback string
+ d.replacements.default = { html: t.html('inspector.unknown') }; // special key `default` works as a fallback string
return t.html(`QA.improveOSM.error_types.${issueKey}.description`, d.replacements);
}
@@ -47,7 +47,7 @@ export function uiImproveOsmDetails(context) {
descriptionEnter
.append('div')
.attr('class', 'qa-details-description-text')
- .text(issueDetail);
+ .html(issueDetail);
// If there are entity links in the error message..
let relatedEntities = [];
diff --git a/modules/ui/improveOSM_header.js b/modules/ui/improveOSM_header.js
index 1505cbe57..4e6b5a015 100644
--- a/modules/ui/improveOSM_header.js
+++ b/modules/ui/improveOSM_header.js
@@ -8,7 +8,7 @@ export function uiImproveOsmHeader() {
function issueTitle(d) {
const issueKey = d.issueKey;
d.replacements = d.replacements || {};
- d.replacements.default = t.html('inspector.unknown'); // special key `default` works as a fallback string
+ d.replacements.default = { html: t.html('inspector.unknown') }; // special key `default` works as a fallback string
return t.html(`QA.improveOSM.error_types.${issueKey}.title`, d.replacements);
}
@@ -62,7 +62,7 @@ export function uiImproveOsmHeader() {
headerEnter
.append('div')
.attr('class', 'qa-header-label')
- .text(issueTitle);
+ .html(issueTitle);
}
improveOsmHeader.issue = function(val) {
diff --git a/modules/ui/keepRight_details.js b/modules/ui/keepRight_details.js
index 2adf77cdb..6045ff664 100644
--- a/modules/ui/keepRight_details.js
+++ b/modules/ui/keepRight_details.js
@@ -14,12 +14,12 @@ export function uiKeepRightDetails(context) {
function issueDetail(d) {
const { itemType, parentIssueType } = d;
- const unknown = t.html('inspector.unknown');
+ const unknown = { html: t.html('inspector.unknown') };
let replacements = d.replacements || {};
replacements.default = unknown; // special key `default` works as a fallback string
let detail = t.html(`QA.keepRight.errorTypes.${itemType}.description`, replacements);
- if (detail === unknown) {
+ if (detail === unknown.html) {
detail = t.html(`QA.keepRight.errorTypes.${parentIssueType}.description`, replacements);
}
return detail;
diff --git a/modules/ui/keepRight_header.js b/modules/ui/keepRight_header.js
index b966b2fe1..91230849c 100644
--- a/modules/ui/keepRight_header.js
+++ b/modules/ui/keepRight_header.js
@@ -10,13 +10,14 @@ export function uiKeepRightHeader() {
const { itemType, parentIssueType } = d;
const unknown = t.html('inspector.unknown');
let replacements = d.replacements || {};
- replacements.default = unknown; // special key `default` works as a fallback string
+ replacements.default = { html: unknown }; // special key `default` works as a fallback string
- let title = t.html(`QA.keepRight.errorTypes.${itemType}.title`, replacements);
- if (title === unknown) {
- title = t.html(`QA.keepRight.errorTypes.${parentIssueType}.title`, replacements);
+ const title = t.html(`QA.keepRight.errorTypes.${itemType}.title`, replacements);
+ if (title !== unknown) {
+ return t.apply(`QA.keepRight.errorTypes.${itemType}.title`, replacements);
+ } else {
+ return t.apply(`QA.keepRight.errorTypes.${parentIssueType}.title`, replacements);
}
- return title;
}