robot_wiki/amWiki/js/amWiki.search.worker.js

220 lines
8.8 KiB
JavaScript

/**
* amWiki Web端 - 搜索计算子进程模块
* @author Tevin
*/
(function (self) {
'use strict';
//通过 jQuery 检查判断是否处于子进程工作
var atWorker = typeof self.jQuery == 'undefined';
(function () {
/**
* 搜索计算器
* @constructor
*/
var Searcher = function () {
//文档存储
this._documents = null;
//搜索处理结果
this._processing = {};
//设置
this._data = {
//标题命中得分
titleScore: 100,
//接口地址命中得分
apiScore: 50,
//单次内容命中得分
textScore: 5
}
};
//初始文档
Searcher.prototype.initDocs = function (docs) {
this._documents = atWorker ? docs : JSON.parse(JSON.stringify(docs));
for (var id in this._documents) {
if (this._documents.hasOwnProperty(id)) {
this._preDoc(this._documents[id]);
}
}
};
//文档预处理
Searcher.prototype._preDoc = function (doc) {
doc.content = doc.content
.replace(/^\s+|\s+$/g, '')
//分离h1标题
.replace(/^#\s?(.*?)[\r|\n]/, function (match, s1) {
doc.title = s1;
return '';
})
//分离测试文档请求地址
.replace(/([^#]#{3} *请求地址[\n\r]{1,4})([-\w:\/\.]+?)[\n\r]{1,}(#{3} *请求类型[\s\S]+?#{3} *请求参数)/,
function (match, s1, s2, s3) {
doc.api = s2;
return s1 + s3;
})
//清除 Markdown 标题标记
.replace(/#{1,6}(.*?)#{0,6}\s*[\r\n]/g, '$1')
//清除 Markdown 强调斜体删除线标记
.replace(/[_\*~]{1,2}(.*?)[_\*~]{1,2}/g, '$1')
//直接删除 Markdown 图片
.replace(/!\[.*?]\(.*?\)/g, '')
//清除 Markdown 链接标记,还原为显示文本
.replace(/\[(.*?)]\(.*?\)/g, '$1')
//清除 Markdown 代码段标记
.replace(/`{3}.*?[\n\r]([\s\S]*?)`{3}/g, '$1')
//清除 Markdown 代码标记
.replace(/`(.*?)`/g, '$1')
//直接删除所有 html 标签
.replace(/<.+?>/g, '')
//清除 Markdown 引用标记
.replace(/> *(.+?)[n\r]/g, '$1')
//清除 Markdown 分割线标记
.replace(/-{3,} *[\n\r]/g, '')
//清除 Markdown 表格标记
.replace(/(\|.*?[\n\r]{1,2}){3,}/g, function (match) {
return match.replace(/\|.*?[\n\r]{1,2}/g, function (match) {
if (match.indexOf('---') >= 0) {
return '';
} else {
return match.replace(/\|/g, '');
}
});
})
//转换一个空白符为一空格
.replace(/[\n\r\t]/g, ' ')
//合并多个空白符为一个空格
.replace(/\s{2,}/g, ' ');
};
//给中转处理添加属性
Searcher.prototype._addPorcessing = function (id, key, value) {
//如果不存在此id则创建
if (typeof this._processing[id] == 'undefined') {
this._processing[id] = {};
this._processing[id][key] = value;
}
//如果存在此id
else {
//如果不存在此属性,直接赋值
if (typeof this._processing[id][key] == 'undefined') {
this._processing[id][key] = value;
}
//如果存在此属性,则相加(仅得分一项)
else {
this._processing[id][key] += value;
}
}
};
//匹配搜索词与得分计算
Searcher.prototype.matchWords = function (words) {
var wordsReg = new RegExp(words, 'gi');
for (var id in this._documents) {
if (this._documents.hasOwnProperty(id)) {
//标题命中
if (this._documents[id].title) {
var titleMatch = this._documents[id].title.match(wordsReg);
if (titleMatch && titleMatch.length > 0) {
var title = this._documents[id].title.replace(wordsReg, function (match) {
return '<mark>' + match + '</mark>';
});
this._addPorcessing(id, 'title', title);
this._addPorcessing(id, 'score', this._data.titleScore);
}
}
//接口地址命中
if (this._documents[id].api) {
var apiMatch = this._documents[id].api.match(wordsReg);
if (apiMatch && apiMatch.length > 0) {
var api = '<p class="p1"><em>接口</em>' +
this._documents[id].api.replace(wordsReg, function (match) {
return '<mark>' + match + '</mark>';
}) + '</p>';
this._addPorcessing(id, 'api', api);
this._addPorcessing(id, 'score', this._data.apiScore);
}
}
//内容命中
var contentMatch = this._documents[id].content.match(new RegExp('.{0,15}' + words + '.{0,30}', 'gi'));
if (contentMatch) {
var content = '<p>';
for (var i = 0, item; item = contentMatch[i]; i++) {
if (i < 2) {
content += item.replace(wordsReg, function (match) {
return '<mark>' + match + '</mark>';
}) + '... ';
}
}
content += '</p>';
this._addPorcessing(id, 'content', content);
this._addPorcessing(id, 'score', contentMatch.length * this._data.textScore);
}
}
}
this._auxiliary();
};
//辅助得分
Searcher.prototype._auxiliary = function () {
};
//排序与属性补齐
Searcher.prototype._sortByScore = function () {
var list = [];
for (var id in this._processing) {
if (this._processing.hasOwnProperty(id)) {
if (typeof this._processing[id].title == 'undefined') {
this._processing[id].title = this._documents[id].title ? this._documents[id].title : '';
}
if (typeof this._processing[id].api == 'undefined') {
this._processing[id].api = '';
}
if (typeof this._processing[id].content == 'undefined') {
this._processing[id].content = '<p>' + this._documents[id].content.substr(0, 45) + '...</p>';
}
this._processing[id].path = this._documents[id].uri;
this._processing[id].timestamp = this._documents[id].timestamp;
list.push(this._processing[id]);
}
}
list.sort(function (a, b) {
return a.score > b.score ? -1 : 1;
});
return list;
};
//获取结果
Searcher.prototype.getResult = function () {
return this._sortByScore();
};
//作为子进程加载时,仅子进程内有效
//作为全局加载时,全局有效
return this.AWSearcher = Searcher;
}).call(self);
//作为子进程工作时,通过 message 通讯工作
if (atWorker) {
//计算器
var searcher = new self.AWSearcher();
self.onmessage = function (event) {
var data = event.data;
if (data.type == 'searcher:docs') {
searcher.initDocs(data.docs);
self.postMessage({type: 'searcher:ready'});
} else if (data.type == 'searcher:search') {
searcher.matchWords(data.words);
self.postMessage({type: 'searcher:result', result: searcher.getResult()});
}
};
self.postMessage({type: 'searcher:loaded'});
}
})(self);