eallion

大大的小蜗牛

机会总是垂青于有准备的人!
mastodon
github
twitter
steam
telegram
keybase
email

Hugo External Link Redirect Prompt Page

Preface#

Recently, I saw a blog post by "Uncle Qin" titled "Website Restart" mentioning that due to an expired domain left by someone in the blog comments linking to a pornographic website, it led to issues related to pornography. This shows that in the current online environment in mainland China, such minor offenses are being cracked down on more strictly.

To comply and self-censor, I did two things for my blog: first, I migrated the comment system to Giscus, which raised the threshold for comments and put them in a semi-closed state; second, I cleaned up some links in the blog, allowing the remaining links to redirect through a landing page. Coincidentally, I saw "Kongbai" update their blog "HUGO External Link Redirect to Intermediate Page", and I directly copied the style, completing one item on my Todo list.

PS: I believe that a serious personal website can be filed for record. But if you want to do something less serious, what you need is complete identity isolation, not just avoiding filing while exposing many related cross-identity information. No paternalism, love it or leave it.

Definition#

External Link: Fully known as an external link, also known as an inbound link. It refers to links from other websites on the internet that lead to one's own website. Hereinafter referred to as "external link."

Creating a Redirect Page with 3 Files#

My design approach is somewhat different from the first version of "Kongbai's" JS method. I utilized Hugo's built-in template _markup's render-link.html to base64 encode external links during Hugo's build process using Hugo's built-in base64Encode command, fully leveraging the features of SSG.

1. Create or Modify render-link.html#

_markup/render-link.html is Hugo's built-in template for rendering links. If the theme selected for the blog does not have a custom render-link.html, you need to create this file yourself. If the theme has already customized link rendering, you can directly modify this file. The file is located in the layouts directory at the root of the Hugo project:

layouts/
└── _default/
    └── _markup/
        ├── render-codeblock-bash.html
        ├── render-codeblock.html
        ├── render-heading.html
        ├── render-image.html
        ├── render-image.rss.xml
        └── render-link.html    # < --- This file

The content of the file I used:

$domainList serves as a whitelist.

{{- $domainList := slice "www.eallion.com" "github.com" "twitter.com" -}}
{{- $parsedDestination := urls.Parse .Destination -}}
{{- $host := $parsedDestination.Host -}}
{{- $matched := false -}}
{{- range $domainList -}}
    {{- if strings.HasSuffix $host . -}}
        {{- $matched = true -}}
        {{- break -}}
    {{- end -}}
{{- end -}}
{{- if $matched -}}
    <a href="/go/?target={{ .Destination }}" target="_blank" rel="noopener noreferrer">{{ .Text | safeHTML}}</a>
{{- else -}}
    <a href="/go/?target={{ .Destination | base64Encode }}" target="_blank" rel="noopener noreferrer">{{ .Text | safeHTML}}</a>
{{- end -}}

PS: For the DoIt theme, you only need to modify layouts/partials/plugin/link.html.

Tips: Using render-link.html allows the blog to open in a new window, i.e., target="_blank". Many Asian users are searching for this trick.

2. Create Layout Template go.html#

Create a page template, such as go.html, located in the layouts/_default/go.html of the Hugo project root. A simple way is to copy single.html and rename it to go.html.

layouts/
└── _default/
    └── go.html    # < --- This file

Here is my content, placing HTML, CSS, and JS in the same page for easier maintenance. Besides ensuring that the <div class="redirect-all"> element is in the correct position in your template, it is basically ready to use.

{{- define "title" }}{{ .Title }} - {{ .Site.Title }}{{ end -}}

{{- define "content" -}}
    {{- $params := .Scratch.Get "params" -}}
    <style>
        .redirect-all {
            position: relative;
            box-shadow: rgba(0, 0, 0, 0.25) 0px 25px 50px -12px;
            border-radius: 10px;
            color: #666;
            word-break: break-all;
            max-width: 800px;
            height: 400px;
            text-align: center;
            font-size: 0.85rem;
            overflow: hidden;
            margin: 100px auto 0;
            background: #fff url(/assets/images/redirect/redirect-light.webp) no-repeat center center / cover;
            @include breakpoint('small') {
                aspect-ratio: 2 / 1;
                height: auto;
            }
        }

        .redirect-nrong {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            padding: 1.5rem 1rem
        }

        .redirect-title {
            font-size: 1.25rem;
            font-weight: bold;
            color: #222;
            margin-bottom: 0.5rem;
        }

        .redirect-info {
            margin-top: 6px;
        }

        .redirect-tis {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 20px;
            margin-top: 1rem;
            margin-bottom: 2px;
            flex-wrap: wrap;
        }

        .redirect-button {
            display: flex;
            align-items: center;
            border-radius: 3px;
            border: none;
            background: #006bee;
            height: 32px;
            padding: 0 14px;
            cursor: pointer;
            outline: 0;
        }

        .redirect-button a {
            color: #fff !important;
        }

        [theme=dark] .redirect-all {
                background: #fff url(/assets/images/redirect/redirect-dark.webp) no-repeat center center / cover;
                color: #999;
            }

        [theme=dark] .redirect-title {
                color: #ddd;
            }
    </style>

    <div class="page single special">

        {{- /* Content */ -}}
        <div class="content" id="content">
            <div class="redirect-all">
                <div class="redirect-nrong">
                    <div class="redirect-title">You are about to leave {{ .Site.Title }} and redirect to the following external link</div>
                    <a href="" target="_self" rel="noopener noreferrer" id="redirect-link"><span id="redirect-link">Redirect target not specified.</span></a>
                    <div class="redirect-info">Please identify whether this link is safe, and pay attention to your account and property security.</div>
                    <div class="redirect-tis">
                        <div class="redirect-button"><a href='' target="_self" id='direct-link' rel="noopener noreferrer">Go Now</a></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        const params = new URLSearchParams(window.location.search);
        const encodedTarget = params.get('target');
        const target = atob(encodedTarget); // Use atob for Base64 decoding

        if (target) {

            const decodedTarget = decodeURIComponent(target);

            document.getElementById('direct-link').href = decodedTarget;
            document.getElementById('redirect-link').textContent = '' + decodedTarget; // Display the original address in the new element
            document.getElementById('redirect-link').href = decodedTarget;

        } else {
            const redirectMessageElement = document.getElementById('redirect-link');
            redirectMessageElement.textContent = 'Redirect target not specified.';
        }
        </script>
{{- end -}}

3. Create go.md to Call the Template#

In the content directory of the Hugo project, create a file named go.md, where go will be the link path for the redirect page. The Front matter of the go.md file should select the corresponding template you just created; if the template name is go.html, then the layout or type should be set to go.

---
title: "Redirect"
layout: "go"
type: "go"
... ...
---
4. Background Image#

Place the background image in the static directory:
or in a location you can reference correctly, such as a CDN, and modify the background url in the <style>. Additionally, you need to adapt it to your theme's Dark mode.

  • static/assets/images/redirect/redirect-light.webp
  • static/assets/images/redirect/redirect-dark.webp

Other Considerations#

This method can only render all Markdown content documents in this blog, i.e., .md files in the content directory. If you are accustomed to using {{ Shortcodes }} for posting, or if the page has custom HTML links, you need to make the link path base64 compatible yourself. This template can parse links like href="/go/?target={{ base64Encode }}" within the blog, excluding the whitelist.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.