parent
5134e9af3c
commit
65cc1a2028
@ -1,495 +0,0 @@ |
|||||||
/** |
|
||||||
* 本地网页插件链接 hiker://files/rules/js/categories-header.js
|
|
||||||
* 子页面链接 hiker://page/categories-header
|
|
||||||
* 道长仓库链接 http://hiker.nokia.press/hikerule/rulelist.json?id=2705
|
|
||||||
* 码云 Gitee 链接 https://gitee.com/reborn0/HikerRules/raw/master/plugins/categories-header.js
|
|
||||||
*/ |
|
||||||
/** |
|
||||||
* Object.assign 用法参考链接 |
|
||||||
* |
|
||||||
* 1.https://www.daimajiaoliu.com/daima/47139a9e7100407
|
|
||||||
* 2.https://segmentfault.com/a/1190000011778875
|
|
||||||
* 3.https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
|
|
||||||
*/ |
|
||||||
// 利用 Symbol 实现私有变量和私有方法,外界不可访问(参考链接2)
|
|
||||||
const symbolMap = { |
|
||||||
// checkParams: Symbol('checkParams'),
|
|
||||||
mLayout: Symbol('mLayout'), |
|
||||||
true_url: Symbol('true_url'), |
|
||||||
mPage: Symbol('mPage'), |
|
||||||
src: Symbol('src'), |
|
||||||
ruleObjList: Symbol('ruleObjList'), |
|
||||||
mFold: Symbol('mFold'), |
|
||||||
mFoldInnerEnable: Symbol('mFoldInnerEnable'), |
|
||||||
mFoldIndex: Symbol('mFoldIndex'), |
|
||||||
mFoldLayout: Symbol('mFoldLayout'), |
|
||||||
mColor: Symbol('mColor'), |
|
||||||
mTag: Symbol('mTag'), |
|
||||||
} |
|
||||||
|
|
||||||
function CategoriesHeader(color) { |
|
||||||
// 'use strict';
|
|
||||||
// ...
|
|
||||||
// this[symbolMap.listRule] = []
|
|
||||||
// this[symbolMap.subListRule] = []
|
|
||||||
this[symbolMap.mColor] = color || "#FA7298"; |
|
||||||
this[symbolMap.ruleObjList] = [] |
|
||||||
this.VARMAP = { |
|
||||||
CATEGORY: "header.category", |
|
||||||
URL: "header.url", |
|
||||||
FOLD: "header.fold", |
|
||||||
} |
|
||||||
this[symbolMap.mFoldLayout] = { |
|
||||||
injectIndex: 1 |
|
||||||
} |
|
||||||
this[symbolMap.mFoldIndex] = 1 |
|
||||||
} |
|
||||||
|
|
||||||
Object.assign(CategoriesHeader.prototype, { |
|
||||||
// Override 构造方法,相当于 function.prototype.constructor = (...) => {...},new function() 的时候会自动执行
|
|
||||||
constructor: CategoriesHeader, |
|
||||||
// 定义私有方法
|
|
||||||
VERSION: 202112011900, |
|
||||||
checkParams() { |
|
||||||
if (!this[symbolMap.mLayout]) { |
|
||||||
throw new Error("请调用 layout(d) 传入当前界面") |
|
||||||
} |
|
||||||
if (!(this[symbolMap.src] || this[symbolMap.true_url])) { |
|
||||||
throw new Error("请调用 trueUrl(url) 传入当前分类的链接或调用 html(mHtml) 传入当前分类页面的源码") |
|
||||||
} |
|
||||||
if (!this[symbolMap.mPage]) { |
|
||||||
throw new Error("请调用 page(mPage) 传入当前页数") |
|
||||||
} |
|
||||||
if (this[symbolMap.ruleObjList].length < 1) { |
|
||||||
throw new Error("请调用相关方法传入定位规则") |
|
||||||
} |
|
||||||
if (!this[symbolMap.mFold]) { |
|
||||||
this[symbolMap.mFold] = '0' |
|
||||||
} |
|
||||||
}, |
|
||||||
layout(mLayout) { |
|
||||||
this[symbolMap.mLayout] = mLayout |
|
||||||
return this |
|
||||||
}, |
|
||||||
trueUrl(url) { |
|
||||||
this[symbolMap.true_url] = url |
|
||||||
return this |
|
||||||
}, |
|
||||||
page(mPage) { |
|
||||||
if (typeof (mPage) === 'string') { |
|
||||||
mPage = parseInt(mPage) |
|
||||||
} |
|
||||||
this[symbolMap.mPage] = mPage |
|
||||||
return this |
|
||||||
}, |
|
||||||
html(mSrc) { |
|
||||||
this[symbolMap.src] = mSrc |
|
||||||
return this |
|
||||||
}, |
|
||||||
list(rule) { |
|
||||||
if (this[symbolMap.ruleObjList].length > 0) { |
|
||||||
throw new Error("list(rule) add(ruleObj) 只能二选一!") |
|
||||||
} |
|
||||||
this[symbolMap.ruleObjList] = [{}] |
|
||||||
this[symbolMap.ruleObjList][0].listRule = rule |
|
||||||
this[symbolMap.ruleObjList][0]['一级分类'] = rule |
|
||||||
return this |
|
||||||
}, |
|
||||||
subList(rule) { |
|
||||||
if (this[symbolMap.ruleObjList].length > 1) { |
|
||||||
throw new Error("subList(rule) add(ruleObj) 只能二选一!") |
|
||||||
} |
|
||||||
if (!this[symbolMap.ruleObjList][0] || (!this[symbolMap.ruleObjList][0].listRule && !this[symbolMap.ruleObjList][0]['一级分类'])) { |
|
||||||
throw new Error("请先调用 list(rule) 或 一级分类(rule) 定位一级分类") |
|
||||||
} |
|
||||||
this[symbolMap.ruleObjList][0].subListRule = rule |
|
||||||
this[symbolMap.ruleObjList][0]['子分类'] = rule |
|
||||||
return this |
|
||||||
}, |
|
||||||
title(rule) { |
|
||||||
if (this[symbolMap.ruleObjList].length > 1) { |
|
||||||
throw new Error("title(rule) add(ruleObj) 只能二选一!") |
|
||||||
} |
|
||||||
if (!this[symbolMap.ruleObjList][0] || (!this[symbolMap.ruleObjList][0].listRule && !this[symbolMap.ruleObjList][0]['一级分类'])) { |
|
||||||
throw new Error("请先调用 list(rule) 或 一级分类(rule) 定位一级分类") |
|
||||||
} |
|
||||||
this[symbolMap.ruleObjList][0].titleRule = rule |
|
||||||
this[symbolMap.ruleObjList][0]['分类标题'] = this[symbolMap.ruleObjList][0].titleRule |
|
||||||
return this |
|
||||||
}, |
|
||||||
url(rule) { |
|
||||||
if (this[symbolMap.ruleObjList].length > 1) { |
|
||||||
throw new Error("url(rule) add(ruleObj) 只能二选一!") |
|
||||||
} |
|
||||||
if (!this[symbolMap.ruleObjList][0] || (!this[symbolMap.ruleObjList][0].listRule && !this[symbolMap.ruleObjList][0]['一级分类'])) { |
|
||||||
throw new Error("请先调用 list(rule) 或 一级分类(rule) 定位一级分类") |
|
||||||
} |
|
||||||
this[symbolMap.ruleObjList][0].urlRule = rule |
|
||||||
this[symbolMap.ruleObjList][0]['分类链接'] = this[symbolMap.ruleObjList][0].urlRule |
|
||||||
return this |
|
||||||
}, |
|
||||||
/** |
|
||||||
* 是否开启折叠功能 |
|
||||||
* |
|
||||||
* @param enabled true 表示开启,false 表示禁用 |
|
||||||
* @returns {CategoriesHeader} |
|
||||||
*/ |
|
||||||
foldInner(enabled) { |
|
||||||
if (!(typeof (enabled) === 'boolean')) { |
|
||||||
throw new Error("请传入 true 或 false 表示开启或关闭折叠功能!") |
|
||||||
} |
|
||||||
this[symbolMap.mFoldInnerEnable] = enabled |
|
||||||
return this |
|
||||||
}, |
|
||||||
/** |
|
||||||
* 从第 index 行开始折叠 |
|
||||||
* |
|
||||||
* @param index 开始折叠的行数 |
|
||||||
* @returns {CategoriesHeader} |
|
||||||
*/ |
|
||||||
foldIndex(index) { |
|
||||||
if (!(typeof (index) === 'number')) { |
|
||||||
throw new Error("开始折叠行请传入数字!") |
|
||||||
} |
|
||||||
if (index < 1) { |
|
||||||
throw new Error("开始折叠行请传入大于 0 的整数!") |
|
||||||
} |
|
||||||
this[symbolMap.mFoldIndex] = index || 1; |
|
||||||
return this |
|
||||||
}, |
|
||||||
/** |
|
||||||
* 折叠按钮的界面 |
|
||||||
* |
|
||||||
* @param layout 与 d.push 结构一致, |
|
||||||
* 例:{ title:"标题1", url:"xxx", col_type:"scroll_button" }; |
|
||||||
* 参数采用可选覆盖模式,不写的参数则使用默认; |
|
||||||
* 比如传入 { col_type:"text_1" },那最终结果就是 { title:"标题1", url:"xxx", col_type:"text_1" } |
|
||||||
* @returns {CategoriesHeader} |
|
||||||
*/ |
|
||||||
foldLayout(layout) { |
|
||||||
if (typeof layout === 'object') { |
|
||||||
let keys = Object.keys(layout) |
|
||||||
let injectIndex = layout.injectIndex || layout['折叠按钮插入行'] |
|
||||||
if (layout.title || layout.url || layout.col_type || injectIndex) { |
|
||||||
for (let i = 0; i < keys.length; i++) { |
|
||||||
const key = keys[i] |
|
||||||
this[symbolMap.mFoldLayout][key] = layout[key]; |
|
||||||
} |
|
||||||
} else { |
|
||||||
throw new Error("请传入正确的折叠界面元素!") |
|
||||||
} |
|
||||||
// injectIndex 折叠按钮插入第 injectIndex 行
|
|
||||||
if (injectIndex) { |
|
||||||
if (!(typeof (injectIndex) === 'number')) { |
|
||||||
throw new Error("折叠按钮插入行请传入数字!") |
|
||||||
} |
|
||||||
if (injectIndex < 1) { |
|
||||||
throw new Error("折叠按钮插入行请传入大于 0 的整数!") |
|
||||||
} |
|
||||||
if (injectIndex > this[symbolMap.mFoldIndex]) { |
|
||||||
throw new Error("折叠按钮插入行不得大于显示折叠行数!请调用 .foldIndex(index) 或 .第几行开始折叠(index) 传入正确的显示折叠行数") |
|
||||||
} |
|
||||||
this[symbolMap.mFoldLayout].injectIndex = injectIndex || 1; |
|
||||||
} |
|
||||||
} else { |
|
||||||
throw new Error("请传入正确的折叠界面元素!") |
|
||||||
} |
|
||||||
return this; |
|
||||||
}, |
|
||||||
// 当前是否折叠
|
|
||||||
fold(isFold) { |
|
||||||
if (typeof (isFold) === 'string') { |
|
||||||
isFold = isFold === '1' |
|
||||||
} |
|
||||||
if (isFold) { |
|
||||||
this[symbolMap.mFold] = '1'; |
|
||||||
} else { |
|
||||||
this[symbolMap.mFold] = '0'; |
|
||||||
} |
|
||||||
return this |
|
||||||
}, |
|
||||||
color(mColor) { |
|
||||||
this[symbolMap.mColor] = mColor |
|
||||||
return this |
|
||||||
}, |
|
||||||
tag(mTag) { |
|
||||||
this[symbolMap.mTag] = mTag |
|
||||||
return this |
|
||||||
}, |
|
||||||
add(ruleObj) { |
|
||||||
// log($.stringify(ruleObj))
|
|
||||||
if (ruleObj.constructor === Array) { |
|
||||||
this[symbolMap.ruleObjList] = this[symbolMap.ruleObjList].concat(ruleObj) |
|
||||||
} else { |
|
||||||
this[symbolMap.ruleObjList].push(ruleObj) |
|
||||||
} |
|
||||||
return this; |
|
||||||
}, |
|
||||||
evalJSRule(item, jsRule) { |
|
||||||
let rule = jsRule.replace("@js:", "") |
|
||||||
rule = rule.trim() |
|
||||||
// log($.stringify(rule))
|
|
||||||
let input = item |
|
||||||
if (rule.startsWith("(")) { |
|
||||||
eval('result = ' + rule) |
|
||||||
} else { |
|
||||||
/** |
|
||||||
* 还原成 $.toString(...) 的最终结果,达到最终处理方式跟上面的 if 一致的目的 |
|
||||||
*/ |
|
||||||
eval('result = ' + '(() => {' + rule + '})()') |
|
||||||
} |
|
||||||
return (result || '') |
|
||||||
}, |
|
||||||
getTitle(src, category) { |
|
||||||
let title = '' |
|
||||||
let titleRule = category.titleRule || 'a&&Text' |
|
||||||
if (titleRule.startsWith("@js:")) { |
|
||||||
title = this.evalJSRule(src, titleRule) |
|
||||||
} else { |
|
||||||
title = parseDomForHtml(src, titleRule) |
|
||||||
} |
|
||||||
return title.trim() || ""; |
|
||||||
}, |
|
||||||
getUrl(src, category) { |
|
||||||
let url = '' |
|
||||||
let urlRule = category.urlRule || 'a&&href' |
|
||||||
if (typeof urlRule === 'object') { |
|
||||||
let mUrlRule = urlRule.rule || urlRule['解析规则'] || 'a&&href'; |
|
||||||
if (mUrlRule.startsWith("@js:")) { |
|
||||||
url = this.evalJSRule(src, mUrlRule); |
|
||||||
} else { |
|
||||||
let parse = parseDom; |
|
||||||
if (urlRule.parseOption) { |
|
||||||
switch (urlRule.parseOption) { |
|
||||||
case "parseDom": |
|
||||||
case "pd": |
|
||||||
parse = parseDom; |
|
||||||
break; |
|
||||||
case "parseDomForHtml": |
|
||||||
case "pdfh": |
|
||||||
parse = parseDomForHtml; |
|
||||||
break; |
|
||||||
default: |
|
||||||
parse = parseDom; |
|
||||||
} |
|
||||||
} else if (urlRule["解析方法"]) { |
|
||||||
switch (urlRule["解析方法"]) { |
|
||||||
case "parseDom": |
|
||||||
case "pd": |
|
||||||
parse = parseDom; |
|
||||||
break; |
|
||||||
case "parseDomForHtml": |
|
||||||
case "pdfh": |
|
||||||
parse = parseDomForHtml; |
|
||||||
break; |
|
||||||
default: |
|
||||||
parse = parseDom; |
|
||||||
} |
|
||||||
} |
|
||||||
url = parse(src, mUrlRule); |
|
||||||
} |
|
||||||
if (urlRule.dealUrl) { |
|
||||||
url = urlRule.dealUrl(url) |
|
||||||
} else if (urlRule['二次处理']) { |
|
||||||
url = urlRule['二次处理'](url) |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (urlRule.startsWith("@js:")) { |
|
||||||
url = this.evalJSRule(src, urlRule); |
|
||||||
} else { |
|
||||||
url = parseDom(src, urlRule); |
|
||||||
} |
|
||||||
} |
|
||||||
return url || ""; |
|
||||||
}, |
|
||||||
build() { |
|
||||||
// 检测是否传入需要的参数
|
|
||||||
this.checkParams() |
|
||||||
// 每一个分类的唯一标识
|
|
||||||
let mTag = this[symbolMap.mTag] || "" |
|
||||||
//翻页 需要根据实际替换
|
|
||||||
const html = this[symbolMap.src] || request(this[symbolMap.true_url]) |
|
||||||
const empty = "hiker://empty" |
|
||||||
//获取列表
|
|
||||||
const categories = [] |
|
||||||
this[symbolMap.ruleObjList].map(ruleObj => { |
|
||||||
let list = [] |
|
||||||
let listRule = ruleObj.listRule || ruleObj["一级分类"] |
|
||||||
if (listRule.startsWith("@js:")) { |
|
||||||
// log($.stringify(listRule))
|
|
||||||
list = this.evalJSRule(html, listRule) |
|
||||||
} else { |
|
||||||
list = parseDomForArray(html, listRule) |
|
||||||
} |
|
||||||
// log(list)
|
|
||||||
list.map(category => { |
|
||||||
categories.push({ |
|
||||||
list: category, |
|
||||||
subListRule: ruleObj.subListRule || ruleObj["子分类"], |
|
||||||
titleRule: ruleObj.titleRule || ruleObj["分类标题"], |
|
||||||
urlRule: ruleObj.urlRule || ruleObj["分类链接"], |
|
||||||
}); |
|
||||||
}) |
|
||||||
}) |
|
||||||
|
|
||||||
// log($.stringify(categories))
|
|
||||||
|
|
||||||
let init_cate = [] |
|
||||||
for (let i = 0; i < 20; i++) { |
|
||||||
init_cate.push("0") |
|
||||||
} |
|
||||||
|
|
||||||
const cate_temp_json = getMyVar(mTag + this.VARMAP.CATEGORY, JSON.stringify(init_cate)) |
|
||||||
const cate_temp = JSON.parse(cate_temp_json) |
|
||||||
|
|
||||||
if (this[symbolMap.mPage] === 1) { |
|
||||||
|
|
||||||
categories.forEach((category, index) => { |
|
||||||
|
|
||||||
// 折叠 UI
|
|
||||||
if (this[symbolMap.mFoldInnerEnable] && this[symbolMap.mFoldLayout].injectIndex === (index+1)) { |
|
||||||
let foldLayout = { |
|
||||||
title: this[symbolMap.mFoldLayout].title || (this[symbolMap.mFold] === '1' ? '““””<b><span style="color: #FF0000">∨</span></b>' : '““””<b><span style="color: #1aad19">∧</span></b>'), |
|
||||||
url: this[symbolMap.mFoldLayout].url || $("hiker://empty#noHistory#").lazyRule((params) => { |
|
||||||
putMyVar(params.mTag + params.VARMAP.FOLD, getMyVar(params.mTag + params.VARMAP.FOLD, params.isFold) === '1' ? '0' : '1') |
|
||||||
refreshPage(false); |
|
||||||
return "hiker://empty" |
|
||||||
}, { |
|
||||||
mTag: mTag, |
|
||||||
isFold: this[symbolMap.mFold], |
|
||||||
VARMAP: this.VARMAP |
|
||||||
}), |
|
||||||
col_type: this[symbolMap.mFoldLayout].col_type || "scroll_button", |
|
||||||
} |
|
||||||
this[symbolMap.mLayout].push(foldLayout) |
|
||||||
} |
|
||||||
|
|
||||||
//具体列表下的分类
|
|
||||||
let sub_categories = []; |
|
||||||
if (category.subListRule.startsWith("@js:")) { |
|
||||||
sub_categories = this.evalJSRule(category.list, category.subListRule) |
|
||||||
} else { |
|
||||||
sub_categories = parseDomForArray(category.list, category.subListRule); |
|
||||||
} |
|
||||||
if (index < (this[symbolMap.mFoldIndex] || 1)) { |
|
||||||
sub_categories.forEach((item, key) => { |
|
||||||
let title = this.getTitle(item, category) |
|
||||||
let url = this.getUrl(item, category) |
|
||||||
|
|
||||||
this[symbolMap.mLayout].push({ |
|
||||||
title: key.toString() === cate_temp[index] ? '““””<b><font color=' + this[symbolMap.mColor] + '>' + title + ' </font></b>' : title, |
|
||||||
url: $(url).lazyRule((params) => { |
|
||||||
let new_cate = [] |
|
||||||
if (params.index === 0) { |
|
||||||
params.cate_temp.forEach((cate, index) => { |
|
||||||
new_cate.push(index === 0 ? params.key.toString() : "0") |
|
||||||
}); |
|
||||||
} else { |
|
||||||
params.cate_temp[params.index] = params.key.toString() |
|
||||||
} |
|
||||||
putMyVar(params.tag + params.VARMAP.CATEGORY, JSON.stringify(params.index === 0 ? new_cate : params.cate_temp)) |
|
||||||
putMyVar(params.tag + params.VARMAP.URL, input) |
|
||||||
refreshPage(true) |
|
||||||
return "hiker://empty" |
|
||||||
}, { |
|
||||||
cate_temp: cate_temp, |
|
||||||
index: index, |
|
||||||
VARMAP: this.VARMAP, |
|
||||||
tag: mTag, |
|
||||||
key: key, |
|
||||||
page: this[symbolMap.mPage], |
|
||||||
}), |
|
||||||
col_type: 'scroll_button', |
|
||||||
}) |
|
||||||
}) |
|
||||||
this[symbolMap.mLayout].push({ |
|
||||||
col_type: "blank_block" |
|
||||||
}); |
|
||||||
} else if (this[symbolMap.mFold] === '0') { |
|
||||||
sub_categories.forEach((item, key) => { |
|
||||||
let title = this.getTitle(item, category) |
|
||||||
let url = this.getUrl(item, category) |
|
||||||
|
|
||||||
this[symbolMap.mLayout].push({ |
|
||||||
title: key.toString() === cate_temp[index] ? '““””<b><font color=' + this[symbolMap.mColor] + '>' + title + ' </font></b>' : title, |
|
||||||
url: $(url).lazyRule((params) => { |
|
||||||
params.cate_temp[params.index] = params.key.toString() |
|
||||||
|
|
||||||
putMyVar(params.tag + params.VARMAP.CATEGORY, JSON.stringify(params.cate_temp)) |
|
||||||
putMyVar(params.tag + params.VARMAP.URL, input) |
|
||||||
refreshPage(true) |
|
||||||
return "hiker://empty" |
|
||||||
}, { |
|
||||||
cate_temp: cate_temp, |
|
||||||
index: index, |
|
||||||
VARMAP: this.VARMAP, |
|
||||||
tag: mTag, |
|
||||||
key: key, |
|
||||||
page: this[symbolMap.mPage], |
|
||||||
}), |
|
||||||
col_type: 'scroll_button', |
|
||||||
}) |
|
||||||
}) |
|
||||||
this[symbolMap.mLayout].push({ |
|
||||||
col_type: "blank_block" |
|
||||||
}); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
界面(layout) { |
|
||||||
return this.layout(layout) |
|
||||||
}, |
|
||||||
分类链接(trueUrl) { |
|
||||||
return this.trueUrl(trueUrl); |
|
||||||
}, |
|
||||||
页码(page) { |
|
||||||
return this.page(page); |
|
||||||
}, |
|
||||||
源码(html) { |
|
||||||
return this.html(html); |
|
||||||
}, |
|
||||||
定位一级分类(list) { |
|
||||||
return this.list(list); |
|
||||||
}, |
|
||||||
定位子分类(subList) { |
|
||||||
return this.subList(subList); |
|
||||||
}, |
|
||||||
定位分类标题(title) { |
|
||||||
return this.title(title); |
|
||||||
}, |
|
||||||
定位分类链接(url) { |
|
||||||
return this.url(url); |
|
||||||
}, |
|
||||||
开启内置折叠功能() { |
|
||||||
return this.foldInner(true); |
|
||||||
}, |
|
||||||
关闭内置折叠功能() { |
|
||||||
return this.foldInner(false); |
|
||||||
}, |
|
||||||
第几行开始折叠(index) { |
|
||||||
return this.foldIndex(index); |
|
||||||
}, |
|
||||||
折叠按钮样式(layout) { |
|
||||||
return this.foldLayout(layout) |
|
||||||
}, |
|
||||||
折叠(fold) { |
|
||||||
return this.fold(fold); |
|
||||||
}, |
|
||||||
选中的分类颜色(color) { |
|
||||||
return this.color(color); |
|
||||||
}, |
|
||||||
唯一标识(mTag) { |
|
||||||
return this.tag(mTag) |
|
||||||
}, |
|
||||||
添加分类定位(ruleObj) { |
|
||||||
return this.add(ruleObj); |
|
||||||
}, |
|
||||||
开始打造分类() { |
|
||||||
return this.build(); |
|
||||||
}, |
|
||||||
|
|
||||||
}) |
|
||||||
$.exports = new CategoriesHeader(); |
|
||||||
$.exports |
|
Loading…
Reference in new issue