vhtml.regexp
Version:
Filter Elements You Want of HTML By RegExp.
121 lines (100 loc) • 4.65 kB
JavaScript
/**
* [vhtml.regexp]{@link https://github.com/miiwu/vhtml.regexp}
*
* @namespace vhtml.regexp
* @version 1.0.2
* @author miiwu [i.miiwu@outlook.com]
* @copyright miiwu
* @license Apache License 2.0
*/
;
function match_element(string, callback = function (element, tool) {}, regexp = /([^<>]*)(<([^ >]*) ?([^>]*)>)/) {
let match_me = {},
index_me = 0;
if ("string" == typeof string) {
while (true) {
if (!(match_me = string.match(regexp)) || !match_me[0].length) return index_me; // 如果 `正则匹配` 失败 || 没匹配到东西,退出
if (5 <= match_me.length) {
callback(
{
content: match_me[1],
tag: match_me[2],
type: match_me[3],
attribute: match_me[4],
},
{ index: index_me + match_me[1].length, match: match_me }
);
}
string = string.slice(match_me[0].length); // 字符串前移,`正则表达式` 匹配到的长度
index_me += match_me[0].length; // 记录下次开始匹配的位置
}
}
}
function filter_regexp(string, regexp = /.*/) {
let match_fr = string.match(RegExp(regexp));
if (!match_fr) return "";
else return match_fr[0];
}
function filter_element(string, list = [], config = {}) {
function concat_element(emt) {
elements.string = elements.string.concat(
`${emt.content}<${emt.type}${!!emt.attribute ? " " + emt.attribute : emt.attribute}>`
);
} // 合并 `元素` 字符串
function callback(type) {
if (!!config.callback && !!config.callback[type])
return config.callback[type](arguments[1], arguments[2], arguments[3]);
} // 处理 `回调函数`
config = Object.assign({ allow: true, regexp: /([^<>]*)(<([^ >]*) ?([^>]*)>)/ }, config); // 合并 `配置`
let elements = { pattern: "", table: [], string: "", index: 0 },
handler_fe = [
{
match: function (emt, item) {
if (!item.content && !item.attribute) return; // 未指定 `内容` 或 `属性`,退出
if (!!item.content && filter_regexp(emt.content, item.content).length) emt.content = ""; // 过滤 `内容`
if (!!item.attribute && filter_regexp(emt.attribute, item.attribute).length) emt.attribute = ""; // 过滤 `属性`
concat_element(emt);
},
miss: function (emt) {
concat_element(emt);
},
},
{
match: function (emt, item) {
if (!!item.content) emt.content = filter_regexp(emt.content, item.content); // 过滤 `内容`
if (!!item.attribute) emt.attribute = filter_regexp(emt.attribute, item.attribute); // 过滤 `属性`
concat_element(emt);
},
miss: function (emt) {},
},
][Number(Boolean(config.allow))]; // 处理模式
for (let idx = 0; idx < list.length; idx++) {
for (let ix = 0, element = list[idx].type; ix < element.length; ix++) {
elements.pattern = elements.pattern + `${elements.pattern.length ? "|" : ""}(<${element[ix]}[^>]*>)`;
elements.table.push(idx); // `table.index` <-> `list.index`
}
} // 合成 `正则表达式`
elements.pattern = RegExp(elements.pattern);
elements.index = match_element(
string,
function (element, tool) {
let match_fe = element.tag.match(elements.pattern);
if (!match_fe) {
handler_fe.miss(element);
callback("miss", element);
} else {
for (let idx = 1; idx < match_fe.length; idx++) {
if (!!match_fe[idx]) {
handler_fe.match(element, list[elements.table[idx - 1]]);
callback("match", element);
break;
}
} // 求出 `匹配元素` 的索引
} // 是否匹配到 `列表中的元素`
callback("extension", element, tool);
},
config.regexp
); // 匹配 `元素`
return (elements.string += string.slice(elements.index)); // 补全剩余 `非元素字符串`
}
export { match_element, filter_element, filter_regexp };