koobai
HUGO 外链跳转到中间页

前天在老麦博客中看到" 给Twikoo添加链接跳转中间页“博文,因为外部链接你无法确定未来某一天可能就会变成不安全链接,从而影响到自己博客。同时又见到 大大的小蜗牛也是因为安全的原因,把博客评论换成了GitHub Discussions。网上也有不少的案例,因为某个链接的原因,而被请喝茶或电话让自己排查。今天在 不亦乐乎那见链接也是跳转到中间页,于是请教了下怎么实现的,感谢。之后经过与 AI 的博弈,搞定。这次使用 ChatGPT 跟 Claude 都不行,说了一堆,完全不懂,最后使用 coze 搞定基本框架,然后再来回沟通逐步完善功能。估计跟它使用的 ChatGPT 4.0 接口有关。想充值 ChatGPT,奈何月费太贵了。

新建 js 文件,如:tiaozhuan.js。里面的网址为排除跳转中间页。

function checkParent(element, classNames) {
while (element) {
if (element.classList && classNames.some(cn => element.classList.contains(cn))) {
return true;
}
element = element.parentElement;
}
return false;
}
var excludedClasses = ['talks_comments','tiaozhuan-button']; // 添加需要排除的a标签类名class
window.addEventListener('load', (event) => {
document.body.addEventListener('click', function(e) {
let target = e.target;
while (target && target.nodeName !== 'A') {
target = target.parentNode;
}
if (target && target.nodeName === 'A' &&
!checkParent(target, excludedClasses) &&
!target.href.includes('koobai.com') &&
!target.href.includes('douban.com') &&
!target.href.includes('bilibili.com') &&
!target.href.includes('github.com') &&
target.hostname !== window.location.hostname) {
e.preventDefault();
let encodedUrl = btoa(target.href); // Base64 encode the URL
let url = '/tiaozhuan?target=' + encodedUrl;
window.open(url, '_blank');
}
});
});

在模板_default目录下,新建一个 html,如tiaozhuan.html。

{{ define "body_classes" }}page-tiaozhuan{{ end }}
{{ define "main" }}
<div class="tiaozhuan-all">
  <div class="tiaozhuan-nrong">
    <div class="tiaozhuan-title">即将离开 {{ .Site.Title }},跳转到以下外部链接</div>
    <div id="tiaozhuan-link"></div> 
    <div class="tiaozhuan-info">请自行识别该链接是否安全,并保管好个人信息。</div>
      <div class="tiaozhuan-button"><a href='' id='direct-link'>继续访问</a></div>
  </div>
</div>
<script>
  const params = new URLSearchParams(window.location.search);
  const encodedTarget = params.get('target');
  const target = atob(encodedTarget); // 使用 atob 进行 Base64 解码
  
  if (target) {
    document.getElementById('direct-link').href = target;
    document.getElementById('tiaozhuan-link').textContent = '' + target; // 直接显示目标地址    
  } else {
    console.error('未指定重定向目标。');
  }
</script>
{{ end }}

相关 css,根据主题风格调整。其中 background 为明暗模式下不同的背景图。

.tiaozhuan-all{
  position: relative;
  box-shadow: rgba(0, 0, 0, 0.25) 0px 25px 50px -12px;
  border-radius: 10px;
  background: #fff url(/tiaozhuanico.webp) no-repeat center center / cover;
  color: #666;
  word-break: break-all;
  max-width: 700px;
  height: 350px;
  text-align: center;
  font-size: 0.85rem;
  overflow: hidden;
  margin: 100px auto 0; 
  @include breakpoint('small') {
    aspect-ratio: 2 / 1;
    height: auto;
  }
}
.tiaozhuan-nrong{
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 20px 20px 30px 20px;
}
.tiaozhuan-title{
  font-size: 1.3rem;
  font-family: var(--font-family-title);
  color: #222;
  line-height: 1.4;
  margin-bottom: 4px;
}
.tiaozhuan-info{
  margin-top: 6px;
}
.tiaozhuan-button{
  margin-top: 20px;
}

.tiaozhuan-button a{
  color: var(--text-highlight-color);
  border-radius: 4px;
  padding: 10px 30px;
  font-family: var(--font-family-title);
  font-size: 0.85rem;
  border: 0.5px solid var(--text-highlight-color);
  display: inline-block;
}

@media (prefers-color-scheme: dark) {
  .tiaozhuan-all{
    background: var(--background-dark-color) url(/tiaozhuandark.webp) no-repeat center center / cover;
    color: #acacac;
  }
  .tiaozhuan-title{
    color: #ddd;
  }
}

最后在页尾引用js文件即可,如

<script src="/js/tiaozhuan.js"></script>

搞定,整体思路是:js文件识别链接的a标签,并把链接用 base64 编码,同时排除一些不需要跳转中间页的class或网站。然后跳转到tiaozhuan.html文件中(链接格式为/tiaozhuan?target=base64编码),html文件承担了中间页具体信息,及跳转动作。如使用base64解码跳转的链接。

以上为全局引用JS方法,判断 a 标签。下面利用 Hugo 内置的 render-link.html 实现。在模板_default/_makup目录下新建 render-link.html文件。思路是直接给链接添加 “/tiaozhuan?target=base64编码”。下面代码中的 “/” 为排除内链;网址为排除特定地址。感谢 大大的小蜗牛提示的 render-link 方法。

{{ $url := .Destination }}
<a 
    {{ if or (in $url "koobai.com") (strings.HasPrefix $url "/") }}
        href="{{ $url }}"
    {{ else }}
        href="/tiaozhuan?target={{ $url | base64Encode }}"
    {{ end }}
    {{ if strings.HasPrefix .Destination "http" }} target="_blank"{{ end }}
>
{{ .Text | safeHTML }}</a>

针对无法给链接添加 “/tiaozhuan?target=base64编码” 的,譬如 Artalk 评论,可以特定使用 js 判断。里面的.atk-comment-wrap a 就是 Artalk 评论的 a 标签;网址为排除特定地址。

document.body.addEventListener('click', function(e) {
  let target = e.target.closest('.atk-comment-wrap a, .datacont a');
  if (target && !target.href.includes('koobai.com')) {
      e.preventDefault();
      let encodedUrl = btoa(target.href);
      let url = '/tiaozhuan?target=' + encodedUrl;
      window.open(url, '_blank');
  }
});

对于浏览体验来说,多了一步跳转,总归是不好,但为了愉快的玩耍博客,稳妥一点更佳。现在把各个页面的评论都去掉了,只留下了唠叨跟博文评论,并且把博文的评论默认设为隐藏。倒也不是因为所谓的安全,主要是觉得评论的样式有待提高。

如果觉得跳转中间页很烦人,浏览器可以装个 Skip Redirect插件,告别所有网站的中间页跳转,直接抵达目标地址。

更新于
评论一下 ...
回到顶部