Update Notes

恭喜你找到了隐藏页面:本站更新笔记。
这里不仅有版本更新记录,还会有一些折腾的笔记和教学。
如果能帮到你,我会很高兴!
(站长不是程序员,没有任何程序基础,纯属素人瞎摸,随时欢迎提出意见或建议并帮助我…!)

当前部署在

Vercel+同时在Netlify有个备份=Verlify wink

当前使用的工具

Hugo v0.143.1 darwin/amd64
Hugo中文文档(版本较旧需注意)

更新笔记

5.7
  • 更新Hugo至0.143版本,总算告别旧版本了!
  • 增加自定义表情,让Hugo自带的丑丑emoji见鬼去吧!wink
    • 示例:同时支持内联丑丑 Emoji 🐱 和 自定义图片 wao hehe atten heng
  • 代码复制按钮总算弄上来了,最终还是DeepSeek给我搞了个外挂js解决 升级后使用render-codeblock即可实现!
  • 给首页的文字也增加了自定义表情的功能,本来想用来提示哪里有更新,但后来想想每次更新还要重新打开上一次有更新的页面,太麻烦了算了
  • 取消了原本自定义的OpenGraph,用新版自带的就行。不过教学还是留下了
    新版自带的跟twittercards的id有冲突,加上不能自动读到文章标题,还是换回老的了。唉!
  • 搬回Vercel了,因为发现了个好东西:解决国内访问Vercel较慢的问题
    • 同时增加静态缓存(仅图片),加快读取速度(应该能)
    • 取消了页面底部的留言框,那是Netlify的特权ai
  • 顺便脱离了越来越坑钱的阿里云,把域名交给大家都爱的CloudFlare了!好耶!
  • 给本页书签增加一个链接按钮,可以一键复制地址,并且会自动识别是否有书签,没有则不出现按钮
  • 修改了小红书(这平台挺恶心的)和RSS的ICON图标!感谢熊鑫伟(cubxxw)的简体中文博客,舒服多了
  • 改了一下favicon和og的图片,换新的了!但About处还是保留了老图
5.6
  • 增加代码高亮但是代码复制按钮怎么都加不上,chatGPT都帮不了我 已解决,见5.7更新
  • 修正一些本页笔记中的代码
  • 过了一下W3C,没毛病,很爽
  • 增加了适配bilibili的短代码视频插入
  • 增加RSS,可以在侧边栏或干脆点此订阅
    • 顺便更改本页为index.md文章页,方便RSS读取
    • 更改RSS输出为全文,使用Papermod的rss.xml为模版(怎会如此)
    • 如果不想要某些页面输出RSS,可以将那个页面设置为_index.md作为目录页
  • 将尾注的build小图更改为短代码
  • 增加一些双向认证链接,但并没有全部生效 都生效了
  • 增加「文章最后更新日期」,并修复Netlify特有的时间bug
  • 新增留言表单,就在本页末尾,使用Netlify自带的服务
  • 这个RSS图标为啥会在hover的时候出现一圈边框呢?! 解决不了,先不用了 在5.7中解决了
  • 搬运了一些教程,请爱护原作者
  • 开启Hugo自带的emoji,虽然很丑 :man_shrugging: 关闭了,替换为自定义表情,详见5.7更新笔记
5.5
  • 更新飞书图标,但还没美化 美化了,直接换了IconPark
  • 更改custom.css的路径,使其脱离原主题文件夹(终于全部自定义内容脱离完毕!)
  • 新增此Update页面
  • 写了点教学……就整理在本页下面
  • 增加运行天数 参考
  • 更改选中时的底色
  • 修复了链接mouseover时后面会多出一个空格的bug!感谢大佬们
5.4
  • 更改标题字体为"Tilt Neon",为了国内访问速度,将字体下载后放在了css/fonts文件夹……
  • Font Awesome的版本为最新,更换读取Kit包
  • 更改部署至Netlify
5.3
5.2
5.1
  • 新增网站内容
5.0
  • 重新开始制作此网站,用Hugo构建
  • 在Vercel上部署完毕并公开

