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[];
/**
* createElement
* Edited from:
* @link https://stackoverflow.com/a/42405694
*/
function createElement(tag, attrs, children) {
var element = document.createElement(tag);
@ -49,6 +54,26 @@ function escapeRegExp(string) {
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() {
if (!data) {
/// Not fetched yet
@ -118,7 +143,7 @@ function clear() {
async function doSearch(keywords: string[]) {
const startTime = performance.now();
const results = await searchKeyword(keywords);
const results = await searchKeywords(keywords);
clear();
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)`;
}
function marker(match, p1, p2, p3, offset, string) {
function marker(match) {
return '<mark>' + match + '</mark>';
}
async function searchKeyword(keywords: string[]) {
async function searchKeywords(keywords: string[]) {
const rawData = await getData();
let results: pageData[] = [];
/// Sort keywords by their length
keywords.sort((a, b) => {
return b.length - a.length
});
@ -152,15 +178,18 @@ async function searchKeyword(keywords: string[]) {
let matched = false;
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
const titleMatch = regex.exec(item.title);
const titleMatch = regex.exec(result.title);
regex.lastIndex = 0; /// Reset regex
if (titleMatch) {
result.title = item.title.replace(regex, marker);
result.title = result.title.replace(regex, marker);
}
if (titleMatch || contentMatch) {
@ -215,7 +244,7 @@ const render = (item: pageData) => {
</article>;
}
window.addEventListener('load', () => {
window.addEventListener('DOMContentLoaded', () => {
handleQueryString();
bindQueryStringChange();
bindSearchForm();

View file

@ -5,7 +5,7 @@
{{- $result := slice -}}
{{- 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" -}}
{{- if and $image.exists $image.resource -}}