普通视图

发现新文章,点击刷新页面。
昨天以前首页

从 Hugo 迁移至 Ghost 后我都做了什么

作者 吕楪
2024年1月3日 20:08
从 Hugo 迁移至 Ghost 后我都做了什么

迁移到新的博客系统Ghost上,好似拿到了新玩具⛷️!东瞧瞧西瞅瞅,哪里都透着一点新鲜气儿。将界面与各种功能品鉴一番后,剩下需要迁移的文本内容堆积着,让我不仅又是一阵头疼:

“啊,怎么还要做这么多的事情啊。”

作为能把5分钟前还在和我讲话的人的面孔忘记的失忆症患者😨,我还是得写点东西做个备忘,认真贯彻“好记性不如烂笔头”的传统精神,以免忘记对Ghost动过什么手脚,防止玩脱了博客出错,那乐子可就大了😭。

先讲下都做过什么吧🤗:

  1. 设置Ghost管理面板相关内容

语言、元数据、更改博客的图标、开启搜索、公告栏、订阅、邮件相关(设置事务邮件与时事通讯)、代码注入、更改Waline评论系统、新链接页面打开、修改路由与重定向。

  1. 主题修改

使用的主题在中文状态下依然有部分英语,主要是时间格式的问题。(略微修改,先这样用用吧)。看着别的朋友的Ghost主题都好好看,但是在官方一看,哇,好贵!😖买个主题的授权,域名都能续费好多年了嘞🧨。

Ghost 安装与部署就不写了,毕竟一搜一大堆。

Ghost 管理面板

Ghost管理面板即Ghost Admin,是后端点击下方齿轮后的设置内容。

语言

Publication Language出设置语言为zh,这是Ghost官方的简体中文代码,而不是zh-Hans,好奇怪🤔。

🥳
推荐使用任何Ghost主题时,都在翻译文件拷贝一份翻译为zh.json,与Ghost官方保持一致。

图标

在一些无版权网站上随便找了一个花儿的图标,稍微修改下尺寸便匆匆上架。还是感觉不够好看呀,以后再改进改进!有朋友会做图标吗?👀

开启搜索

Advanced处的Integrations打开Add custom integration,输入名字后复制Admin API key处的内容,再点击Design & branding中的Customize,在Site wide处填入Search API key下的输入框保存激活。

从 Hugo 迁移至 Ghost 后我都做了什么
🥲
不过Ghost的搜索有点问题——中文的搜索力也太弱了。尝尝搜不出文章内的内容,标题也只能以开头来识别。

公告栏

Announcement bar即为公告栏,是我在Ghost中最喜欢的功能之一🎉。在自定义内容后会在博客全部页面的最上端出现一个小小的横幅来提醒来到博客的朋友。

从 Hugo 迁移至 Ghost 后我都做了什么

这里我没有修改,不过想要修改的朋友可以参考Ghost官方修改教程来做个更漂亮的!

How to add an offer banner to a Ghost site
Offers are often shared as a link in an email call to action, during a podcast, or via social media. But what if you want to display a special offer as a banner on your site, so all visitors can access it? Our tutorial gives you everything you need to add a beautiful offer banner to your site.
从 Hugo 迁移至 Ghost 后我都做了什么TutorialsTeam Ghost
从 Hugo 迁移至 Ghost 后我都做了什么

邮件系统

Newsletter的中文名字是时事通讯,不过讲中文的感觉好奇怪:这个名字英文听到的频率总比中文时候多😐。

因为邮件广告的泛滥,现在还支持群发邮件的厂商已经很少了!微软、谷歌等通过SMTP群发邮件会有极大的概率封禁。所以Ghsot也开始背靠邮件方面的“大厂——Mailgun”实现这个功能:Ghost中的邮件群发深度绑定Mailgun,所以在Ghost中实现时事通讯功能,我们只能通过注册Mailgun🤐来解决。

当然,还有一种我从使用Hugo博客时期想到的解决方案,那就是依然检测RSS变动,使用Zaiper联动Mailchimp解决,具体可以看我的《静态博客添加 Newsletter 的几种推荐方案》这篇文章。
静态博客添加 Newsletter 的几种推荐方案
经过朋友的评论启发,尝试为自己的静态博客添加 Newsletter 订阅方式,并先后使用 Mailchimp、Tinyletter、Substack、revue、Briefcake 得出总结。
从 Hugo 迁移至 Ghost 后我都做了什么山茶花舍吕楪
从 Hugo 迁移至 Ghost 后我都做了什么

如果不使用Zaiper,那么还可以自建Listmook,但这种方案推荐使用域名邮箱和服务器(不过Listmook可以使用Railway搭建)。

注册Mailgun

💡
Mailgun需要外币卡!

Mailgun现在每月免费邮件量从5000降至1000。唉,要是老用户就好了😭,还是原来的5000封邮件量限制。这里还有坑,大家需要注意!虽然pricing中有尝试免费计划的选项,但注册后是默认开启的一个月的Foundation计划!!在一个月后会从你卡中扣款!我在去年注册Mailgun时没有注意到这个问题,打开Mailgun的仪表板发现账户被冻结,并且有一张35美金的账单时才发现!幸亏外币卡我都是随用随充的,里面只有剩下的几美元,扣款失败哈哈哈。

所以我们需要:在注册后打开订阅计划页面,手动降级到FLEX计划。

从 Hugo 迁移至 Ghost 后我都做了什么

点击降级后会在下面提示你下个月是FLEX计划,在下个月后会变成上面这张图的样子,就不怕扣费拉🥳!

配置群发

仪表板 点击 senging后domains中点击Add New Domain,绑定mg.域名.com(或其他域名,Mailgun推荐使用mg子域名),Domain region选US或EU都可以,我是US🎉,然后再DNS服务提供商那里修改为Mailgun要求的指向内容。

点击右上角账户,选择API Security,在Mailgun API keys 处点击add new key,复制并保存API Keys

登录Ghost后台,打开Mailgun settings,点击edit更改。

Mailgun region-选择位置,Mailgun domain-你刚才设置的域名,Mailgun private API key处填写Apikeys内容,点击保存即可。

