// ==UserScript==
// @name 收藏控 · 链接清洗
// @version 1.2.6
// @author 极品小猫
// @description 把链接地址缩减至最短可用状态,并复制到剪切板,以方便分享。【在每个页面的底部中间,有一个小小的按钮,用来呼出面板】
// @namespace https://greasyfork.org/users/3128
// @homepage https://greasyfork.org/users/3128
// @icon https://s1.ax1x.com/2020/08/13/dSUEsU.png
// @supportURL
// @updateURL
// @downloadURL
// @include *://*/*
// @require https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js
// @grant GM_setClipboard
// @grant GM_notification
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_info
// @license MIT
// @noframes
// @downloadURL https://update.greasyfork.icu/scripts/414335/%E6%94%B6%E8%97%8F%E6%8E%A7%20%C2%B7%20%E9%93%BE%E6%8E%A5%E6%B8%85%E6%B4%97.user.js
// @updateURL https://update.greasyfork.icu/scripts/414335/%E6%94%B6%E8%97%8F%E6%8E%A7%20%C2%B7%20%E9%93%BE%E6%8E%A5%E6%B8%85%E6%B4%97.meta.js
// ==/UserScript==
/****
*
2021-11-13
1、改进 Param 参数获取通过 URLSearchParams 获得
2、改进 Rules 规则表,设定保留参数
3、改进 自定义规则生成逻辑,应用保留参数设定
4、改进 自定义规则配置应用方法,通过 URLSearchParams 函数删除参数
*
*/
/** 主功能函数 **/
(function(){
let webUrl=location.href,
webOrigin=location.origin;
webHost=location.host.toLowerCase(),
webSearch=location.search,
webPathname=location.pathname;
console.log(GM_info);
const rules = { //预定义规则
'mp.weixin.qq.com':{
//testReg: /^http(?:s)?:\/\/.+/i, // //'', /s?__biz=MzUxMjMxOTE0Nw==&mid=2247531927&idx=1&sn=ba1327de710ee8116f567f5d20f393cc
//replace: '',
reserveQuery: ['biz','mid','idx','sn'], //保留的参数
hash: false
},
'www.bilibili.com': {/* Blibili */
testReg: /^http(?:s)?:\/\/www\.bilibili\.com\/video\/(av\d+).*$/i,
replace: 'https://www.bilibili.com/$1',
reserveQuery: ['p'],
hash: true
},
'itunes.apple.com': {/* Apple Stroe */
testReg: /^http(?:s)?:\/\/itunes\.apple\.com\/(?:\w{2}\/)?([^\/]+)\/(?:[^\/]+\/)?((?:id)\d+).*$/i,
replace: 'https://itunes.apple.com/cn/$1/$2',
},
'chrome.google.com/webstore': {/* Chrome Store */
testReg: /^http(?:s)?:\/\/chrome\.google\.com\/webstore\/detail\/[^\/]+\/([a-z]{32}).*/i,
replace: 'https://chrome.google.com/webstore/detail/$1',
},
's.taobao.com': {/* Taobao Search */
testReg: /^http(?:s)?:\/\/s\.taobao\.com\/search.*$/i,
replace: 'https://s.taobao.com/search',
reserveQuery: ['q'],
},
'list.tmall.com': {/* Tmall Search */
testReg: /^http(?:s)?:\/\/list\.tmall\.com\/search_product\.htm.*$/i,
replace: 'https://list.tmall.com/search_product.htm',
reserveQuery: ['q'],
},
'item.taobao.com': {/* Taobao item */
testReg: /^http(?:s)?:\/\/item\.taobao\.com\/item\.htm.*$/i,
replace: 'https://item.taobao.com/item.htm',
reserveQuery: ['id'],
},
'detail.tmall.com': {/* Tmall item */
testReg: /^http(?:s)?:\/\/detail\.tmall\.com\/item\.htm.*$/i,
replace: 'https://detail.tmall.com/item.htm',
reserveQuery: ['id'],
},
'taobao/tmall.com/shop': {/* Taobao/Tmall Shop */
testReg: /^http(?:s)?:\/\/(\w+)\.(taobao|tmall)\.com\/shop\/view_shop\.htm.*$/i,
replace: 'https://$1.$2.com/',
},
'c.pc.qq.com': {/* Open Taobao share link from QQ */
testReg: /^http(?:s)?:\/\/c\.pc\.qq\.com\/middle.html\?.*pfurl=([^&]*)(?:&.*$|$)/i,
replace: '$1',
reserveQuery: [],
methods: ['decodeUrl'],
},
'item.m.jd.com': {/* JD mobile to PC */
testReg: /^http(?:s)?:\/\/item\.m\.jd\.com\/product\/(\d+)\.html(\?.*)?$/i,
replace: 'https://item.jd.com/$1.html',
},
'item.m.jd.com/ware/': {/* JD mobile to PC */
testReg: /^http(?:s)?:\/\/item\.m\.jd\.com\/ware\/view\.action\?.*wareId=(\d+).*$/i,
replace: 'https://item.jd.com/$1.html',
},
'search.jd.com': {/* JD Search */
testReg: /^http(?:s)?:\/\/search\.jd\.com\/Search\?.*$/i,
reserveQuery: ['keyword', 'enc'],
},
're.jd.com': {/* JD hot sell */
testReg: /^http(?:s)?:\/\/re\.jd\.com\/cps\/item\/(\d+)\.html.*$/i,
replace: 'https://item.jd.com/$1.html',
},
'weibo.com/u': {/* Weibo personal homepage to mobile */
testReg: /^http(?:s)?:\/\/(?:www\.)?weibo\.com\/u\/(\d+)(\?.*)?$/i,
replace: 'https://m.weibo.cn/$1',
},
'weibo.com': {/* Weibo article page to mobile */
testReg: /^http(?:s)?:\/\/(?:www\.)?weibo\.com\/(?:\d+)\/(\w+)(\?.*)?$/i,
replace: 'https://m.weibo.cn/status/$1',
},
'greasyfork.org': {/* Greasyfork Script */
testReg: /^http(?:s)?:\/\/(?:www\.)?greasyfork\.org\/(?:[\w-]*\/)?scripts\/(\d+)-.*$/i,
replace: 'https://greasyfork.org/zh-CN/scripts/$1',
},
'store.steampowered.com|steamcommunity.com': {/* Steam */
testReg: /^http(?:s)?:\/\/(store\.steampowered|steamcommunity)\.com\/app\/(\d+).*$/i,
replace: 'https://$1.com/app/$2',
},
'meta.appinn.com': {/* Appinn BBS */
testReg: /^http(?:s)?:\/\/meta\.appinn\.net\/t(?:\/[^/]*)*?\/(\d+)(\/.*$|$)/i,
replace: 'https://meta.appinn.net/t/$1',
},
'amazon.co.jp': {/* amazon.co.jp */
testReg: /^http(?:s)?:\/\/(?:www\.)?amazon\.co\.jp\/([^\/]+)\/dp\/(\w+)\/.*$/i,
replace: 'https://www.amazon.co.jp/$1/dp/$2',
},
'yangkeduo.com': {/* Pin Duo Duo product Page */
testReg: /^http(?:s)?:\/\/mobile\.yangkeduo\.com\/goods.html\?.*$/i,
reserveQuery: ['goods_id'],
},
'other': {/* All url */
testReg: /^(http(?:s)?:\/\/[^?#]*)[?#].*$/i,
reserveQuery: ['id', 'tid', 'uid', 'q', 'wd', 'query', 'keyword'],
}
}
/** 必须函数 */
let localConfig=localStorage['Cat_LC_Config']?JSON.parse(localStorage['Cat_LC_Config']):{"param":[], testReg:'', OpenMode:'history'};
const LinkCleaner={
webRule : rules[webHost],
theUrlParam : new URLSearchParams(webSearch),
theUrlParamKeys : [],
reserveQueryJSON : {},
param_Count : function(search, len){ //分割参数,获取参数key
let Params=new URLSearchParams(search||location.search),
theUrlParam=[];
for(let key of Params.keys()) {
theUrlParam.push(key);
}
//const theUrlParam=search.replace(/^\?/,'').split('&');
if(len) return theUrlParam.length;
return theUrlParam;
},
PureUrl : function(url){
switch(localConfig.OpenMode) {
case 'location':
if(window.location.href !== url) window.location.href = url;
default:
case 'history':
history.pushState('', '', url);
break;
}
},
Cat_get_pure_url : function(url){
url = url||window.location.href;
const hash = url.replace(/^[^#]*(#.*)?$/, '$1')
const base = url.replace(/(\?|#).*$/, '')
let pureUrl = url
const getQueryString = function(key) {
let ret = url.match(new RegExp('(?:\\?|&)(' + key + '=[^?#&]*)', 'i'))
return ret === null ? '' : ret[1]
}
/* 链接处理方法 */
const methods = {
decodeUrl: function(url){return decodeURIComponent(url) }
}
for(let i in rules){
let rule = rules[i]
let reg = rule.testReg
let replace = rule.replace
if (reg.test(url)){
let newQuerys = ''
if(typeof(rule.reserveQuery)!=='undefined' && rule.reserveQuery.length>0){
rule.reserveQuery.map((reserveQuery) => {
const ret = getQueryString(reserveQuery)
if(ret !== '') newQuerys += (newQuerys.length ? '&' : '?') + ret;
})
}
newQuerys += typeof(rule.hash)!=='undefined' && rule.hash ? hash : '';
pureUrl = (typeof(replace)==='undefined'?base:url.replace(reg, replace) ) + newQuerys;
if(typeof(rule.methods)!=='undefined' && rule.methods.length>0){
rule.methods.map((methodName)=>{
pureUrl = methods[methodName](pureUrl)
})
}
break;
}
}
return pureUrl;
},
/* 复制净化后的链接和标题 */
getCleanUrlAndTitle : function(){
const pureUrl = this.Cat_get_pure_url();
const ttileAndUrl = document.title + ' \n' + pureUrl;
GM_setClipboard(ttileAndUrl);
CatCLNotification('链接地址已净化,并和网站标题一起复制到剪切板中~');
PureUrl(pureUrl);
},
/* 复制净化后的链接 */
getCleanUrl : function(){
const pureUrl = this.Cat_get_pure_url();
GM_setClipboard(pureUrl);
CatCLNotification('链接地址已净化并复制到剪切板中~');
PureUrl(pureUrl);
},
/* 直接复制页面链接和标题 */
getUrlAndTitle : function(){
const theUrl = document.title + ' \n' + window.location.href;
GM_setClipboard(theUrl);
CatCLNotification('网站标题 & 链接地址已复制到剪切板中~');
this.CatLCToggleEl();
},
/*** 面板切换 ***/
CatLCToggleEl : function(el){
el = document.querySelector('#Cat_lc_panel');
if(!el) return false;
$(this).toggleClass('show');
$(this).find('span').toggleClass('show');
$('#Cat_lc_panel').slideToggle('fast', 'linear');
},
/* 清理整个页面 */
cleanAllPage : function(){
console.log(this);
const aTagEles = document.getElementsByTagName('a');
for (let i = 0; i < aTagEles.length; i++) {
let theLink = aTagEles[i].href;
if (theLink.match(/^(http:\/\/|https:\/\/|\/\/)/) !== null) {
theLink = theLink.replace(/^\/\//, 'https://');
aTagEles[i].href = Cat_get_pure_url(theLink);
}
}
//panel.style.display = '';
CatCLNotification('页面中所有链接已净化~\n可能导致部分链接无法使用,刷新后恢复。');
this.CatLCToggleEl();
},
CustomRule : function(search){
const CR=$('#Cat_lc_panel_CustomRule');
if(CR.css('display')=='none') {
const theUrlParam=this.param_Count();
const p=$('
'),
UrlRule=new RegExp(location.href.replace(/\/[^/]+(\.\w+)?\/?\?.+/, '\/.+$1').replace(/\/%[^/]+/,'').replace(/\//g,'\\/'), 'i'),
SaveBtn=$('').attr({type: 'button', id:'lc_CustomRule_SaveBtn'}).val('应用配置'),
CloseBtn=$('').attr({type: 'button', id:'lc_CustomRule_CloseBtn'}).val('关闭'),
UrlText=$('').attr({type: 'text', id:'lc_CustomRule_UrlRule', placeholder:'网址匹配采用正则表达式', title:'网址匹配采用正则表达式'}).val(localConfig['testReg']||UrlRule),
Option_Auto=$('