diff --git a/static/skin/i18n/en.json b/static/skin/i18n/en.json
index 9345a1cb5..7add683cc 100644
--- a/static/skin/i18n/en.json
+++ b/static/skin/i18n/en.json
@@ -51,8 +51,8 @@
, "torrent-download-link-text": "BitTorrent"
, "torrent-download-alt-text": "Download via BitTorrent"
, "library-opds-feed-all-entries": "Library OPDS Feed - All entries"
- , "filter-by-tag": "Filter by tag \"{{TAG}}\""
- , "stop-filtering-by-tag": "Stop filtering by tag \"{{TAG}}\""
+ , "filter-by-tag": "Filter by tag \"{{{TAG}}}\""
+ , "stop-filtering-by-tag": "Stop filtering by tag \"{{{TAG}}}\""
, "library-opds-feed-parameterised": "Library OPDS Feed - entries matching {{#LANG}}\nLanguage: {{LANG}} {{/LANG}}{{#CATEGORY}}\nCategory: {{CATEGORY}} {{/CATEGORY}}{{#TAG}}\nTag: {{TAG}} {{/TAG}}{{#Q}}\nQuery: {{Q}} {{/Q}}"
, "welcome-to-kiwix-server": "Welcome to Kiwix Server"
, "download-links-heading": "Download links for {{BOOK_TITLE}}"
diff --git a/static/skin/index.js b/static/skin/index.js
index 13359cbcf..873b187f0 100644
--- a/static/skin/index.js
+++ b/static/skin/index.js
@@ -105,6 +105,14 @@
return '';
}
+ // Borrowed from https://stackoverflow.com/a/1912522
+ function htmlDecode(input){
+ var e = document.createElement('textarea');
+ e.innerHTML = input;
+ // handle case of empty input
+ return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
+ }
+
function htmlEncode(str) {
return str.replace(/[\u00A0-\u9999<>\&]/gim, (i) => `${i.charCodeAt(0)};`);
}
@@ -121,9 +129,14 @@
function generateTagLink(tagValue) {
tagValue = tagValue.toLowerCase();
- const htmlEncodedTagValue = htmlEncode(tagValue);
const tagMessage = $t("filter-by-tag", {TAG: tagValue});
- return `${htmlEncodedTagValue}`
+ const spanElement = document.createElement("span");
+ spanElement.className = 'tag__link';
+ spanElement.setAttribute('aria-label', tagMessage);
+ spanElement.setAttribute('title', tagMessage);
+ spanElement.setAttribute('data-tag', tagValue);
+ spanElement.innerHTML = htmlEncode(tagValue);
+ return spanElement.outerHTML;
}
function generateBookHtml(book, sort = false) {
@@ -144,7 +157,7 @@
const mulLangList = langCodesList.filter(x => languages.hasOwnProperty(x)).map(x => languages[x]);
language = mulLangList.join(', ');
}
- const tags = getInnerHtml(book, 'tags');
+ const tags = htmlDecode(getInnerHtml(book, 'tags'));
const tagList = tags.split(';').filter(tag => {return !(tag.startsWith('_'))});
const tagFilterLinks = tagList.map((tagValue) => generateTagLink(tagValue));
const tagHtml = tagFilterLinks.join(' | ');
@@ -492,7 +505,7 @@
function addTagElement(tagValue, resetFilter) {
const tagElement = document.getElementsByClassName('tagFilterLabel')[0];
tagElement.style.display = 'inline-block';
- tagElement.innerHTML = `${tagValue}`;
+ tagElement.innerHTML = htmlEncode(tagValue);
const tagMessage = $t("stop-filtering-by-tag", {TAG: tagValue});
tagElement.setAttribute('aria-label', tagMessage);
tagElement.setAttribute('title', tagMessage);