From ccb4753756887738318c0d3c9daa918bcdb0d44f Mon Sep 17 00:00:00 2001 From: yeyangchen2009 <441551798@qq.com> Date: Wed, 16 Sep 2026 07:39:02 +0800 Subject: [PATCH] feat: add GmeekExternal plugin (open external links in new tab) --- plugins/GmeekExternal.js | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 plugins/GmeekExternal.js diff --git a/plugins/GmeekExternal.js b/plugins/GmeekExternal.js new file mode 100644 index 0000000..bb2e912 --- /dev/null +++ b/plugins/GmeekExternal.js @@ -0,0 +1,42 @@ +/* GmeekExternal —— 正文外链自动在新标签页打开 + * 作用域:#postBody 内的 (config 的 script 字段只注入文章页/固定页) + * 外链判定:交给 URL 构造器按 host 比较——绝对/协议相对/各种相对路径 + * 都能正确归类,自己站点的绝对 URL 不会误判 + * 安全:target=_blank 时补 rel=noopener(合并已有值,不覆盖) + * 不做:不自动加 nofollow(SEO 语义)、不强制 noreferrer(保留来源统计) + */ +(function () { + var body = document.getElementById('postBody'); + if (!body) return; + + var links = body.querySelectorAll('a[href]'); + Array.prototype.forEach.call(links, function (a) { + var u = toUrl(a.getAttribute('href')); + if (!u) return; // 锚点/mailto/tel/javascript/非法值 + if (u.hostname === location.hostname) return; // 站内链接原地跳 + + // 尊重作者显式声明(比如手写 target="_self") + if (!a.hasAttribute('target')) a.setAttribute('target', '_blank'); + mergeRel(a, 'noopener'); + }); + + function toUrl(href) { + if (!href) return null; + href = href.trim(); + if (!href || href.charAt(0) === '#') return null; + if (/^(mailto|tel|javascript):/i.test(href)) return null; + try { + return new URL(href, location.href); + } catch (e) { + return null; + } + } + + function mergeRel(a, token) { + var rels = (a.getAttribute('rel') || '').split(/[ \t]+/).filter(Boolean); + if (rels.indexOf(token) === -1) { + rels.push(token); + a.setAttribute('rel', rels.join(' ')); + } + } +})();