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" - +