fix(search): HTML escape issue
This commit is contained in:
parent
08102e2f69
commit
6e48765d82
@ -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 = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
'"': '"'
|
||||||
|
};
|
||||||
|
|
||||||
|
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();
|
||||||
|
@ -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 -}}
|
||||||
|
Loading…
Reference in New Issue
Block a user