[opt] search

This commit is contained in:
xaoxuu 2022-11-29 21:54:15 +08:00
parent 95353cec00
commit e9f9d0e560
5 changed files with 115 additions and 117 deletions

View File

@ -63,10 +63,11 @@ article:
search: search:
service: local_search # local_search, todo... service: local_search # local_search, todo...
local_search: local_search: # 在 front-matter 中设置 indexing:false 来避免被搜索索引
field: all # post, page, all field: all # post, page, all
path: /search.json path: /search.json # 搜索文件存放位置
content: true content: true # 是否搜索内容
codeblock: true # 是否搜索代码块需要content: true)
######## Comments ######## ######## Comments ########

View File

@ -83,7 +83,7 @@ function layoutWidgets() {
if (name in theme.data.widgets) { if (name in theme.data.widgets) {
Object.assign(widget, theme.data.widgets[name]) Object.assign(widget, theme.data.widgets[name])
} }
if (typeof w == 'object' && w.override) { if (typeof w == 'object' && (w.override || w.layout)) {
Object.assign(widget, w) Object.assign(widget, w)
} }
if (widget && widget.layout) { if (widget && widget.layout) {

View File

@ -5,15 +5,23 @@ function layoutDiv() {
el += '<div class="search-wrapper" id="search">' el += '<div class="search-wrapper" id="search">'
el += '<form class="search-form">' el += '<form class="search-form">'
var filter = '' var filter = ''
if (item.filter == 'auto' && page.layout == 'wiki') { if (item.filter == 'auto') {
let matches = page.path.match(/(.*?)\/(.*?)\//i) if (page.layout == 'wiki') {
if (matches?.length > 0) { let matches = page.path.match(/(.*?)\/(.*?)\//i)
filter = matches[0] if (matches?.length > 0) {
filter = matches[0]
}
}
} else {
if (item.filter?.length > 0) {
filter = item.filter
} }
} }
el += '<input type="text" class="search-input" id="search-input"' el += '<input type="text" class="search-input" id="search-input"'
if (filter.length > 0) { if (filter.length > 0) {
filter = '/' + filter if (!filter.startsWith('/')) {
filter = '/' + filter
}
el += ' data-filter="' + filter + '"' el += ' data-filter="' + filter + '"'
el += ' placeholder="' + (item.placeholder || __('search.search_in', filter)) + '">' el += ' placeholder="' + (item.placeholder || __('search.search_in', filter)) + '">'
} else { } else {

View File

@ -3,101 +3,105 @@
*/ */
hexo.extend.generator.register('search_json_generator', function (locals) { hexo.extend.generator.register('search_json_generator', function (locals) {
if (this.theme.config.search.service != 'local_search') { if (this.theme.config.search.service != 'local_search') { return {} }
return {} const { root } = this.config
} const { local_search: cfg } = this.theme.config.search
var config = this.config cfg.sort = '-date'
const { local_search } = this.theme.config.search cfg.field = cfg.field?.trim()
var searchfield = local_search.field
var content = local_search.content
var posts, pages var posts, pages
if (cfg.field == 'post') {
if (searchfield.trim() != '') { posts = locals.posts?.filter(p => p.content?.length > 0).sort(cfg.sort)
searchfield = searchfield.trim() } else if (cfg.field == 'page') {
if (searchfield == 'post'){ pages = locals.pages?.filter(p => p.content?.length > 0)
posts = locals.posts.sort('-date')
} else if (searchfield == 'page') {
pages = locals.pages
} else {
posts = locals.posts.sort('-date')
pages = locals.pages
}
} else { } else {
posts = locals.posts.sort('-date') posts = locals.posts?.filter(p => p.content?.length > 0).sort(cfg.sort)
pages = locals.pages?.filter(p => p.content?.length > 0)
} }
var res = new Array() var res = new Array()
var index = 0
function generateJson(post) {
var temp_post = new Object()
if (post.title) {
temp_post.title = post.title.trim()
}
if (post.path) {
temp_post.path = root + post.path
}
if (cfg.content != false && post._content) {
var content = post._content.trim()
// 过滤掉标签和注释
if (content.includes('{%')) {
// 需要保留内容的的标签
content = content.replace(/{%\s*mark\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*folding\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*copy\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*note\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*kbd\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*emp\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*wavy\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*sub\s*(.*?)\s*%}/g, '$1')
content = content.replace(/{%\s*sup\s*(.*?)\s*%}/g, '$1')
content = content.replace(/<!--\s*folder(.*?)\s*-->/g, '$1')
content = content.replace(/<!--\s*tab(.*?)\s*-->/g, '$1')
content = content.replace(/<!--\s*node(.*?)\s*-->/g, '$1')
// 不保留内容的标签
content = content.replace(/{%\s*(.*?)\s*%}/g, '')
// 注释
content = content.replace(/<!--\s*(.*?)\s*-->/g, '')
// ## 标题
content = content.replace(/[#]{2,} /g, '')
// 部分HTML标签
content = content.replace(/<iframe[\s|\S]+iframe>/g, '')
// 图片
content = content.replace(/\!\[(.*?)\]\((.*?)\)/g, '')
// 链接
content = content.replace(/\[(.*?)\]\((.*?)\)/g, '$1')
// 过滤代码块
if (cfg.codeblock == false) {
content = content.replace(/```([^`]+)```/g, '')
}
// 多个连续空格换成单个空格
content = content.replace(/[\s]{2,} /g, ' ')
// 特殊字符
content = content.replace(/[\r|\n]+/g, '')
}
temp_post.content = content.trim()
}
if (post.tags && post.tags.length > 0) {
var tags = []
post.tags.forEach(function (tag) {
tags.push(tag.name)
})
temp_post.tags = tags
}
if (post.categories && post.categories.length > 0) {
var categories = []
post.categories.forEach(function (cate) {
categories.push(cate.name)
})
temp_post.categories = categories
}
return temp_post
}
if (posts) { if (posts) {
posts.each(function(post) { posts.each(function(post) {
if (post.indexing != undefined && !post.indexing) return if (post.indexing == false) return
var temp_post = new Object() let temp_post = generateJson(post)
if (post.title) { res.push(temp_post)
temp_post.title = post.title
}
if (post.path) {
temp_post.url = config.root + post.path
}
if (content != false && post._content) {
temp_post.content = post._content
}
if (post.tags && post.tags.length > 0) {
var tags = []
post.tags.forEach(function (tag) {
tags.push(tag.name)
})
temp_post.tags = tags
}
if (post.categories && post.categories.length > 0) {
var categories = []
post.categories.forEach(function (cate) {
categories.push(cate.name)
})
temp_post.categories = categories
}
res[index] = temp_post
index += 1
}) })
} }
if (pages) { if (pages) {
pages.each(function(page) { pages.each(function(page) {
if (page.indexing != undefined && !page.indexing) return if (page.indexing == false) return
var temp_page = new Object() let temp_post = generateJson(page)
if (page.title) { res.push(temp_post)
temp_page.title = page.title })
}
if (page.path) {
temp_page.url = config.root + page.path
}
if (content != false && page._content) {
temp_page.content = page._content
}
if (page.tags && page.tags.length > 0) {
var tags = new Array()
var tag_index = 0
page.tags.each(function (tag) {
tags[tag_index] = tag.name
})
temp_page.tags = tags
}
if (page.categories && page.categories.length > 0) {
temp_page.categories = []
(page.categories.each || page.categories.forEach)(function (item) {
temp_page.categories.push(item)
})
}
res[index] = temp_page
index += 1
})
} }
var json = JSON.stringify(res)
return { return {
path: local_search.path, path: cfg.path,
data: json data: JSON.stringify(res)
} }
}) })

View File

@ -24,20 +24,6 @@
/*exported searchFunc*/ /*exported searchFunc*/
var searchFunc = function(path, filter, searchId, contentId) { var searchFunc = function(path, filter, searchId, contentId) {
function stripHtml(html) {
html = html.replace(/<style([\s\S]*?)<\/style>/gi, "");
html = html.replace(/<script([\s\S]*?)<\/script>/gi, "");
html = html.replace(/<figure([\s\S]*?)<\/figure>/gi, "");
html = html.replace(/<\/div>/ig, "\n");
html = html.replace(/<\/li>/ig, "\n");
html = html.replace(/<li>/ig, " * ");
html = html.replace(/<\/ul>/ig, "\n");
html = html.replace(/<\/p>/ig, "\n");
html = html.replace(/<br\s*[\/]?>/gi, "\n");
html = html.replace(/<[^>]+>/ig, "");
return html;
}
function getAllCombinations(keywords) { function getAllCombinations(keywords) {
var i, j, result = []; var i, j, result = [];
@ -68,18 +54,17 @@ var searchFunc = function(path, filter, searchId, contentId) {
} }
// perform local searching // perform local searching
datas.forEach(function(data) { datas.forEach(function(data) {
if (!data.title?.trim().length) { return }
if (!data.content?.trim().length) { return }
var matches = 0; var matches = 0;
if (!data.title || data.title.trim() === "") { if (filter && !data.path.includes(filter)) {
return;
}
if (filter && !data.url.includes(filter)) {
return; return;
} }
var dataTitle = data.title.trim().toLowerCase(); var dataTitle = data.title.trim().toLowerCase();
var dataTitleLowerCase = dataTitle.toLowerCase(); var dataTitleLowerCase = dataTitle.toLowerCase();
var dataContent = stripHtml(data.content.trim()); var dataContent = data.content;
var dataContentLowerCase = dataContent.toLowerCase(); var dataContentLowerCase = dataContent.toLowerCase();
var dataUrl = data.url; var dataUrl = data.path;
var indexTitle = -1; var indexTitle = -1;
var indexContent = -1; var indexContent = -1;
var firstOccur = -1; var firstOccur = -1;