修改Hugo主题时的通用注意事项

  1. 建议将所有修改过的文件均放在layouts或static目录中,以便日后升级theme时不造成妨碍。
    所有的html相关文件均在Hugo的根目录/themes/主题名/layouts目录下。此目录下的全部文件均可直接复制至根目录/layouts/下,Hugo在发布时会将根目录/layouts/里的内容替换掉主题自带的themes/主题名/layouts/里的文件。
    同理,新建的文件也可以直接在根目录/layouts/下建立。
  2. CSS文件的路径不同。自定义的css文件需要放在根目录/static/css/下,才能正常覆盖掉主题自带的css。
    JS文件、图片等同CSS,分别在jsimg文件夹下。

这样一来就可以无痛无脑更新主题,而不用担心自己的自定义内容全消失了。


给网站添加OpenGraph标签

这样做可以方便在SNS上进行图片及内容的预览,让网址被分享时更美观易用。主要代码来自FUJI Theme,不仅有og,还有twitter card! 就像这样:

og sample

理论上所有不带OG标签的主题都适用,此处就以「hugo-creative-portfolio-theme」主题为例。

  1. /layouts/partials/head.html的任意一处增加以下内容:
<!-- og -->
{{ partial "opengraph.html" . }}
  1. /layouts/partials/目录下增加opengraph.html,并写入以下内容:
<!-- 整个都是从FUJI theme复制的!标题等有略微修改 -->
<!-- 更改Home的OG标题,避免输出2个相同标题 by 猫鱼 -->
{{- if .IsHome -}}
<meta property="og:title" content="{{ .Site.Title }}" />
<meta name="twitter:title" content="{{ .Site.Title }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:url" content="{{ .Permalink }}" />
{{- else -}}
<meta property="og:title" content="{{ .Title }} - {{ .Site.Title }}" />
<meta name="twitter:title" content="{{ .Title }} - {{ .Site.Title }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:url" content="{{ .Permalink }}" />
{{- end -}}
<!-- end -->

{{- if .Description -}}
<meta property="og:description" content="{{ .Description }}" />
<meta name="twitter:description" content="{{ .Description }}" />
{{- else if .Params.description -}}
<meta property="og:description" content="{{ .Params.description }}" />
<meta name="twitter:description" content="{{ .Params.description }}" />
{{- else -}}
{{- if .IsPage -}}
<meta property="og:description" content="{{ .Summary }}" />
<meta name="twitter:description" content="{{ .Summary }}" />
{{- end -}}
{{- end -}}

{{- if .Params.image -}}
<meta property="og:image" content="{{ .Params.image | absURL }}" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="{{ .Params.image | absURL }}" />
{{- else if .Site.Params.og -}}
<meta property="og:image" content="{{ .Site.Params.og | absURL }}" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="{{ .Site.Params.og | absURL }}" />
{{- else -}}
<meta name="twitter:card" content="summary" />
{{- end -}}

{{- $iso8601 := "2006-01-02T15:04:05-07:00" -}}
{{- if .IsPage -}}
{{- if not .PublishDate.IsZero -}}
<meta property="article:published_time" {{ .PublishDate.Format $iso8601 | printf "content=%q" | safeHTMLAttr }} />
{{- else if not .Date.IsZero -}}
<meta property="article:published_time" {{ .Date.Format $iso8601 | printf "content=%q" | safeHTMLAttr }} />
{{- end -}}
{{- if not .Lastmod.IsZero -}}
<meta property="article:modified_time" {{ .Lastmod.Format $iso8601 | printf "content=%q" | safeHTMLAttr }} />
{{- end -}}
{{- else -}}
{{- if not .Date.IsZero -}}
<meta property="og:updated_time" {{ .Lastmod.Format $iso8601 | printf "content=%q" | safeHTMLAttr }} />
{{- end -}}
{{- end -}}
  1. config.toml增加og参数:
# 增加OG图片
  og = "/img/你的图片名.jpg"

这样就完成了。这个主题不自带OG,作为作品集来说缺少了很重要的部分,因此添加上了。


在「hugo-creative-portfolio-theme」主题中取消默认的文件夹路径「portfolio/」,将地址栏固定为「/」

访问网站后地址栏显示「cat-fish.net」而非「cat-fish.net/portfolio」,感觉好多了!

