fix(search): HTML escape issue

This commit is contained in:
Jimmy Cai 2020-09-26 22:50:23 +02:00
parent 08102e2f69
commit 6e48765d82
No known key found for this signature in database
GPG Key ID: 3EA408E527F37B18
2 changed files with 38 additions and 9 deletions

View File

@ -15,6 +15,11 @@ const searchResultTitle = document.querySelector('.search-result--title') as HTM
let data: pageData[]; let data: pageData[];
/**
* createElement
* Edited from:
* @link https://stackoverflow.com/a/42405694
*/
function createElement(tag, attrs, children) { function createElement(tag, attrs, children) {
var element = document.createElement(tag); var element = document.createElement(tag);
@ -49,6 +54,26 @@ function escapeRegExp(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
} }
/**
* Escape HTML tags as HTML entities
* Edited from:
* @link https://stackoverflow.com/a/5499821
*/
const tagsToReplace = {
'&': '&',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;'
};
function replaceTag(tag) {
return tagsToReplace[tag] || tag;
}
function replaceHTMLEnt(str) {
return str.replace(/[&<>"]/g, replaceTag);
}
async function getData() { async function getData() {
if (!data) { if (!data) {
/// Not fetched yet /// Not fetched yet
@ -118,7 +143,7 @@ function clear() {
async function doSearch(keywords: string[]) { async function doSearch(keywords: string[]) {
const startTime = performance.now(); const startTime = performance.now();
const results = await searchKeyword(keywords); const results = await searchKeywords(keywords);
clear(); clear();
for (const item of results) { for (const item of results) {
@ -130,14 +155,15 @@ async function doSearch(keywords: string[]) {
searchResultTitle.innerText = `${results.length} pages (${((endTime - startTime) / 1000).toPrecision(1)} seconds)`; searchResultTitle.innerText = `${results.length} pages (${((endTime - startTime) / 1000).toPrecision(1)} seconds)`;
} }
function marker(match, p1, p2, p3, offset, string) { function marker(match) {
return '<mark>' + match + '</mark>'; return '<mark>' + match + '</mark>';
} }
async function searchKeyword(keywords: string[]) { async function searchKeywords(keywords: string[]) {
const rawData = await getData(); const rawData = await getData();
let results: pageData[] = []; let results: pageData[] = [];
/// Sort keywords by their length
keywords.sort((a, b) => { keywords.sort((a, b) => {
return b.length - a.length return b.length - a.length
}); });
@ -152,15 +178,18 @@ async function searchKeyword(keywords: string[]) {
let matched = false; let matched = false;
for (const keyword of keywords) { for (const keyword of keywords) {
const regex = new RegExp(escapeRegExp(keyword), 'gi'); if (keyword === '') continue;
const contentMatch = regex.exec(item.content); const regex = new RegExp(escapeRegExp(replaceHTMLEnt(keyword)), 'gi');
const contentMatch = regex.exec(result.content);
regex.lastIndex = 0; /// Reset regex regex.lastIndex = 0; /// Reset regex
const titleMatch = regex.exec(item.title);
const titleMatch = regex.exec(result.title);
regex.lastIndex = 0; /// Reset regex regex.lastIndex = 0; /// Reset regex
if (titleMatch) { if (titleMatch) {
result.title = item.title.replace(regex, marker); result.title = result.title.replace(regex, marker);
} }
if (titleMatch || contentMatch) { if (titleMatch || contentMatch) {
@ -215,7 +244,7 @@ const render = (item: pageData) => {
</article>; </article>;
} }
window.addEventListener('load', () => { window.addEventListener('DOMContentLoaded', () => {
handleQueryString(); handleQueryString();
bindQueryStringChange(); bindQueryStringChange();
bindSearchForm(); bindSearchForm();

View File

@ -5,7 +5,7 @@
{{- $result := slice -}} {{- $result := slice -}}
{{- range $filtered -}} {{- range $filtered -}}
{{- $data := dict "title" .Title "date" .Date "permalink" .Permalink "content" (htmlUnescape .Plain) -}} {{- $data := dict "title" .Title "date" .Date "permalink" .Permalink "content" (.Plain) -}}
{{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}} {{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}}
{{- if and $image.exists $image.resource -}} {{- if and $image.exists $image.resource -}}