从 Hugo 迁移至 Ghost 后我都做了什么
💡
这时,你可以群发邮件啦,要不先写篇草稿试试能不能发你邮箱🤔?

事务邮件

事务邮件是指博客上的注册、评论、订阅成员的通知。

Mailgun控制台打开Domain Settings-SMTP credentials,点击右上角的Add nwe SMTP user 输入名字,添加完成后右下角会出现提示框,在其中复制密码保存后关闭窗口。

从 Hugo 迁移至 Ghost 后我都做了什么

登录服务器,打开Ghost的配置文件config.production.json

nano config.production.json

修改为:

"mail": { "transport": "SMTP", 
		 "options": { 
			 "service": "Mailgun", 
			 "auth": {
				"user": "你设置的SMTP账户", 
				"pass": "你复制的SMTP密码" 
				} 
			} 
	},

保存后,ghost stop 停止运行,然后ghost start重新启动就好啦。

订阅计划

我一直特别好奇Ghost中此功能是如何运行的,毕竟能接入一个支付系统真的是太酷了!

从 Hugo 迁移至 Ghost 后我都做了什么
💡
因为Stripe没有国内用户的注册方式,正常情况需要护照。

不过我没有使用护照页注册成功并连接到Ghost了,这里不做详解,毕竟要解释的内容太多了😭!如果有需要的朋友可以评论区或通过联系方式告诉我,如果需要开启方式的人比较多,我可以单独写一篇激活方式的文章🤔。

代码注入

添加google分析、prism.js代码高亮、umami分析、新链接页面打开、更改Waline主题色、修改路由与重定向等一大堆内容!

代码注入在Ghost控制台最下面,Code injection处点击edit编辑。

添加Google分析

Google分析处添加账号与媒体资源名称后,点击“数据搜集和修改”,打开数据流点击添加,类型选择网站,在设置完毕后找到追踪代码拷贝。

从 Hugo 迁移至 Ghost 后我都做了什么

然后将代码粘贴于于代码注入的Site header处(分析类JS推荐在header),等一段时间Googke分析首页就会出现内容拉😎!

代码高亮

在初次测试Ghost的各项功能时,我神奇的发现Ghost竟然没有原生支持代码高亮功能,我的天哪!这都2023年了喂😕。

不过没关系,只要有搜索引擎,一切事情都有解决办法🤭:在Ghost官方教程中有写如何设置使用Prism.js。

在代码注入的Header处加入内容:

<!-- prism.js -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" integrity="sha512-vswe+cgvic/XBoF1OcM/TeJ2FW0OofqAVdCZiEYkd6dwGXthvkSFWOoGGJgS2CW70VK5dQM5Oh+7ne47s74VTg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.css" integrity="sha512-Dqf5696xtofgH089BgZJo2lSWTvev4GFo+gA2o4GullFY65rzQVQLQVlzLvYwTo0Bb2Gpb6IqwxYWtoMonfdhQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />

在Footer处加入内容:

<!-- prism.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js" integrity="sha512-9khQRAUBYEJDCDVP2yw3LRUQvjJ0Pjx0EShmaQjcHa6AXiOv6qHQu9lCAIR8O+/D8FtaCoJ2c0Tf9Xo7hYH01Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js" integrity="sha512-SkmBfuA2hqjzEVpmnMt/LINrjop3GKWqsuLSSB3e7iBmYK7JuWw4ldmmxwD9mdm2IRTTi0OxSAfEGvgEi0i2Kw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/toolbar/prism-toolbar.min.js" integrity="sha512-st608h+ZqzliahyzEpETxzU0f7z7a9acN6AFvYmHvpFhmcFuKT8a22TT5TpKpjDa3pt3Wv7Z3SdQBCBdDPhyWA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js" integrity="sha512-/kVH1uXuObC0iYgxxCKY41JdWOkKOxorFVmip+YVifKsJ4Au/87EisD1wty7vxN2kAhnWh6Yc8o/dSAXj6Oz7A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

保存后就实现了代码高亮的功能拉🎉!而且我贴心的帮你们找到了prism.js实现右上角复制代码的功能,不用再添加额外的代码咯~快谢谢我😋。

在这之后,Ghost的编辑器内输入代码片段时,在右上角的框内填写代码类型,如:html。脚本会贴心的在加载代码片段时只自动加载html格式的代码高亮,加快页面载入速度🥳。

评论系统

Ghost评论系统还是不够完善,本来想试试的,但是用了几天发现有下面几个问题:

  1. 国内网络环境加载缓慢,极端慢🙃!(这个通过cloudflare或国内CDN可以一定程度上环节)
  2. 不能使用表情包:这绝对不能忍🤬!我那么多可爱的表情全浪费了吗?
  3. 评论通知频繁🤫,一个朋友对另一个朋友做出的评论我也会接到通知,不符合逻辑。况且Mailgun每月只有1000封邮件的额度,担心评论系统也使用Mailgun发送邮件会用超免费额度🥺。

不甘心的我在网上高强度搜索,决定在下面几种评论系统选一个比较合适的:

Cusdis:超级轻量,但没有表情包。

Artalk:进去官网就看到文档下面的评论显示404,离了个大谱,信心丢失。

twikoo:各方面都可以,但为什么不选Waline呢?

Waline:还是用原本采用的吧,路径依赖也是蛮好的。还可以试着导入以前的评论。

💡
唉,要是评论系统支持Ghost的账户系统SSO登录就好了,那样可以直接在我博客注册的朋友免去重新输入评论必要信息的麻烦。

想了想,还是用回Hugo上经历许多考验的Waline吧。评论系统是在Vercel平台上免费部署的,但因为Vercel的DNS被污染,以及Serverless平台后端代码执行缓慢的原因,有朋友经常给我留言说评论系统一直出现fetch错误。这次我决定在服务器独立部署Waline,希望能解决这方面的问题。

如果想使用Vercel,可以点击下面的按钮一键部署🎉!

或参考下面的官网部署教程:

