fix theme...

This commit is contained in:
2024-08-01 08:46:51 +08:00
parent dea546ddfa
commit 167f6afe6a
16 changed files with 3036 additions and 26146 deletions

View File

@@ -54,7 +54,7 @@
isHome: false,
isHighlightShrink: true,
isToc: false,
postUpdate: '2024-08-01 08:43:54'
postUpdate: '2024-08-01 08:46:20'
}</script><script>(win=>{
win.saveToLocal = {
set: (key, value, ttl) => {

View File

@@ -54,7 +54,7 @@
isHome: false,
isHighlightShrink: true,
isToc: false,
postUpdate: '2024-08-01 08:43:54'
postUpdate: '2024-08-01 08:46:20'
}</script><script>(win=>{
win.saveToLocal = {
set: (key, value, ttl) => {

View File

@@ -54,7 +54,7 @@
isHome: false,
isHighlightShrink: true,
isToc: false,
postUpdate: '2024-08-01 08:43:54'
postUpdate: '2024-08-01 08:46:20'
}</script><script>(win=>{
win.saveToLocal = {
set: (key, value, ttl) => {

View File

@@ -54,7 +54,7 @@
isHome: false,
isHighlightShrink: true,
isToc: false,
postUpdate: '2024-08-01 08:43:54'
postUpdate: '2024-08-01 08:46:20'
}</script><script>(win=>{
win.saveToLocal = {
set: (key, value, ttl) => {

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 KiB

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,192 +1,177 @@
window.addEventListener("load", () => {
const $searchMask = document.getElementById("search-mask");
const $searchDialog = document.querySelector("#algolia-search .search-dialog");
window.addEventListener('load', () => {
const $searchMask = document.getElementById('search-mask')
const $searchDialog = document.querySelector('#algolia-search .search-dialog')
const openSearch = () => {
anzhiyu.animateIn($searchMask, "to_show 0.5s");
$searchDialog.style.display = "block";
setTimeout(() => {
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
}, 100);
const bodyStyle = document.body.style
bodyStyle.width = '100%'
bodyStyle.overflow = 'hidden'
btf.animateIn($searchMask, 'to_show 0.5s')
btf.animateIn($searchDialog, 'titleScale 0.5s')
setTimeout(() => { document.querySelector('#algolia-search .ais-SearchBox-input').focus() }, 100)
// shortcut: ESC
document.addEventListener("keydown", function f(event) {
if (event.code === "Escape") {
closeSearch();
document.removeEventListener("keydown", f);
document.addEventListener('keydown', function f (event) {
if (event.code === 'Escape') {
closeSearch()
document.removeEventListener('keydown', f)
}
});
})
fixSafariHeight();
window.addEventListener("resize", fixSafariHeight);
};
// shortcut: shift+S
if (anzhiyu_keyboard) {
window.addEventListener("keydown", function (event) {
if (event.keyCode == 83 && event.shiftKey) {
console.info(selectTextNow);
if (selectTextNow) {
openSearch();
const t = document.querySelector("#algolia-search-input > div > form > input");
t.value = selectTextNow;
t.dispatchEvent(new Event("input"));
setTimeout(() => {
document.querySelector("#algolia-search-input > div > form > button.ais-SearchBox-submit").click();
}, 64);
} else {
openSearch();
}
return false;
}
});
fixSafariHeight()
window.addEventListener('resize', fixSafariHeight)
}
const closeSearch = () => {
anzhiyu.animateOut($searchDialog, "search_close .5s");
anzhiyu.animateOut($searchMask, "to_hide 0.5s");
window.removeEventListener("resize", fixSafariHeight);
};
const bodyStyle = document.body.style
bodyStyle.width = ''
bodyStyle.overflow = ''
btf.animateOut($searchDialog, 'search_close .5s')
btf.animateOut($searchMask, 'to_hide 0.5s')
window.removeEventListener('resize', fixSafariHeight)
}
// fix safari
const fixSafariHeight = () => {
if (window.innerWidth < 768) {
$searchDialog.style.setProperty("--search-height", window.innerHeight + "px");
$searchDialog.style.setProperty('--search-height', window.innerHeight + 'px')
}
};
}
const searchClickFn = () => {
anzhiyu.addEventListenerPjax(document.querySelector("#search-button > .search"), "click", openSearch);
};
btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch)
}
const searchFnOnce = () => {
$searchMask.addEventListener("click", closeSearch);
document.querySelector("#algolia-search .search-close-button").addEventListener("click", closeSearch);
};
$searchMask.addEventListener('click', closeSearch)
document.querySelector('#algolia-search .search-close-button').addEventListener('click', closeSearch)
}
const algolia = GLOBAL_CONFIG.algolia;
const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName;
const cutContent = content => {
if (content === '') return ''
const firstOccur = content.indexOf('<mark>')
let start = firstOccur - 30
let end = firstOccur + 120
let pre = ''
let post = ''
if (start <= 0) {
start = 0
end = 140
} else {
pre = '...'
}
if (end > content.length) {
end = content.length
} else {
post = '...'
}
const matchContent = pre + content.substring(start, end) + post
return matchContent
}
const algolia = GLOBAL_CONFIG.algolia
const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName
if (!isAlgoliaValid) {
return console.error("Algolia setting is invalid!");
return console.error('Algolia setting is invalid!')
}
const search = instantsearch({
indexName: algolia.indexName,
/* global algoliasearch */
searchClient: algoliasearch(algolia.appId, algolia.apiKey),
searchFunction(helper) {
if (helper.state.query) {
let innerLoading = '<i class="anzhiyufont anzhiyu-icon-spinner anzhiyu-spin"></i>';
document.getElementById("algolia-hits").innerHTML = innerLoading;
helper.search();
}
},
});
searchFunction (helper) {
helper.state.query && helper.search()
}
})
const configure = instantsearch.widgets.configure({
hitsPerPage: algolia.hits.per_page ?? 5,
});
hitsPerPage: 5
})
const searchBox = instantsearch.widgets.searchBox({
container: "#algolia-search-input",
container: '#algolia-search-input',
showReset: false,
showSubmit: false,
placeholder: algolia.languages.input_placeholder,
showLoadingIndicator: true,
searchOnEnterKeyPressOnly: true,
searchAsYouType: false,
});
placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
showLoadingIndicator: true
})
const hits = instantsearch.widgets.hits({
container: "#algolia-hits",
container: '#algolia-hits',
templates: {
item(data) {
const link = data.permalink ? data.permalink : GLOBAL_CONFIG.root + data.path;
const result = data._highlightResult;
const loadingLogo = document.querySelector("#algolia-hits .anzhiyu-spin");
if (loadingLogo) {
loadingLogo.style.display = "none";
}
setTimeout(() => {
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
}, 200);
item (data) {
const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path)
const result = data._highlightResult
const content = result.contentStripTruncate
? cutContent(result.contentStripTruncate.value)
: result.contentStrip
? cutContent(result.contentStrip.value)
: result.content
? cutContent(result.content.value)
: ''
return `
<a href="${link}" class="algolia-hit-item-link">
<span class="algolia-hits-item-title">${result.title.value || "no-title"}</span>
</a>`;
<span class="algolia-hits-item-title">${result.title.value || 'no-title'}</span>
<p class="algolia-hit-item-content">${content}</p>
</a>`
},
empty: function (data) {
const loadingLogo = document.querySelector("#algolia-hits .anzhiyu-spin");
console.info(loadingLogo);
if (loadingLogo) {
loadingLogo.style.display = "none";
}
setTimeout(() => {
document.querySelector("#algolia-search .ais-SearchBox-input").focus();
}, 200);
return (
'<div id="algolia-hits-empty">' +
GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) +
"</div>"
);
},
},
cssClasses: {
item: "algolia-hit-item",
},
});
'</div>'
)
}
}
})
const stats = instantsearch.widgets.stats({
container: "#algolia-info > .algolia-stats",
container: '#algolia-info > .algolia-stats',
templates: {
text: function (data) {
const stats = GLOBAL_CONFIG.algolia.languages.hits_stats
.replace(/\$\{hits}/, data.nbHits)
.replace(/\$\{time}/, data.processingTimeMS);
return `<hr>${stats}`;
},
},
});
.replace(/\$\{time}/, data.processingTimeMS)
return (
`<hr>${stats}`
)
}
}
})
const powerBy = instantsearch.widgets.poweredBy({
container: "#algolia-info > .algolia-poweredBy",
});
container: '#algolia-info > .algolia-poweredBy'
})
const pagination = instantsearch.widgets.pagination({
container: "#algolia-pagination",
totalPages: algolia.hits.per_page ?? 5,
container: '#algolia-pagination',
totalPages: 5,
templates: {
first: '<i class="anzhiyufont anzhiyu-icon-angle-double-left"></i>',
last: '<i class="anzhiyufont anzhiyu-icon-angle-double-right"></i>',
previous: '<i class="anzhiyufont anzhiyu-icon-angle-left"></i>',
next: '<i class="anzhiyufont anzhiyu-icon-angle-right"></i>',
},
scrollTo: false,
showFirstLast: false,
cssClasses: {
root: "pagination",
item: "pagination-item",
link: "page-number",
active: "current",
disabled: "disabled-item",
},
});
first: '<i class="fas fa-angle-double-left"></i>',
last: '<i class="fas fa-angle-double-right"></i>',
previous: '<i class="fas fa-angle-left"></i>',
next: '<i class="fas fa-angle-right"></i>'
}
})
search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]); // add the widgets to the instantsearch instance
search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]) // add the widgets to the instantsearch instance
search.start();
search.start()
searchClickFn();
searchFnOnce();
searchClickFn()
searchFnOnce()
window.addEventListener("pjax:complete", () => {
!anzhiyu.isHidden($searchMask) && closeSearch();
searchClickFn();
});
window.addEventListener('pjax:complete', () => {
!btf.isHidden($searchMask) && closeSearch()
searchClickFn()
})
window.pjax &&
search.on("render", () => {
window.pjax.refresh(document.getElementById("algolia-hits"));
});
});
window.pjax && search.on('render', () => {
window.pjax.refresh(document.getElementById('algolia-hits'))
})
})

View File

@@ -1,270 +1,364 @@
window.addEventListener("load", () => {
let loadFlag = false;
let dataObj = [];
const $searchMask = document.getElementById("search-mask");
/**
* Refer to hexo-generator-searchdb
* https://github.com/next-theme/hexo-generator-searchdb/blob/main/dist/search.js
* Modified by hexo-theme-butterfly
*/
class LocalSearch {
constructor ({
path = '',
unescape = false,
top_n_per_article = 1
}) {
this.path = path
this.unescape = unescape
this.top_n_per_article = top_n_per_article
this.isfetched = false
this.datas = null
}
getIndexByWord (words, text, caseSensitive = false) {
const index = []
const included = new Set()
if (!caseSensitive) {
text = text.toLowerCase()
}
words.forEach(word => {
if (this.unescape) {
const div = document.createElement('div')
div.innerText = word
word = div.innerHTML
}
const wordLen = word.length
if (wordLen === 0) return
let startPosition = 0
let position = -1
if (!caseSensitive) {
word = word.toLowerCase()
}
while ((position = text.indexOf(word, startPosition)) > -1) {
index.push({ position, word })
included.add(word)
startPosition = position + wordLen
}
})
// Sort index by position of keyword
index.sort((left, right) => {
if (left.position !== right.position) {
return left.position - right.position
}
return right.word.length - left.word.length
})
return [index, included]
}
// Merge hits into slices
mergeIntoSlice (start, end, index) {
let item = index[0]
let { position, word } = item
const hits = []
const count = new Set()
while (position + word.length <= end && index.length !== 0) {
count.add(word)
hits.push({
position,
length: word.length
})
const wordEnd = position + word.length
// Move to next position of hit
index.shift()
while (index.length !== 0) {
item = index[0]
position = item.position
word = item.word
if (wordEnd > position) {
index.shift()
} else {
break
}
}
}
return {
hits,
start,
end,
count: count.size
}
}
// Highlight title and content
highlightKeyword (val, slice) {
let result = ''
let index = slice.start
for (const { position, length } of slice.hits) {
result += val.substring(index, position)
index = position + length
result += `<mark class="search-keyword">${val.substr(position, length)}</mark>`
}
result += val.substring(index, slice.end)
return result
}
getResultItems (keywords) {
const resultItems = []
this.datas.forEach(({ title, content, url }) => {
// The number of different keywords included in the article.
const [indexOfTitle, keysOfTitle] = this.getIndexByWord(keywords, title)
const [indexOfContent, keysOfContent] = this.getIndexByWord(keywords, content)
const includedCount = new Set([...keysOfTitle, ...keysOfContent]).size
// Show search results
const hitCount = indexOfTitle.length + indexOfContent.length
if (hitCount === 0) return
const slicesOfTitle = []
if (indexOfTitle.length !== 0) {
slicesOfTitle.push(this.mergeIntoSlice(0, title.length, indexOfTitle))
}
let slicesOfContent = []
while (indexOfContent.length !== 0) {
const item = indexOfContent[0]
const { position } = item
// Cut out 120 characters. The maxlength of .search-input is 80.
const start = Math.max(0, position - 20)
const end = Math.min(content.length, position + 100)
slicesOfContent.push(this.mergeIntoSlice(start, end, indexOfContent))
}
// Sort slices in content by included keywords' count and hits' count
slicesOfContent.sort((left, right) => {
if (left.count !== right.count) {
return right.count - left.count
} else if (left.hits.length !== right.hits.length) {
return right.hits.length - left.hits.length
}
return left.start - right.start
})
// Select top N slices in content
const upperBound = parseInt(this.top_n_per_article, 10)
if (upperBound >= 0) {
slicesOfContent = slicesOfContent.slice(0, upperBound)
}
let resultItem = ''
url = new URL(url, location.origin)
url.searchParams.append('highlight', keywords.join(' '))
if (slicesOfTitle.length !== 0) {
resultItem += `<div class="local-search-hit-item"><a href="${url.href}"><span class="search-result-title">${this.highlightKeyword(title, slicesOfTitle[0])}</span>`
} else {
resultItem += `<div class="local-search-hit-item"><a href="${url.href}"><span class="search-result-title">${title}</span>`
}
slicesOfContent.forEach(slice => {
resultItem += `<p class="search-result">${this.highlightKeyword(content, slice)}...</p></a>`
})
resultItem += '</div>'
resultItems.push({
item: resultItem,
id: resultItems.length,
hitCount,
includedCount
})
})
return resultItems
}
fetchData () {
const isXml = !this.path.endsWith('json')
fetch(this.path)
.then(response => response.text())
.then(res => {
// Get the contents from search data
this.isfetched = true
this.datas = isXml
? [...new DOMParser().parseFromString(res, 'text/xml').querySelectorAll('entry')].map(element => ({
title: element.querySelector('title').textContent,
content: element.querySelector('content').textContent,
url: element.querySelector('url').textContent
}))
: JSON.parse(res)
// Only match articles with non-empty titles
this.datas = this.datas.filter(data => data.title).map(data => {
data.title = data.title.trim()
data.content = data.content ? data.content.trim().replace(/<[^>]+>/g, '') : ''
data.url = decodeURIComponent(data.url).replace(/\/{2,}/g, '/')
return data
})
// Remove loading animation
window.dispatchEvent(new Event('search:loaded'))
})
}
// Highlight by wrapping node in mark elements with the given class name
highlightText (node, slice, className) {
const val = node.nodeValue
let index = slice.start
const children = []
for (const { position, length } of slice.hits) {
const text = document.createTextNode(val.substring(index, position))
index = position + length
const mark = document.createElement('mark')
mark.className = className
mark.appendChild(document.createTextNode(val.substr(position, length)))
children.push(text, mark)
}
node.nodeValue = val.substring(index, slice.end)
children.forEach(element => {
node.parentNode.insertBefore(element, node)
})
}
// Highlight the search words provided in the url in the text
highlightSearchWords (body) {
const params = new URL(location.href).searchParams.get('highlight')
const keywords = params ? params.split(' ') : []
if (!keywords.length || !body) return
const walk = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, null)
const allNodes = []
while (walk.nextNode()) {
if (!walk.currentNode.parentNode.matches('button, select, textarea, .mermaid')) allNodes.push(walk.currentNode)
}
allNodes.forEach(node => {
const [indexOfNode] = this.getIndexByWord(keywords, node.nodeValue)
if (!indexOfNode.length) return
const slice = this.mergeIntoSlice(0, node.nodeValue.length, indexOfNode)
this.highlightText(node, slice, 'search-keyword')
})
}
}
window.addEventListener('load', () => {
// Search
const { path, top_n_per_article, unescape, languages } = GLOBAL_CONFIG.localSearch
const localSearch = new LocalSearch({
path,
top_n_per_article,
unescape
})
const input = document.querySelector('#local-search-input input')
const statsItem = document.getElementById('local-search-stats-wrap')
const $loadingStatus = document.getElementById('loading-status')
const isXml = !path.endsWith('json')
const inputEventFunction = () => {
if (!localSearch.isfetched) return
let searchText = input.value.trim().toLowerCase()
isXml && (searchText = searchText.replace(/</g, '&lt;').replace(/>/g, '&gt;'))
if (searchText !== '') $loadingStatus.innerHTML = '<i class="fas fa-spinner fa-pulse"></i>'
const keywords = searchText.split(/[-\s]+/)
const container = document.getElementById('local-search-results')
let resultItems = []
if (searchText.length > 0) {
// Perform local searching
resultItems = localSearch.getResultItems(keywords)
}
if (keywords.length === 1 && keywords[0] === '') {
container.textContent = ''
statsItem.textContent = ''
} else if (resultItems.length === 0) {
container.textContent = ''
const statsDiv = document.createElement('div')
statsDiv.className = 'search-result-stats'
statsDiv.textContent = languages.hits_empty.replace(/\$\{query}/, searchText)
statsItem.innerHTML = statsDiv.outerHTML
} else {
resultItems.sort((left, right) => {
if (left.includedCount !== right.includedCount) {
return right.includedCount - left.includedCount
} else if (left.hitCount !== right.hitCount) {
return right.hitCount - left.hitCount
}
return right.id - left.id
})
const stats = languages.hits_stats.replace(/\$\{hits}/, resultItems.length)
container.innerHTML = `<div class="search-result-list">${resultItems.map(result => result.item).join('')}</div>`
statsItem.innerHTML = `<hr><div class="search-result-stats">${stats}</div>`
window.pjax && window.pjax.refresh(container)
}
$loadingStatus.textContent = ''
}
let loadFlag = false
const $searchMask = document.getElementById('search-mask')
const $searchDialog = document.querySelector('#local-search .search-dialog')
// fix safari
const fixSafariHeight = () => {
if (window.innerWidth < 768) {
$searchDialog.style.setProperty('--search-height', window.innerHeight + 'px')
}
}
const openSearch = () => {
const bodyStyle = document.body.style;
bodyStyle.width = "100%";
bodyStyle.overflow = "hidden";
anzhiyu.animateIn($searchMask, "to_show 0.5s");
anzhiyu.animateIn(document.querySelector("#local-search .search-dialog"), "titleScale 0.5s");
setTimeout(() => {
document.querySelector("#local-search-input input").focus();
}, 100);
const bodyStyle = document.body.style
bodyStyle.width = '100%'
bodyStyle.overflow = 'hidden'
btf.animateIn($searchMask, 'to_show 0.5s')
btf.animateIn($searchDialog, 'titleScale 0.5s')
setTimeout(() => { input.focus() }, 300)
if (!loadFlag) {
search();
loadFlag = true;
!localSearch.isfetched && localSearch.fetchData()
input.addEventListener('input', inputEventFunction)
loadFlag = true
}
// shortcut: ESC
document.addEventListener("keydown", function f(event) {
if (event.code === "Escape") {
closeSearch();
document.removeEventListener("keydown", f);
document.addEventListener('keydown', function f (event) {
if (event.code === 'Escape') {
closeSearch()
document.removeEventListener('keydown', f)
}
});
};
})
fixSafariHeight()
window.addEventListener('resize', fixSafariHeight)
}
const closeSearch = () => {
const bodyStyle = document.body.style;
bodyStyle.width = "";
bodyStyle.overflow = "";
anzhiyu.animateOut(document.querySelector("#local-search .search-dialog"), "search_close .5s");
anzhiyu.animateOut($searchMask, "to_hide 0.5s");
};
const bodyStyle = document.body.style
bodyStyle.width = ''
bodyStyle.overflow = ''
btf.animateOut($searchDialog, 'search_close .5s')
btf.animateOut($searchMask, 'to_hide 0.5s')
window.removeEventListener('resize', fixSafariHeight)
}
const searchClickFn = () => {
document.querySelector("#search-button > .search").addEventListener("click", openSearch);
document.querySelector("#menu-search").addEventListener("click", openSearch);
};
btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch)
}
const searchClickFnOnce = () => {
document.querySelector("#local-search .search-close-button").addEventListener("click", closeSearch);
$searchMask.addEventListener("click", closeSearch);
if (GLOBAL_CONFIG.localSearch.preload) dataObj = fetchData(GLOBAL_CONFIG.localSearch.path);
};
// check url is json or not
const isJson = url => {
const reg = /\.json$/;
return reg.test(url);
};
const fetchData = async path => {
let data = [];
const response = await fetch(path);
if (isJson(path)) {
data = await response.json();
} else {
const res = await response.text();
const t = await new window.DOMParser().parseFromString(res, "text/xml");
const a = await t;
data = [...a.querySelectorAll("entry")].map(item => {
let tagsArr = [];
if (item.querySelector("tags") && item.querySelector("tags").getElementsByTagName("tag")) {
Array.prototype.forEach.call(item.querySelector("tags").getElementsByTagName("tag"), function (item, index) {
tagsArr.push(item.textContent);
});
}
let content = item.querySelector("content") && item.querySelector("content").textContent;
let imgReg = /<img.*?(?:>|\/>)/gi; //匹配图片中的img标签
let srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; // 匹配图片中的src
let arr = content.match(imgReg); //筛选出所有的img
let srcArr = [];
if (arr) {
for (let i = 0; i < arr.length; i++) {
let src = arr[i].match(srcReg);
// 获取图片地址
if (!src[1].indexOf("http")) srcArr.push(src[1]);
}
}
return {
title: item.querySelector("title").textContent,
content: content,
url: item.querySelector("url").textContent,
tags: tagsArr,
oneImage: srcArr && srcArr[0],
};
});
const searchFnOnce = () => {
document.querySelector('#local-search .search-close-button').addEventListener('click', closeSearch)
$searchMask.addEventListener('click', closeSearch)
if (GLOBAL_CONFIG.localSearch.preload) {
localSearch.fetchData()
}
if (response.ok) {
const $loadDataItem = document.getElementById("loading-database");
$loadDataItem.nextElementSibling.style.display = "block";
$loadDataItem.remove();
}
return data;
};
localSearch.highlightSearchWords(document.getElementById('article-container'))
}
const search = () => {
if (!GLOBAL_CONFIG.localSearch.preload) {
dataObj = fetchData(GLOBAL_CONFIG.localSearch.path);
}
const $input = document.querySelector("#local-search-input input");
const $resultContent = document.getElementById("local-search-results");
const $loadingStatus = document.getElementById("loading-status");
window.addEventListener('search:loaded', () => {
const $loadDataItem = document.getElementById('loading-database')
$loadDataItem.nextElementSibling.style.display = 'block'
$loadDataItem.remove()
})
$input.addEventListener("input", function () {
const keywords = this.value.trim().toLowerCase().split(/[\s]+/);
if (keywords[0] !== "")
$loadingStatus.innerHTML = '<i class="anzhiyufont anzhiyu-icon-spinner anzhiyu-pulse-icon"></i>';
$resultContent.innerHTML = "";
let str = '<div class="search-result-list">';
if (keywords.length <= 0) return;
let count = 0;
// perform local searching
dataObj.then(data => {
data.forEach(data => {
let isMatch = true;
let dataTitle = data.title ? data.title.trim().toLowerCase() : "";
let dataTags = data.tags;
let oneImage = data.oneImage ?? "";
const dataContent = data.content
? data.content
.trim()
.replace(/<[^>]+>/g, "")
.toLowerCase()
: "";
const dataUrl = data.url.startsWith("/") ? data.url : GLOBAL_CONFIG.root + data.url;
let indexTitle = -1;
let indexContent = -1;
let firstOccur = -1;
// only match articles with not empty titles and contents
if (dataTitle !== "" || dataContent !== "") {
keywords.forEach((keyword, i) => {
indexTitle = dataTitle.indexOf(keyword);
indexContent = dataContent.indexOf(keyword);
if (indexTitle < 0 && indexContent < 0) {
isMatch = false;
} else {
if (indexContent < 0) {
indexContent = 0;
}
if (i === 0) {
firstOccur = indexContent;
}
}
});
} else {
isMatch = false;
}
// show search results
if (isMatch) {
if (firstOccur >= 0) {
// cut out 130 characters
// let start = firstOccur - 30 < 0 ? 0 : firstOccur - 30
// let end = firstOccur + 50 > dataContent.length ? dataContent.length : firstOccur + 50
let start = firstOccur - 30;
let end = firstOccur + 100;
let pre = "";
let post = "";
if (start < 0) {
start = 0;
}
if (start === 0) {
end = 100;
} else {
pre = "...";
}
if (end > dataContent.length) {
end = dataContent.length;
} else {
post = "...";
}
let matchContent = dataContent.substring(start, end);
// highlight all keywords
keywords.forEach(keyword => {
const regS = new RegExp(keyword, "gi");
matchContent = matchContent.replace(regS, '<span class="search-keyword">' + keyword + "</span>");
dataTitle = dataTitle.replace(regS, '<span class="search-keyword">' + keyword + "</span>");
});
str += '<div class="local-search__hit-item">';
if (oneImage) {
str += `<div class="search-left"><img src=${oneImage} alt=${dataTitle} data-fancybox='gallery'>`;
} else {
str += '<div class="search-left" style="width:0">';
}
str += "</div>";
if (oneImage) {
str +=
'<div class="search-right"><a href="' +
dataUrl +
'" class="search-result-title">' +
dataTitle +
"</a>";
} else {
str +=
'<div class="search-right" style="width: 100%"><a href="' +
dataUrl +
'" class="search-result-title">' +
dataTitle +
"</a>";
}
count += 1;
if (dataContent !== "") {
str +=
'<p class="search-result" onclick="pjax.loadUrl(`' +
dataUrl +
'`)">' +
pre +
matchContent +
post +
"</p>";
}
if (dataTags.length) {
str += '<div class="search-result-tags">';
for (let i = 0; i < dataTags.length; i++) {
const element = dataTags[i].trim();
str +=
'<a class="tag-list" href="/tags/' +
element +
'/" data-pjax-state="" one-link-mark="yes">#' +
element +
"</a>";
}
str += "</div>";
}
}
str += "</div></div>";
}
});
if (count === 0) {
str +=
'<div id="local-search__hits-empty">' +
GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) +
"</div>";
}
str += "</div>";
$resultContent.innerHTML = str;
if (keywords[0] !== "") $loadingStatus.innerHTML = "";
window.pjax && window.pjax.refresh($resultContent);
});
});
};
searchClickFn();
searchClickFnOnce();
searchClickFn()
searchFnOnce()
// pjax
window.addEventListener("pjax:complete", () => {
!anzhiyu.isHidden($searchMask) && closeSearch();
searchClickFn();
});
});
window.addEventListener('pjax:complete', () => {
!btf.isHidden($searchMask) && closeSearch()
localSearch.highlightSearchWords(document.getElementById('article-container'))
searchClickFn()
})
})

