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.css b/static/skin/index.css
index bfe6dc1f3..b8af17508 100644
--- a/static/skin/index.css
+++ b/static/skin/index.css
@@ -121,7 +121,7 @@
.tagFilterLabel {
width: max-content;
- padding: 10px;
+ padding: 7px;
font-family: roboto;
font-size: 12px;
margin: 0 0 0 17px;
diff --git a/static/skin/index.js b/static/skin/index.js
index 28a452d2b..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 humanFriendlyTagValue = humanFriendlyTitle(tagValue);
- const tagMessage = $t("filter-by-tag", {TAG: humanFriendlyTagValue});
- return `${humanFriendlyTagValue}`
+ const tagMessage = $t("filter-by-tag", {TAG: tagValue});
+ 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);
diff --git a/test/library_server.cpp b/test/library_server.cpp
index f5082a42f..1c97b9548 100644
--- a/test/library_server.cpp
+++ b/test/library_server.cpp
@@ -1033,7 +1033,7 @@ TEST_F(LibraryServerTest, no_name_mapper_catalog_v2_individual_entry_access)
" />\n" \
" \n" \
" \n" \
diff --git a/test/server.cpp b/test/server.cpp
index 44fc99311..9c4ce01ab 100644
--- a/test/server.cpp
+++ b/test/server.cpp
@@ -61,9 +61,9 @@ const ResourceCollection resources200Compressible{
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/i18n.js" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/i18n.js?cacheid=071abc9a" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.css" },
- { STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=1e78e7cf" },
+ { STATIC_CONTENT, "/ROOT%23%3F/skin/index.css?cacheid=e0600dde" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/index.js" },
- { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=f43eb0b9" },
+ { STATIC_CONTENT, "/ROOT%23%3F/skin/index.js?cacheid=480ca6b4" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js" },
{ STATIC_CONTENT, "/ROOT%23%3F/skin/iso6391To3.js?cacheid=ecde2bb3" },
{ DYNAMIC_CONTENT, "/ROOT%23%3F/skin/isotope.pkgd.min.js" },
@@ -279,7 +279,7 @@ TEST_F(ServerTest, CacheIdsOfStaticResources)
{
/* url */ "/ROOT%23%3F/",
R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/kiwix.css?cacheid=2158fad9"
- href="/ROOT%23%3F/skin/index.css?cacheid=1e78e7cf"
+ href="/ROOT%23%3F/skin/index.css?cacheid=e0600dde"
@@ -292,7 +292,7 @@ R"EXPECTEDRESULT( href="/ROOT%23%3F/skin/kiwix.css?cacheid=2158fad9"
-
+