部署
Waline 支持多种部署方式,你可以从以下部署平台进行选择。 Vercel (./vercel.md) (默认); 阿里云函数计算 (./aliyun-fc.md); 百度云函数计算 (./baidu-cfc.md); Cloudbase (./cloudbase.md); Deta (./deta.md); Railway (./railway.m…
从 Hugo 迁移至 Ghost 后我都做了什么Waline
从 Hugo 迁移至 Ghost 后我都做了什么
💡
服务器可以参考官网使用learnCloud或使用免费的PostgreSQL:supabaseplanetscale

服务器部署,在服务器上新建docker-compose.yaml文件:

nano docker-compose.yml

输入以下内容:

version: '3'
services:
  waline:
    container_name: waline
    image: lizheming/waline:latest
    restart: always
    ports:
      - 127.0.0.1:8360:8360
    volumes:
      - ${PWD}/data:/app/data
    environment:
      TZ: 'Asia/Shanghai' #时区设置
      #SQLITE_PATH: '/app/data' #使用SQLITE就不需要注释
      #JWT_TOKEN: 'Your token' #SQLITE内容
      SITE_NAME: '站点名字'
      SITE_URL: '站点链接'
      AUTHOR_EMAIL: '博主邮箱'
      LOGIN: 'disable' #是否强制登录 disable为关闭
      DISABLE_USERAGENT: 'true' #是否隐藏评论者的 UA,默认为否
      DISABLE_REGION: 'true' #是否隐藏评论者的归属地
      #AVATAR_PROXY: 'false' #头像的代理地址,设置 false 关闭代理 推荐注释使用下面的内容
      GRAVATAR_STR: 'https://use.sevencdn.com/avatar/{{mail|lower|trim|md5}}' #头像代理替换
      IPQPS: '20' #发言间隔-秒
      SECURE_DOMAINS: 'irithys.com' #安全域名配置 防止他人使用你的评论系统
      #SMTP_HOST: '' #SMTP_HOST、SMTP_PORT两个或直接使用SMTP_SERVICE一个配置
      #SMTP_PORT: ''
      #SMTP_USER: ''
      #SMTP_PASS: ''
      SMTP_SERVICE: 'Aliyun'
      SMTP_SECURE: true #是否使用 SSL 连接 SMTP
      SENDER_NAME: '发件人名字'
      MYSQL_DB: '' #如果使用SQLITE则 MYSQL相关配置都注释掉
      MYSQL_USER: ''
      MYSQL_PASSWORD: ''
      MYSQL_HOST: ''
      MYSQL_PORT: ''
      MYSQL_SSL: 'true'
      MAIL_SUBJECT: ''
      MAIL_TEMPLATE: ''
      MAIL_SUBJECT_ADMIN: ''
      MAIL_TEMPLATE_ADMIN: ''
      

需要修改的数据库相关配置可以参考官方配置

环境变量名称 必填 默认值 备注
MYSQL_DB MySQL 数据库库名
MYSQL_USER MySQL 数据库的用户名
MYSQL_PASSWORD MySQL 数据库的密码
MYSQL_HOST 127.0.0.1 MySQL 服务的地址
MYSQL_PORT 3306 MySQL 服务的端口
MYSQL_PREFIX wl_ MySQL 数据表的表前缀
MYSQL_CHARSET utf8mb4 MySQL 数据表的字符集
MYSQL_SSL false 是否使用 SSL MYSQL 连接数据库
邮件配置参考这里

Waline还可以自定义邮件模板,如果想要自定义,可以参考下面的紫罗兰主题模板内容填入。

从 Hugo 迁移至 Ghost 后我都做了什么

是这个样子!不过因为屏幕原因只能截取到正文内容,上面的封面没有截取到🥺。并且我发现其他朋友使用的这个模版中的代码有些错误,无法在docker-compose.yml文件内使用,不过我已经改正拉!

💡
注意:Vercel中规定环境变量的长度不能超过4KB,所以可能会出现错误,解决办法是修改index.js内的相关内容。

MAIL_SUBJECT:邮件主题

{{parent.nick | safe}},『{{site.name | safe}}』上的评论收到了回复

MAIL_TEMPLATE:邮件模板

<div style="background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/bg2.png);padding:20px 0px 20px;margin:0px;background-color:#d6d6d6;width:100%;"><style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style><div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;margin:50px auto;max-width:100%;background: #ffffff;"><img class="beforeimg" style="margin-top: -30px;margin-bottom: -120px;width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png"><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" style="width:100%;overflow:hidden;pointer-events:none"><div style="width:100%;background:#f8d1ce;color:#9d2850;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/line034_666x66.png) left top no-repeat;"><p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;padding: 23px 32px;margin:0;">您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}">『{{site.name | safe}}』</a>上的留言有新回复啦!</p></div><div class="formmain" style="background:#fff;width:96%;max-width:800px;margin:auto auto;border-radius:5px;border: 1px solid #564f4f59;overflow:hidden;pointer-events:none"><div style="margin:40px auto;width:90%;"><p>Hi,{{parent.nick}},您曾在文章上发表评论:</p><div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{parent.comment | safe}}</div><p><strong>{{self.nick}}</strong> 给您的回复如下:</p><div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div><p>您可以点击<a style="text-decoration:none; color:#cf5c83" href="{{site.postUrl}}" target="_blank"> 查看回复的完整內容 </a>,欢迎再次光临<a style="text-decoration:none; color:#cf5c83" href="{{site.url}}" target="_blank"> {{site.name}} </a>。<hr /><p style="font-size:14px;color:#b7adad;text-align:center">本邮件为系统自动发送,请勿直接回复邮件哦,可到博文内容回复。<br />https://irithys.com</p></p><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none"><p class="bottomhr" style="font-size:12px;text-align:center;color:#999">自动书记人偶竭诚为您服务!</p></div></div><img class="afterimg" style="width:530px;height:317px;margin-top: -155px;z-index:100;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"></div></div>'

MAIL_SUBJECT_ADMIN:博主邮件主题

{{site.name | safe}} 上有新评论了

MAIL_TEMPLATE_ADMIN:博主邮件模板

<div style="background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/bg2.png);padding:20px 0px 20px;margin:0px;background-color:#d6d6d6;width:100%;"><style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style><div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;margin:50px auto;max-width:100%;background: #ffffff;"><img class="beforeimg" style="margin-top: -30px;margin-bottom: -120px;width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png"><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/violet.jpg" style="width:100%;overflow:hidden;pointer-events:none"><div style="width:100%;background:#f8d1ce;color:#9d2850;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://npm.elemecdn.com/sarakale-assets@v1/Article/email/line034_666x66.png) left top no-repeat;"><p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;padding: 23px 32px;margin:0;">您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}"target="_blank">{{site.name}}</a>上的文章有了新的评论</p></div><div class="formmain" style="background:#fff;width:96%;max-width:800px;margin:auto auto;border-radius:5px;border: 1px solid #564f4f59;overflow:hidden;pointer-events:none"><div style="margin:40px auto;width:90%;"><p><strong>{{self.nick}}</strong> 回复说:</p><div style="background: #eee;margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div><p style="text-align:center;">您可以点击<a style="text-decoration:none;color:#cf5c83" href="{{site.postUrl}}" target="_blank">查看回复的完整內容</a></p><img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none"><p class="bottomhr" style="font-size:12px;text-align:center;color:#999">自动书记人偶竭诚为您服务!</p></div></div><img class="afterimg" style="width:530px;height:317px;margin-top: -155px;z-index:100;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"></div></div>

umami分析

umami声称是Google分析的代替品,不过我用它的主要原因是Google分析太难用了😭,经常想找一个功能找不到位置,而umami界面简洁清爽,各项功能排列合理,使用起来比Google分析舒服多了!而且自建也超级方便,甚至可以免费在Vercel上部署。有兴趣的朋友可以参考官网的Vercel部署攻略:

Running on-vercel – umami
从 Hugo 迁移至 Ghost 后我都做了什么

也是一键部署🤩!同样可以使用免费PostgreSQL。

💡
免费PostgreSQL:supabaseplanetscale

新页面打开链接

在代码注入的Footer处加入以下代码:

<!-- Open external links in a new tab by default -->
<script>
  const anchors = document.querySelectorAll('a');
    
  for (x = 0, l = anchors.length; x < l; x++) {
    const regex = new RegExp('/' + window.location.host + '/');
        
    if (!regex.test(anchors[x].href) && anchors[x].href.indexOf('javascript') == -1) {
      anchors[x].setAttribute('target', '_blank');
      anchors[x].setAttribute('rel', 'noopener');
    }
  }
</script>

实现的功能是在博客内点击一个链接时,检测是否为博客内部链接,不是博客内部链接则打开新的标签页跳转(变着法儿的让朋友们留在我的博客里哈哈哈😂)。

路由与重定向

在Ghost中可以方便的修改文章路径与重定向。简单来说,你可以通过下载 Setting - Labs - Beta features 处的重定向与路由文件进行修改上传。

将博客从Hugo迁移到Ghost后,最感到烦躁的就是文章中海量的链接了,文章内部没有什么好办法,只能一篇篇文章慢慢手动修改过去✏️,现在只能悔恨为什么当初非要弄一个看起来很酷但是不支持其他平台的Hugo语法进行内部跳转,换到Ghost后博客的内部链接全部失效,12/22号一整天修改累死我了😭。

重定向

官方参考方案在这里,神奇的是官方推荐使用redirects.yaml文件,但Ghost后台下载的确是一个json文件。

💡
注意,如果你只是单纯的想从/变成/p/这种形式,那么不如使用内容集合

举个例子,redirects.yaml文件是这个形式。编辑yaml文件(推荐使用vscode,yaml文件对空格缩进敏感,vscode可以减少失误,很方便的编辑):

301:
  /from: /to
  domain.com/category/category-slug/: domain.com/tag/tag-slug/
302:
  /from: /to

比如在使用Hugo时,我的全部文章都是domain.com/p/url的形式,但现在使用Ghost时,文章链接全变成了domain.com/url的形式,如果有朋友在自己博客中引用了我的文章内容,并且给出了文章链接,那么别人想要来我博客看看这篇文章时,会找不到原来的旧链接,导致出现404错误——这是我们不愿意看到的😕。那么这时就可以这样:

301:
  /p/保护自己的密码安全自托管或免费部署bitwarden: /bitwarden-1
302:

将丢失的旧链接重定向至新文章链接上。以往我都是使用Nginx跳转的,这真的好方便!省略了超多的步骤🥰。

301代表永久重定向,而302代表临时重定向,根据自己的需要修改,一般改动使用301,我也不知道302是让干嘛的哈哈哈哈😂,编辑好后重新打开Labs页面,选择Upload redirects file上传,左下角会有成功上传提示。

如果想要删除所有重定向,那么重新下面这样子的redirects.yaml空文件重新上传至Ghost即可:

301:

302:

主题汉化

Ghost的汉化可以说是两个极端,一方面极其开放,主题中用到的显示在前台的文字都可以在主题的locales文件夹中找到,只需要简单的将en.json文件拷贝一份,重新命名为zh.json然后自己手动翻译就好🥳。另一方面,又超级封闭,Ghost的一些组件如登、评论等前台界面中显示的文字已硬编码在程序中,导致无法修改😮。

注意:Ghost好像有一个隐形Bug的地方:简体中文的国际化一般叫做zh-Hans,但Ghost很奇怪叫做zh,繁体中文的zh-Hant倒是写得很对,这就导致有些主题的汉化文件与Ghost不一致,在后台Publication Language中选择Site language时,选择官方的zh,主题汉化引用不了,使用主题的,Ghsot又会出现一些官方英文。所以,在这里直接在主题文件这里重新拷贝一份zh.json汉化。

时间表达

我使用的是liebling主题,可能有些稍稍不一样,但代码中的文字表达方式大致相同:

这里:
<span class="m-heading__meta__time">{{date published_at}}</span>
修改为
<span class="m-heading__meta__time">{{date published_at format="YYYY年MM月DD日 HH:mm"}}</span>

具体想修改为那种表达方式,可以看着参考Ghost的 Date 章节来修改 。

Ghost Handlebars Theme Helpers: date
Output date formats in your Ghost publication with the date helper. More about Ghost themes inside ✨
从 Hugo 迁移至 Ghost 后我都做了什么Ghost - The Professional Publishing Platform
从 Hugo 迁移至 Ghost 后我都做了什么

Ghost - 时间助手模块

值得注意的是,Ghost中在date中引用了momentjs,但其中中文的表达方式又不一样。找了好久才知道,需要在其中加入locale="zh-cn"才可以变成中文(又出现了一个不同的代表中文的代码!!🤬)。

<span>{{date published_at locale="zh-cn" timeago="true"}}</span>

结语

呼,终于写完了🥳!还有目录没有做,但是使用Ghost官方教程的内容不会浮动,修改起来好头疼。自己还写过想要自己写一个Ghost主题,现在只完成了第一步:迁移到Ghot上,什么时候开始学习界面设计与Ghost主题开发依然遥遥无期😵‍💫。

就先这样吧?一边用着一边想着怎么修改。Ghost用起来我还蛮喜欢的🎉。

来写一些好玩的 Hugo 短代码吧

作者 吕楪
2022年11月14日 18:02
💡
请注意,由于博主已更换博客系统为 “Ghost”,以下代码已无法正常显示。 ——2023年12月22日18:10

Hugo短代码

来写一些好玩的 Hugo 短代码吧

由Hugo官方的文档可知,简码是内容文件中调用内置或自定义模板的简单代码段。那为什么会用到这东西呢🤔?因为:

💡
虽然Markdown的内容格式简单,但有时会达不到创作者的要求。通常,内容作者被迫将原始HTML(例如视频)添加到Markdown内容中。Hugo认为这与 Markdown语法的简单性相矛盾,比如<iframe>之类的标签。Hugo创造了短代码(shortcodes)来规避这些限制。

你会发现,上面这段文字被框起来了🎉,这就是Hugo短代码的实际运用~

短代码是内容文件中的简单片段,Hugo 将使用预定义的模板呈现该片段。请注意,短代码在模板文件中不起作用。如果需要短代码提供的插入功能类型,但在模板中,那很可能需要一个部分模板。除了更简洁的Markdown之外,短代码可以随时更新以反映新的类、技术或标准。在网站生成时,Hugo短代码将轻松合并更改。避免可能复杂的搜索和替换操作。

编写

在Markdown文件中,Hugo短代码通过{{</* shortcodename parameters */>}}的形式引用。前一个单词shortcodename为短代码名称,后一个单词parameters为参数,且排除第一个单词外都是参数,中间使用空格隔开。如果需要多个参数的传递,那么需要使用name="value"的形式传值。

💡
在Hugo中使用短代码,需要在在Hugo根目录下的./layouts/shortcodes/创建shortcodename.html文件,shortcodename为你短代码的名字。

语法

这里先写一些Hugo的简单语法😙,如:

{{ index .Params 0 }}

这句代码表达的意思为获取短代码中的第一个参数,如果是{{ index .Params 1 }}代表第二个,以此轮推。

{{ .Get "text1" }}

此代码表达为获取参数名为text1的参数,如果引用代码为{{</* myshortscode text="文本" */>}},那么传入的参数为“文本”二字。

传入日期需要使用{{/* .Date.Format ( default "2006-01-02") */}},后面为可以格式化的日期样式。

使用{{ /*with .Site.Params.footer.customText */}}语句可以引用站点配置文件中定义的变量值。如{{ /*with .Site.Params.sidebar.subtitle */}}此语句返回为:吕楪在记录自己的生活

分享

在Github与Google一通搜索😵‍💫后收集了很多短代码,连带着自己也照着写了几个😊。

高亮

样式:

{{< mark text="这是一个重点标记" >}}

创建mark.html文件,其中内容编写:

<mark>{{ .Get "text" }}</mark>

这样一个简单的短代码便实现啦,但默认的高亮为荧光黄色,看起来有点刺眼,那么可以在./assets/scss/custom.css中增加mark标记的样式🤭。

{{< notice notice-warning >}}
注意:./assets/scss/custom.css为我使用主题的自定义css文件,其他主题可能不相同。
{{< /notice >}}

mark{
    background: hsla(332, 81%, 58%, 0.879);
}

使用:

{{</* mark text="这是一个重点标记" */>}}

但这个颜色也不好看诶🥲。

缩写

样式:

{{< abbr title="这里有着非常非常非常非常非常非常非常非常长的缩写内容~" text="缩写的文本" >}}

这时,将鼠标放在缩写的文本上方时,会自动浮现出被缩写的内容。

创建abbr.html文件,其中内容编写:

<abbr title="{{ .Get "title" }}">{{ .Get "text" }}</abbr>

使用:

{{</* abbr title="这里有着非常非常非常非常非常非常非常非常长的缩写内容~" text="缩写的文本" */>}}

蛮好玩的样子😙!

文本位置

样式:

{{< align center "文字居中" >}}

会发现上面的文本在文章中心。

创建align.html文件,其中内容编写:

<p style="text-align:{{ index .Params 0 }}">{{ index .Params 1 | markdownify }}</p>

使用:

{{</* align center "文字居中" */>}}

理解起来也非常简单😘,首先align.html内容为一段html5编码,p标签为段落,我们要实现的自由变动文本位置需要使用css样式text-align,这里能用的参数有:center、left、right。

{{ index .Params 0 }}代表读取短代码的第一个参数center{{ index .Params 1 | markdownify }}代表读取短代码中第二个参数,至于markdownify代表通过Markdown处理器运行提供的字符串。markdownifyHugo V0.93版本提供的新功能,旧版本不适用哦。

块引用

样式:

{{< blockquote author="电影" link="https://irithys.com" title="《寻梦环游记》" >}}
死亡不是一切的终点,遗忘才是
{{< /blockquote >}}

创建blockquote.html文件,拷贝以下内容。

<!-- reset scratch variables at the start -->
{{ $.Scratch.Set "bl_author" false }}
{{ $.Scratch.Set "bl_source" false }}
{{ $.Scratch.Set "bl_link" false }}
{{ $.Scratch.Set "bl_title" false }}

{{ if .IsNamedParams }}
  {{ $.Scratch.Set "bl_author" (.Get "author") }}
  {{ $.Scratch.Set "bl_source" (.Get "source") }}
  {{ $.Scratch.Set "bl_link" (.Get "link") }}
  {{ $.Scratch.Set "bl_title" (.Get "title") }}
{{ else }}
  <!-- for the positional version if any -->
{{ end }}

<!-- if title is not set explicitly then we need to beautify the link
     if length of link is more than 32 chars, we will cut it off by 32 and
     then drop everything after the last / if any and put it in into title -->

{{ with $.Scratch.Get "bl_title" }}
  <!-- do nothing -->
{{ else }}
  {{ with $.Scratch.Get "bl_link" }}    <!-- if link is given -->
    {{ range last 1 (split ($.Scratch.Get "bl_link" ) "://") }}  <!-- split by :// and then only take the items after it to remove protocol:// -->
      {{ $.Scratch.Set "title_without_protocol" . }}
    {{ end }}
    {{ range last 1 (split ($.Scratch.Get "title_without_protocol" ) "www.")  }} <!-- also remove the www. at the start if any. we are using a second split because all URLS may not start with it -->
      {{ $.Scratch.Set "title_without_protocol" . }}
    {{ end }}
    {{ $.Scratch.Set "bl_title" ($.Scratch.Get "title_without_protocol") }}

    <!-- if link is longer than 32 bytes we should trim it -->
    {{ if (gt (len ($.Scratch.Get "title_without_protocol") ) 32) }}
      {{ $title := (slicestr ($.Scratch.Get "title_without_protocol") 0 32) }}   <!-- get the first 32 characters of title_without_protocol -->
      {{ $split_by_fw_slash := split $title "/" }}   <!-- now split on / because we want to stop after the last forward slash -->
      {{ $count := (sub (len $split_by_fw_slash) 1) }}   <!-- we want everything but the last part so we adjust the count accordingly -->

      {{ $.Scratch.Set "tempstring" "" }}   <!-- temp variable to hold the concatinated string -->
      {{ range first $count $split_by_fw_slash  }}  <!-- loop through all parts except last and concat them (add / between halves) -->
        {{ $.Scratch.Set "tempstring" ( . | printf "%s%s/" ($.Scratch.Get "tempstring") | printf "%s" ) }}
      {{ end }}
      {{ $.Scratch.Set "bl_title" ( printf "%s..." ($.Scratch.Get "tempstring") | printf "%s" ) }}
    {{ end }}
  {{ end }}
{{ end }}

<blockquote>
  <p>{{ .Inner | markdownify }}</p>
  <footer style="text-align:right">
    <strong>{{ with $.Scratch.Get "bl_author" }}{{ . }}{{ end }}</strong>
    {{ with $.Scratch.Get "bl_source" }}
      <cite>{{ . }}</cite>
    {{ else }}
      {{ with $.Scratch.Get "bl_link" }}
        <cite>
          <a href="{{ . }}" title="{{ . }}" rel="noopener noreferrer">{{ $.Scratch.Get "bl_title" }}</a> <!-- can't have new lines here -->
        </cite>
      {{ else }}
        {{ with $.Scratch.Get "bl_title" }}
          <cite>
            {{ $.Scratch.Get "bl_title" }}</a>
          </cite>
        {{ end }}
      {{ end }}
    {{ end }}
  </footer>
</blockquote>

使用:

{{</* blockquote author="电影" link="https://irithys.com" title="《寻梦环游记》" */>}}
死亡不是一切的终点,遗忘才是
{{</* /blockquote */>}}

隐藏

样式:

{{< detail "点下我呀🎁" >}}
对看到这行文字的人报以深切的祝福🥰!
{{< /detail >}}

创建detail.html文件,拷贝其中内容:

<details>
    <summary>{{ (.Get 0) | markdownify }}</summary>
    {{ .Inner | markdownify }}
</details>

使用:

{{</* detail "点下我呀🎁" */>}}
对看到这行文字的人报以深切的祝福!🥰
{{</* /detail */>}}

标签

这里的标签非常好看!文章第一章节便使用了这个标签。源文件来自@martignoni,但颜色过重,我使用了@荷戟独彷徨的修改版本~

此标签有4个样式~

样式一,警告:
{{< notice notice-warning >}}
警告!这个标签太好看了,我忍不住分享。
{{< /notice >}}

样式二,信息:
{{< notice notice-info >}}
明确的爱,直接的厌恶,真诚的喜欢。站在太阳下的坦荡,大声无愧地称赞自己。
{{< /notice >}}

样式三,贴条:
{{< notice notice-tip >}}
遇到一些需要做提示性语句的位置,可以贴个条。
{{< /notice >}}

样式四,注释:
{{< notice notice-note >}}
我想要的不是解释,而是注释。
{{< /notice >}}

创建notice.html文件,拷贝以下内容:

{{- $noticeType := .Get 0 -}}

{{- $raw := (markdownify .Inner | chomp) -}}

{{- $block := findRE "(?is)^<(?:address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h(?:1|2|3|4|5|6)|header|hgroup|hr|li|main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video)\\b" $raw 1 -}}

{{ $icon := (replace (index $.Site.Data.SVG $noticeType) "icon" "icon notice-icon") }}
<div class="notice {{ $noticeType }}" {{ if len .Params | eq 2 }} id="{{ .Get 1 }}" {{ end }}>
    <div class="notice-title">{{ $icon | safeHTML }}</div>
    {{- if or $block (not $raw) }}{{ $raw }}{{ else }}<p>{{ $raw }}</p>{{ end -}}
</div>

/assets/scss/custom.scss中新加入以下样式:

.notice {
  position:relative;
  padding: 1em 1em 1em 2.5em;
  margin-bottom: 1em;
  border-radius: 4px;
  p:last-child {
      margin-bottom: 0;
  }
  .notice-title {
      position: absolute;
      left: 0.8em;
      .notice-icon {
          width: 1.2em;
          height: 1.2em;
      }
  }
  &.notice-warning {
      background: hsla(0, 65%, 65%, 0.15);
      border-left: 5px solid hsl(0, 65%, 65%);
      .notice-title {
          color: hsl(0, 65%, 65%);
      }
  }
  &.notice-info {
      background: hsla(30, 80%, 70%, 0.15);
      border-left: 5px solid hsl(30, 80%, 70%);
      .notice-title {
          color: hsl(30, 80%, 70%);
      }
  }
  &.notice-note {
      background: hsla(200, 65%, 65%, 0.15);
      border-left: 5px solid hsl(200, 65%, 65%);
      .notice-title {
          color: hsl(200, 65%, 65%);
      }
  }
  &.notice-tip {
      background: hsla(140, 65%, 65%, 0.15);
      border-left: 5px solid hsl(140, 65%, 65%);
      .notice-title {
          color: hsl(140, 65%, 65%);
      }
  }
}

[data-theme="dark"] .notice {
  &.notice-warning {
      background: hsla(0, 25%, 35%, 0.15);
      border-left: 5px solid hsl(0, 25%, 35%);
      .notice-title {
          color: hsl(0, 25%, 35%);
      }
  }
  &.notice-info {
      background: hsla(30, 25%, 35%, 0.15);
      border-left: 5px solid hsl(30, 25%, 35%);
      .notice-title {
          color: hsl(30, 25%, 35%);
      }
  }
  &.notice-note {
      background: hsla(200, 25%, 35%, 0.15);
      border-left: 5px solid hsl(200, 25%, 35%);
      .notice-title {
          color: hsl(200, 25%, 35%);
      }
  }
  &.notice-tip {
      background: hsla(140, 25%, 35%, 0.15);
      border-left: 5px solid hsl(140, 25%, 35%);
      .notice-title {
          color: hsl(140, 25%, 35%);
      }
  }
}

文件中的[data-theme="dark"]为暗色模式下的css样式,虽然我主题带有暗色模式,但没有用。推测应该需要在variables.scss中定义变量然后引用。但应该蛮少人在我博客中使用暗色模式的吧,就先这样用吧。

之后,在./data/目录下新建SVG.toml文件,拷贝以下内容:

notice-warning = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 576 512" fill="hsl(0, 65%, 65%)"><path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6.0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6.0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"/></svg>'
notice-info = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512" fill="hsl(30, 80%, 70%)"><path d="M256 8a248 248 0 100 496 248 248 0 000-496zm0 110a42 42 0 110 84 42 42 0 010-84zm56 254c0 7-5 12-12 12h-88c-7 0-12-5-12-12v-24c0-7 5-12 12-12h12v-64h-12c-7 0-12-5-12-12v-24c0-7 5-12 12-12h64c7 0 12 5 12 12v100h12c7 0 12 5 12 12v24z"/></svg>'
notice-note = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512" fill="hsl(200, 65%, 65%)"><path d="M504 256a248 248 0 11-496 0 248 248 0 01496 0zm-248 50a46 46 0 100 92 46 46 0 000-92zm-44-165l8 136c0 6 5 11 12 11h48c7 0 12-5 12-11l8-136c0-7-5-13-12-13h-64c-7 0-12 6-12 13z"/></svg>'
notice-tip = '<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 512 512" fill="hsl(140, 65%, 65%)"><path d="M504 256a248 248 0 11-496 0 248 248 0 01496 0zM227 387l184-184c7-6 7-16 0-22l-22-23c-7-6-17-6-23 0L216 308l-70-70c-6-6-16-6-23 0l-22 23c-7 6-7 16 0 22l104 104c6 7 16 7 22 0z"/></svg>'

此文件中定义的4个变量为svg矢量图,如果想要用其他的图片也可以换成其他的。

注意:如果在/assets/scss/custom.scss中定义的css样式不起作用,也就是说图标为黑色状态,那么需要在SVG标签中写入fill="hsl(0, 65%, 65%)"之类的颜色标签,此内容和css在定义中定义的颜色相同。

使用:

{{</* notice notice-warning */>}}
警告!这个标签太好看了,我忍不住分享。
{{</* /notice */>}}

这是第一个标签,将notice-warning分别修改为notice-notenotice-infonotice-tip就可以得到其他三个不同样式的标签啦😛。

音乐

样式:

{{< music id="557578993" type="song" server="netease" >}}

首先,引用外部链接需要关闭Hugo的安全模式(必须):

打开根目录的config.yaml文件,修改以下内容:

markup:
    goldmark:
        renderer:
            unsafe: true

当然,如果配置文件为config.toml,则是这种修改方式:

[markup.goldmark.renderer]
unsafe= true
此步骤设置为true,markdown中就可以使用html5标签啦。

新建music.html文件夹,拷贝以下内容:

<!-- require APlayer -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
<style type="text/css">.dark-theme .aplayer{background:#212121}.dark-theme .aplayer.aplayer-withlist .aplayer-info{border-bottom-color:#5c5c5c}.dark-theme .aplayer.aplayer-fixed .aplayer-list{border-color:#5c5c5c}.dark-theme .aplayer .aplayer-body{background-color:#212121}.dark-theme .aplayer .aplayer-info{border-top-color:#212121}.dark-theme .aplayer .aplayer-info .aplayer-music .aplayer-title{color:#fff}.dark-theme .aplayer .aplayer-info .aplayer-music .aplayer-author{color:#fff}.dark-theme .aplayer .aplayer-info .aplayer-controller .aplayer-time{color:#eee}.dark-theme .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon path{fill:#eee}.dark-theme .aplayer .aplayer-list{background-color:#212121}.dark-theme .aplayer .aplayer-list::-webkit-scrollbar-thumb{background-color:#999}.dark-theme .aplayer .aplayer-list::-webkit-scrollbar-thumb:hover{background-color:#bbb}.dark-theme .aplayer .aplayer-list li{color:#fff;border-top-color:#666}.dark-theme .aplayer .aplayer-list li:hover{background:#4e4e4e}.dark-theme .aplayer .aplayer-list li.aplayer-list-light{background:#6c6c6c}.dark-theme .aplayer .aplayer-list li .aplayer-list-index{color:#ddd}.dark-theme .aplayer .aplayer-list li .aplayer-list-author{color:#ddd}.dark-theme .aplayer .aplayer-lrc{text-shadow:-1px -1px 0 #666}.dark-theme .aplayer .aplayer-lrc:before{background:-moz-linear-gradient(top, #212121 0%, rgba(33,33,33,0) 100%);background:-webkit-linear-gradient(top, #212121 0%, rgba(33,33,33,0) 100%);background:linear-gradient(to bottom, #212121 0%, rgba(33,33,33,0) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#212121', endColorstr='#00212121',GradientType=0 )}.dark-theme .aplayer .aplayer-lrc:after{background:-moz-linear-gradient(top, rgba(33,33,33,0) 0%, rgba(33,33,33,0.8) 100%);background:-webkit-linear-gradient(top, rgba(33,33,33,0) 0%, rgba(33,33,33,0.8) 100%);background:linear-gradient(to bottom, rgba(33,33,33,0) 0%, rgba(33,33,33,0.8) 100%);filter:progid:DXImageTransform.Microsoft.gradient( startColorstr='#00212121', endColorstr='#cc212121',GradientType=0 )}.dark-theme .aplayer .aplayer-lrc p{color:#fff}.dark-theme .aplayer .aplayer-miniswitcher{background:#484848}.dark-theme .aplayer .aplayer-miniswitcher .aplayer-icon path{fill:#eee}</style>
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<!-- require MetingJS -->
<script src="https://cdn.jsdelivr.net/npm/meting@2.0.1/dist/Meting.min.js"></script>

<!-- 注意!!我因为APlayer与meting-js都是以插件形式引入的,所以不需要写上面这些 -->
{{ if .IsNamedParams }}
    <meting-js
      id="{{ .Get "id" }}"
      server="{{ .Get "server" }}"
      type="{{ .Get "type" }}"
      fixed="{{ if .Get "fixed" }}{{ .Get "fixed" }}{{ else }}false{{ end }}"
      mini="{{ if .Get "mini" }}{{ .Get "mini" }}{{ else }}false{{ end }}"
      autoplay="{{ if .Get "autoplay" }}{{ .Get "autoplay" }}{{ else }}false{{ end }}"
      loop="{{ if .Get "loop" }}{{ .Get "loop" }}{{ else }}none{{ end }}"
      theme="{{ if .Get "autoplay" }}{{ .Get "autoplay" }}{{ else }}#255579{{ end }}"
      volume="{{ if .Get "volume" }}{{ .Get "volume" }}{{ else }}0.6{{ end }}"
      prelosd="{{ if .Get "prelosd" }}{{ .Get "prelosd" }}{{ else }}auto{{ end }}"
      mutex="{{ if .Get "mutex" }}{{ .Get "mutex" }}{{ else }}true{{ end }}"
      list-folded="{{ if .Get "list-folded" }}{{ .Get "list-folded" }}{{ else }}true{{ end }}">
    </meting-js>
{{ end }}

使用:

{{</* music id="557578993" type="song" server="netease" */>}}

此处的id为音乐的网址id,如我上面引用的音乐,地址为https://music.163.com/#/song?id=557578993server代表用的哪家的服务,netease代表网易,还可以使用有腾讯tencent,酷狗kugou,百度baidu

长毛象

样式:

{{< mastodon status="109336902159860386" >}}

新建mastodon.html文件,拷贝以下内容:

{{ .Page.Scratch.Set "include_mastodon" true }}
{{ $server := .Get "server" | default "im.irithys.com" }}
{{ $user := .Get "user" | default "thy" }}
{{ $width := .Get "width" | default "100%" }}
{{ $height := .Get "height" | default "auto"}}
{{ $status := .Get "status" | default "false" }}

{{ if eq ($status) "false" }}
{{ else }}
<iframe src= "https://{{ $server }}/@{{ $user }}/{{ $status }}/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="{{ $width }}" height="{{ $height }}" allowfullscreen="allowfullscreen"></iframe><script src="https://{{ $server }}/embed.js" async="async"></script>
{{ end }}

这里我在上方预先定义了一些默认的常量,如serveruser,这是因为如果是引用自己的话,每次都传一次也太呆了吧。所以如果其他毛象站的朋友们使用,需要先修改server为自己的服务器,user为自己的用户名

使用:

{{</* mastodon status="109336902159860386" */>}}

只需要将嘟文id传入就好啦😙~

哔站

样式:

{{< bilibili BV1NF411J7JH >}}

创建bilibili.html文件,拷贝以下内容:

{{ $vid := (.Get 0) }}
{{ $videopage := default 1 (.Get 1) }}
{{ $basicQuery := querify "page" $videopage "high_quality" 1 "as_wide" 1 }}
{{ $videoQuery := "" }}

{{ if strings.HasPrefix (lower $vid) "av" }}
    {{ $videoQuery = querify "aid" (strings.TrimPrefix "av" (lower $vid)) }}
{{ else if strings.HasPrefix (lower $vid) "bv" }}
    {{ $videoQuery = querify "bvid" $vid }}
{{ else }}
    <p>Bilibili 视频av号或BV号错误!请检查视频av号或BV号是否正确</p>
    <p>当前视频av或BV号:{{ $vid }},视频分P:{{ $videopage }}</p>
{{ end }}

<div class="video-wrapper">
    <iframe src="https://player.bilibili.com/player.html?{{ $basicQuery | safeURL }}&{{ $videoQuery | safeURL }}"
            scrolling="no"
            frameborder="no"
            framespacing="0"
            allowfullscreen="true"
    >
    </iframe>
</div>

使用:

{{</* bilibili BV1NF411J7JH */>}}

蛮好玩的,B站除了一些需要版权的视频之外,都可以引用哦。

网易云

样式:

{{< netease 557578993 0 >}}

这其实是网易云自带的嵌入,略作修改后就能拿过来用啦。

新建netease.html文件,拷贝以下内容:

<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" width=100% height=86 src="//music.163.com/outchain/player?type=2&id={{ index .Params 0 }}&auto={{ index .Params 1 }}&height=66"></iframe>

使用:

{{</* netease 557578993 0 */>}}

输入的第一个参数为歌曲的id,第二个参数代表是否自动播放,1为自动播放,0为手动播放。

完结

分享完毕😊,在之后我遇到新的Hugo短代码再继续更新此文章😋~我发现国内好多网站都已经不提供嵌入代码了呀,虽然是互联网但是没有一点开放的态度呢🤔。

❌
❌