View File

@@ -7,7 +7,7 @@ document.addEventListener('DOMContentLoaded', function () {
saveToLocal.get(targetEncodingCookie) === undefined
? defaultEncoding
: Number(saveToLocal.get('translate-chn-cht'))
let translateButtonObject, translateRightMenuButtonObject;
let translateButtonObject
const isSnackbar = snackbarData !== undefined
function setLang () {
@@ -56,12 +56,12 @@ document.addEventListener('DOMContentLoaded', function () {
currentEncoding = 1
targetEncoding = 2
translateButtonObject.textContent = msgToTraditionalChinese
isSnackbar && anzhiyu.snackbarShow(snackbarData.cht_to_chs)
isSnackbar && btf.snackbarShow(snackbarData.cht_to_chs)
} else if (targetEncoding === 2) {
currentEncoding = 2
targetEncoding = 1
translateButtonObject.textContent = msgToSimplifiedChinese
isSnackbar && anzhiyu.snackbarShow(snackbarData.chs_to_cht)
isSnackbar && btf.snackbarShow(snackbarData.chs_to_cht)
}
saveToLocal.set(targetEncodingCookie, targetEncoding, 2)
setLang()
@@ -97,24 +97,16 @@ document.addEventListener('DOMContentLoaded', function () {
return str
}
function translateInitialization() {
translateButtonObject = document.getElementById('translateLink');
translateRightMenuButtonObject = document.getElementById('menu-translate').querySelector('span');
if (translateButtonObject || translateRightMenuButtonObject) {
function translateInitialization () {
translateButtonObject = document.getElementById('translateLink')
if (translateButtonObject) {
if (currentEncoding !== targetEncoding) {
const textContent = targetEncoding === 1 ? msgToSimplifiedChinese : msgToTraditionalChinese;
if (translateButtonObject) {
translateButtonObject.textContent = textContent;
}
if (translateRightMenuButtonObject) {
translateRightMenuButtonObject.textContent = textContent;
}
setLang();
setTimeout(translateBody, translateDelay);
translateButtonObject.textContent =
targetEncoding === 1
? msgToSimplifiedChinese
: msgToTraditionalChinese
setLang()
setTimeout(translateBody, translateDelay)
}
}
}
@@ -127,4 +119,4 @@ document.addEventListener('DOMContentLoaded', function () {
translateInitialization()
document.addEventListener('pjax:complete', translateInitialization)
})
})

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long