将地址栏固定为「/」

根据此Commit进行修改。 如果没有main.html,可以自己新建一个。

atten 注意:原文中将protfolio全部改为artical并新增了main.html、之后又将原portfolio文件夹改名为artical。如果你像我一样不想更改文件夹名,可以将main.html里的{{ range (site.GetPage "artical").Pages }}改为{{ range (site.GetPage "portfolio").Pages }}

(此处的page可以定义到任何一个page从而让它在首页显示出来,相当于替代了config.toml里的index=true

修复首页OG中标题重复的问题

这样更改后首页的标题可能会出现重复title的问题(即文章标题和网站标题重复),原主题根本没有OG,所以也没有遇到这个问题,我自行修复了!可以在<head>里或opengraph.html里这样更改:

<!-- 更改Home的OG标题,避免输出2个相同标题 by 猫鱼 https://cat-fish.net/ -->
{{- if .IsHome -}}
<meta property="og:title" content="{{ .Site.Title }}" />
<meta name="twitter:title" content="{{ .Site.Title }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:url" content="{{ .Permalink }}" />
{{- else -}}
<meta property="og:title" content="{{ .Title }} - {{ .Site.Title }}" />
<meta name="twitter:title" content="{{ .Title }} - {{ .Site.Title }}" />
<meta property="og:type" content="{{ if .IsPage }}article{{ else }}website{{ end }}" />
<meta property="og:url" content="{{ .Permalink }}" />
{{- end -}}
<!-- end -->

这样就可以避免首页出现重复的标题了。

PS:如果你按照本站的这篇添加了OpenGraph图片预览功能,则不用再处理标题重复的问题,因为那篇里已经修改完毕了。


修正正文内容的所有链接均被打开新窗口的问题

根据这篇文章,可以自动在有外链(正文内带有http及https开头的地址)时,在外链的文字后面加上一个打开新窗口的小箭头图示。

但是,根据原文直接做的话,正文内不管是不是外链的地址,都会被打开新窗口。 这样就没有小箭头存在的意义了,所以需要把它解决一下。方法如下:

layouts/_default/_markup/render-link.html里的内容替换成如下:

{{- if strings.HasPrefix .Destination "http" -}}<a href="{{- .Destination | safeURL -}}"{{ with .Title}} title="{{- . -}}"{{ end }} target="_blank" rel="noopener">{{- .Text | safeHTML -}}<span style="white-space: nowrap;"><svg width=".7em" height=".7em" viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg"><path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor"/><path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z" fill="currentColor"></svg></span></a>{{- else -}}<a href="{{- .Destination | safeURL -}}"{{ with .Title}} title="{{- . -}}"{{ end }}>{{- .Text | safeHTML -}}</a>{{- end }}

增加了一个判断,只有当链接是外链时才打开新窗口并增加小箭头图示,反之则渲染成普通的链接即可。使用Markdown写的内容也都适用。例如:

[文字链接](https://cat-fish.net) #这条会被加上小箭头并打开新窗口
[文字链接](/update/) #这条就是普通的链接

atten 注意: 代码中的小箭头图示用的是原文的图示(方块形)。如果需要使用本站的圆形图示,可以参考IconPark的用法,和Font Awesome很类似,但更简单,非常推荐。

PS: 代码已更新(2024/5/6),加上注释的话会多一个空格,我真是服了这HTML,把注释杀了就好了。顺便优化成了单行代码。


增加代码高亮功能

根据Hugo的官方文档,可以启用自带的Chroma代码高亮功能。
(我有不加载过多js文件的PTSD,所以没有选择js渲染)

  1. config.toml里添加如下设置:
# 增加代码高亮,来自hugo官方
[markup]
[markup.highlight]
  anchorLineNos = false
  codeFences = true #代码框,默认启用
  guessSyntax = true #自动推测代码类别
  hl_Lines = ''
  hl_inline = false
  lineAnchors = ''
  lineNoStart = 1
  lineNos = false
  lineNumbersInTable = true
  noClasses = true #是否启用自带样式,默认为是
  noHl = false
  style = 'monokailight' #样式主题
  tabWidth = 4
  1. 由于我的guessSyntax没有自动识别出任何代码(怎会如此),因此需要自己指定一下代码类型。在任意可写Markdown的地方这样写:
```html
// ... 代码放这里面
```

```后面直接增加想要指定的代码种类就行。有效的类型列表在这里
这样就能直接使用Hugo自带的快速高亮了!

自定义代码框的高亮样式

对Chroma自带的高亮样式不满意?可以自定义。参考Hugo文档
方法:

  1. 禁用Chroma自带的样式:
noClasses = false
  1. 在命令行里输入以下命令,下载CSS文件:
hugo gen chromastyles --style=monokailight > syntax.css

记得将monokailight改为你想下载的css主题名字。
下载后的文件会在Hugo根目录里。

  1. 将下载的synatx.css挪动到static/css下。

  2. <head>里适当的位置引用这个css:

<link href="{{ "css/syntax.css" | absURL }}" rel="stylesheet">

完成!修改这个CSS文件即可自定义自己的样式了。

顺便一提……
因为我用的monokailight这个主题的高亮对于展示html+hugo简码不是很友好,把一大堆东西都误标记成错误代码了,所以我很直接的改了一下报错的背景色,让它显得不那么显眼……鸵鸟式处理。

调整代码框的相对位置

原本代码框的位置有点微妙,看了一下是mk写的东西自动带<p>,导致代码框上面有一个空行,下面又空间不足。所以调一下就好了,在css里插入:

pre { margin:-15px 0 20px 0; }

即可。具体的参数可以根据自己的需求调整。

为代码框添加复制按钮

有新旧两种版本,主要是因为旧版Hugo不支持render-codeblock。

Hugo v0.143适用
  1. static/js/里新建custom.js并复制以下代码:
function copyCode(button) {
  // 找到代码框内容
  const codeBlock = button.nextElementSibling;
  const codeText = codeBlock.innerText;

  // 使用 Clipboard API 复制文本
  navigator.clipboard.writeText(codeText)
    .then(() => {
      // 提示复制成功
      button.textContent = "已复制!";
      setTimeout(() => {
        button.textContent = "复制";
      }, 2000); // 2 秒后恢复按钮文字
    })
    .catch((err) => {
      console.error("复制失败: ", err);
      button.textContent = "复制失败";
    });
}
  1. 修改layouts/_default/_markup/render-codeblock.html的内容,添加以下:
    (如果没有这个文件则新建一个)
<div class="code-block-wrapper">
  <button class="copy-button" onclick="copyCode(this)">复制</button>
  {{ highlight .Inner .Type }}
</div>
  1. 在css里添加:
/* 代码框容器 */
.code-block-wrapper {
  position: relative; /* 为按钮定位提供参考 */
}

/* 复制按钮 */
.copy-button {
  position: absolute; /* 绝对定位 */
  top: 0.5em;         /* 距离顶部 */
  right: 0.5em;       /* 距离右侧 */
  padding: 0.25em 0.5em;
  font-size: 0.875em;
  background-color: #f5f5f5;
  border: 1px solid #ddd;
  border-radius: 3px;
  cursor: pointer;
  opacity: 0.6;
  transition: opacity 0.2s;
}

/* 鼠标悬停时显示按钮 */
.code-block-wrapper:hover .copy-button {
  opacity: 1;
}

/* 按钮点击效果 */
.copy-button:active {
  background-color: #e0e0e0;
}
  1. 在head或footer里引用js文件:
<script src="{{ "js/custom.js" | relURL }}"></script>
Hugo v0.88适用

由于版本太低导致无法使用hugo自带的复制按钮,于是暂时用外挂js曲线救国一下。

  1. static/js/里新建custom.js并复制以下代码:
// 整个都是叫ds写的,我看都没看,能用(hugo v0.88)
function copyCode(button) {
  const codeBlock = button.nextElementSibling;
  const codeText = codeBlock.querySelector('code').innerText;

  // 调试:打印代码内容
  console.log("代码内容:", codeText);

  // 兼容旧版浏览器的复制逻辑
  if (navigator.clipboard) {
    // 使用 Clipboard API
    navigator.clipboard.writeText(codeText)
      .then(() => {
        updateButtonText(button, "已复制!");
      })
      .catch((err) => {
        console.error("复制失败: ", err);
        updateButtonText(button, "复制失败");
      });
  } else {
    // 使用 document.execCommand 作为备选方案
    const textarea = document.createElement('textarea');
    textarea.value = codeText;
    document.body.appendChild(textarea);
    textarea.select();
    try {
      document.execCommand('copy');
      updateButtonText(button, "已复制!");
    } catch (err) {
      console.error("复制失败: ", err);
      updateButtonText(button, "复制失败");
    }
    document.body.removeChild(textarea);
  }
}

// 更新按钮文字
function updateButtonText(button, text) {
  button.textContent = text;
  if (text !== "复制") {
    setTimeout(() => {
      button.textContent = "复制";
    }, 2000);
  }
}

// 动态插入按钮
document.addEventListener("DOMContentLoaded", function() {
  const highlights = document.querySelectorAll('.highlight');

  highlights.forEach(highlight => {
    const button = document.createElement('button');
    button.className = 'copy-button';
    button.textContent = '复制';
    button.onclick = function() { copyCode(this); };

    const wrapper = document.createElement('div');
    wrapper.className = 'code-block-wrapper';
    highlight.parentNode.insertBefore(wrapper, highlight);
    wrapper.appendChild(button);
    wrapper.appendChild(highlight);
  });
});
  1. 参考新版Hugo的步骤3和步骤4即可。

添加bilibili短代码播放器

短代码播放器总是需要一个的。
参考这篇教学添加了播放器,只需要写一个短代码就好了。

添加shortcodes短代码
  1. layouts/shortcodes/里新建一个叫bilibili.html的文件,并写入以下代码:
<!-- 语法规则
    1. 匿名模式
        <bilibili BV1Wg411t7EE 233>
    2. 具名模式
        <bilibili 
            src="https://www.bilibili.com/video/BV1RK41117eY/" 
            page="332"
        >
-->

<!-- 获取第一个参数 作为视频地址 -->
{{- $dest := ( .Get 0) -}}

<!-- 如果是具名模式, 获取 src -->
{{ if .IsNamedParams }}
    {{ $dest = (.Get "src") }}
{{ end }}

<!-- 判断是否为 全路径, 是则获取视频ID -->
{{ if (hasPrefix $dest "http" )}}
    <!-- https://www.bilibili.com/video/BV1RK41117eY/ -->
    {{ $dest = (strings.TrimPrefix "http" $dest ) }}

    <!-- 解析 URL -->
    {{ $url := urls.Parse $dest }}

    <!-- /video/BV1RK41117eY/ -->
    {{ $dest = $url.Path }}

    <!-- BV1RK41117eY -->
    {{ $dest = (path.BaseName $dest) }}
{{ end }}


<!-- 获取专辑中的视频 ID -->
{{- $page := (.Get 1) -}}

{{ if .IsNamedParams }}
    {{ $page = (.Get "page") }}
{{ end }}

<!-- 默认值为 1 -->
{{ if (not $page) }}
    {{ $page = 1 }}
{{ end }}


<!-- 嵌入 bilibili 播放框 -->
<div style="margin: 10px 0 20px 0;">
  <!-- <h3>视频ID: {{ $dest }} - {{ $page }} </h3> -->
  <div style="position:relative; padding-bottom:75%; width:100%; height:0">
    <iframe src="//player.bilibili.com/player.html?bvid={{ $dest }}&page={{ $page }}&autoplay=0&muted=true"       
        scrolling="no" border="0"
        frameborder="no" 
        framespacing="0" 
        allowfullscreen="true" 
        style="position:absolute; height: 100%; width: 100%;">
    </iframe>
  </div>
</div>
  1. 在需要插入视频的地方写:
{{< bilibili BV号 分集号 >}}

或者这么写:

{{< bilibili src="视频地址" page="分集号" >}}

就完成了,非常简单。bilibili可以替换成任何词,只要能对应就行。

默认静音+不自动播放

在原文的基础上增加了静音与不自动播放,我最讨厌自动播放了,必须干掉它才能安心睡觉。
办法很简单,在iframe src地址里加上&autoplay=0&muted=true就可以了。(上面的代码里已经加上了)

不过话说回来,我也不喜欢iframe这个标签就是了……而且bili的播放器好丑……


添加文章最后更新日期,并修复Netlify的日期bug

参考这篇文章,给所有页面(除了About和Contact这种不需要更新日期的)的底部添加了最后更新日期。对于作品集来说非常有用!
但是,果然也遇到了Netlify的构建会导致文章的修改时间失效的问题。本地预览时正确的,但部署上去后就全变成部署的日期了。这样不就没有意义了嘛……
好在找到了这篇文章里提供的方法解决了这个bug。
如果你像我一样不知道去哪找netlify.toml,可以参考这篇文章来自己建立一个文件,并把它上传到GitHub。
……好吧,我把全部的步骤写一下,免得出现一大堆404:

添加文章的最后更新日期
  1. 将以下代码添加进single.html中合适的部分(通常在{{ .Content }}{{ .main }}后面),或者任意你想显示的地方:
{{ if ne (.Lastmod.Format "2006-01-02") (.Date.Format "2006-01-02") }}
<p>最后更新于: {{ .Lastmod.Year }}/{{ printf "%d" .Lastmod.Month }}/{{ .Lastmod.Day }}</p>
{{ end }}
  1. 设置config.toml文件
enableGitInfo = true
[frontmatter]
  lastmod = [":git", "lastmod", ":fileModTime"]

本地能正确显示的话就是成功了。

修正Netlify部署时的时间错误bug
  1. 如果你没有netlify.toml,那就在Hugo的根目录新建一个,并写入以下设置:
[build]
publish = "public"
# command = "hugo --gc --minify" 修改时间bug
command = '''find content -name '*.md' | while read file; do touch -d "$(git log -1 --format="@%ct" "$file")" "$file"; done; hugo --gc --minify'''

[context.production.environment]
HUGO_VERSION = "0.88.1" #请根据自己的 Hugo 版本进行修改
HUGO_ENV = "production"
HUGO_ENABLEGITINFO = "true"

[context.split1]
command = "hugo --gc --minify --enableGitInfo"

[context.split1.environment]
HUGO_VERSION = "0.88.1" #请根据自己的 Hugo 版本进行修改
HUGO_ENV = "production"

[context.deploy-preview]
command = "hugo --gc --minify --buildFuture -b $DEPLOY_PRIME_URL"

[context.deploy-preview.environment]
HUGO_VERSION = "0.88.1" #请根据自己的 Hugo 版本进行修改

[context.branch-deploy]
command = "hugo --gc --minify -b $DEPLOY_PRIME_URL"

[context.branch-deploy.environment]
HUGO_VERSION = "0.88.1" #请根据自己的 Hugo 版本进行修改

[context.next.environment]
HUGO_ENABLEGITINFO = "true"
  1. 将它和Hugo的其他文件一起上传到GitHub就行了,Netlify会自动部署的,这样部署后的日期也是正确的了。

使用Netlify自带的服务建立留言表单

Netlify很好心的提供基础的表单服务,免费用户一个月可以收100封,支持自定义成功页面,自定义邮件提醒,支持防spam机器人,支持ajax提交等,十分nice!心动不如行动,马上整一个玩玩。
例子就在本页末尾,以下代码均以此为例。

建立基础HTML表单
  1. 登入Netlify后台,找到「Forms」,点击「Enable」启用表单功能。
  2. 在任意需要插入表单的地方写入以下代码(也可以做成短代码):
<form
  name="update-page-form"
  method="POST"
  netlify-honeypot="bot-field"
  data-netlify="true"
>
  <!-- 蜜罐领域 -->
  <p class="hidden">
    <label>
      Don’t fill this out if you’re human: <input name="bot-field" />
    </label>
  </p>
  <div class="chat-input">
    <input type="text" name="message" placeholder="如果有任何bug或想说的...">
    <button type="submit">Send</button>
  </div>
</form>

以上代码默认开启了防spam功能(机翻:蜜罐领域),没有特殊问题的话建议保留。
表单是纯HTML的,各个字段都可以自己更改,注意必须要有name="自定义字段",不然后台读不到内容。

  1. 在css里增加如下样式:
.chat-input {
    display: flex;
    align-items: center;
    width: 100%;
    border: 1px solid #ccc;
    border-radius: 5px;
    padding: 8px;
    margin: 50px 0 20px 0;
}
.chat-input input {
    flex: 1;
    border: none;
    outline: none;
    font-size: 14px;
    padding:0 0 0 8px;
}
.chat-input button {
    background-color: #ef5285;
    color: white;
    border: none;
    border-radius: 5px;
    padding: 8px 12px;
    margin-left: 8px;
    cursor: pointer;
}
.chat-input button:hover {
    background-color: #c7254e;
}

颜色等可以自己更改。大功告成!

自定义发送成功页面
  1. 在Hugo里新建一个页面。根据主题不同,方法也不同,这里仅写出针对「hugo-creative-portfolio-theme」主题的方法:
  • 复制about文件夹,并将其改名为success
  • layouts/下新建success/list.html,并写入以下代码:
{{ define "main" }}
<div class="col-xs-12 col-sm-8 col-md-9 content-column white-background">
{{ partial "mobile_nav_toggle.html" . }}
<div class="row">
  <div class="col-lg-8">
    <div class="content-column-content">
       <h1>{{ .Title }}</h1>
       {{ .Content }}
       <button onclick="goBack()" class="btn btn-ghost">Back</button>
        <script>
        function goBack() {
          window.history.back();
        }
        </script>
    </div>
  </div>
</div>
</div>
{{ end }}
  • 打开success/_index.md,编辑内容
  • 在浏览器里输入(hugo的根目录,一般是localhost:1313)/success,确认页面是否能显示
  1. 确认页面能显示后,将form action="/success"插入到表单中:
<form
    name="update-page-form"
    action="/success"
    method="POST"
    netlify-honeypot="bot-field"
    data-netlify="true"
>
  ...
</form>

到这里就全部完成啦!

atten 注意:必须部署后才会生效,本地按发送是没用的。

启用邮件通知及自定义邮件通知的标题
  1. 在Netlify后台Forms > Form notifications > Form submission notifications处选择Add notification > Email notification,在里面写上邮件地址等
  2. 然后在Custom email subject line处自由编辑即可
  3. 更多变量可查看官方文档

为Hugo添加自定义表情图

没找到教学,原本叫chatGPT给我写个,结果这家伙不顶用,写的东西不能使!(具体表现为杜撰了一个$EmojiMap的参数叫我放进.site.params里)
隔了很久之后DeepSeek出现了,遂叫它给我写个,嘿,能用了!身体还是新的好。

以下是具体做法:

  1. 配置Emoji映射。在data/下创建一个叫emoji.yaml的文件并写入以下文字:
smile: "😊"
cat: "🐱"
custom: "/img/emoji/custom.png"

需要增加emoji的话在这个文件下继续添加或修改图片路径即可。 记得在图片文件夹内增加对应的图片(推荐svg)。

  1. layouts/partials/下创建一个叫emoji.html的文件,并写入以下内容:
{{ $content := . }}
{{ range $name, $value := site.Data.emoji }}
  {{ $pattern := printf ":%s:" $name }}
  {{ if hasPrefix $value "/" }}
    {{ $replacement := printf `<img src="%s" alt="%s" class="inline-emoji">` ($value | relURL) $name }}
    {{ $content = replace $content $pattern $replacement }}
  {{ else }}
    {{ $content = replace $content $pattern $value }}
  {{ end }}
{{ end }}
{{ return $content }}
  1. 找到文章模版(一般在layouts/_default/single.html),将原本的{{ .Content }}(或类似的东西)替换为:
{{ define "main" }}
  <article>
    {{ partial "emoji" .Content | safeHTML }}
  </article>
{{ end }}
  1. 在任意地方使用即可:
这是内联 Emoji :smile: 和自定义图片 :custom:。
  1. 按需添加CSS样式:
/* 确保表情图片是内联元素 */
.inline-emoji {
  display: inline; /* 确保图片是内联元素 */
  height: 1em;     /* 与文字高度一致 */
  width: auto;     /* 宽度自适应 */
  vertical-align: middle; /* 与文字垂直对齐 */
  margin: 0 0 0.2em 0; /* icon-park的svg图多少有点往下掉,稍微往上抬一点 */
}
/* 针对列表项的额外调整 */
ul li .inline-emoji,
ol li .inline-emoji {
  display: inline; /* 确保在列表项中也是内联元素 */
  vertical-align: middle; /* 与列表项的基线对齐 */
}

这样就完成了!wink


原本的主题不带有这个功能,正好今天想逃避工作,给它增加上了。hehe
特意让链接按钮仅在有【手动添加的】书签时才出现,避免全部渲染造成的视觉妨碍。
全部代码都用DeepSeek写成,希望它不要一直服务器繁忙了,害我出去遛弯儿了一圈才写好。

  1. 添加标题是否有书签的判断。
    将以下代码写入layouts/_default/_markup/render-heading.html,如果没有就新建一个:
{{ $level := .Level }}
{{ $text := .Text | safeHTML }}
{{ $autoID := $text | anchorize }}  {{/* Hugo 自动生成的 ID */}}
{{ $userID := .Anchor | safeURL }}  {{/* 用户手动指定的 ID(如有) */}}

{{ if and $userID (ne $userID $autoID) }}
  {{/* 用户手动指定了 {#id},且与自动生成的 ID 不同 */}}
  <h{{ $level }} id="{{ $userID }}">
    {{ $text }}
    <a href="#{{ $userID }}" class="header-link" aria-label="复制链接">
      <span class="link-icon">
        <svg width="20" height="20" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M30 19H20C15.5817 19 12 22.5817 12 27C12 31.4183 15.5817 35 20 35H36C40.4183 35 44 31.4183 44 27C44 24.9711 43.2447 23.1186 42 21.7084" stroke="#ef5285" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M6 24.2916C4.75527 22.8814 4 21.0289 4 19C4 14.5817 7.58172 11 12 11H28C32.4183 11 36 14.5817 36 19C36 23.4183 32.4183 27 28 27H18" stroke="#ef5285" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/></svg>
      </span>
    </a>
  </h{{ $level }}>
{{ else }}
  {{/* 无手动 ID,使用自动生成的 ID */}}
  <h{{ $level }} id="{{ $autoID }}">
    {{ $text }}
  </h{{ $level }}>
{{ end }}

这其中链接的图标使用了SVG图片,来自Icon Park,有需要随便自己改。

  1. 增加CSS使其美观(在static/css/custom.css里直接添加就好):
/* ds写的,通用样式:所有标题下的链接图标 */
.header-link {
  opacity: 0;
  transition: opacity 0.3s ease;
  text-decoration: none;
  color: #ef5285;
}

/* 鼠标悬停时显示链接图标 */
h1:hover .header-link,
h2:hover .header-link,
h3:hover .header-link,
h4:hover .header-link,
h5:hover .header-link,
h6:hover .header-link {
  opacity: 1;
}

/* 调整链接图标位置(可选) */
.header-link .link-icon {
  vertical-align: middle;
}
  1. 添加点击就能一键复制的功能,在static/js/custom.js里
  document.addEventListener('DOMContentLoaded', function () {
    document.querySelectorAll('.header-link').forEach(link => {
      link.addEventListener('click', function (event) {
        event.preventDefault();
        const anchor = this.getAttribute('href');
        const url = window.location.href.split('#')[0] + anchor;
        navigator.clipboard.writeText(url).then(() => {
          console.log('链接已复制:', url);
          const tooltip = document.createElement('div');
          tooltip.textContent = '链接已复制!';
          tooltip.style.position = 'fixed';
          tooltip.style.bottom = '20px';
          tooltip.style.right = '20px';
          tooltip.style.padding = '8px 16px';
          tooltip.style.background = '#333';
          tooltip.style.color = '#fff';
          tooltip.style.borderRadius = '4px';
          document.body.appendChild(tooltip);
          setTimeout(() => tooltip.remove(), 2000);
        }).catch(err => {
          console.error('复制失败:', err);
        });
      });
    });
  });

此方案可精准区分手动和自动生成的ID,确保仅显示需要的复制按钮。

Netlify Status

Last update: 2025 / 3 / 5
Running for 0 days.