惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Engineering at Meta
Engineering at Meta
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
B
Blog RSS Feed
GbyAI
GbyAI
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recorded Future
Recorded Future
美团技术团队
The Register - Security
The Register - Security
V
Visual Studio Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
量子位
B
Blog
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
L
LangChain Blog
Latest news
Latest news
S
SegmentFault 最新的问题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
W
WeLiveSecurity
T
Tenable Blog
T
Tor Project blog

韩小韩博客

你还在用真实邮箱注册网站?等等,你真的想清楚了吗? IPFS星际文件系统 最新二合一收款码 - 物理合并版 从Hexo到Astro博客1分钟迁移指南 Astro 添加 Waline 评论组件 腾讯云 EdgeOne Pages 实测对比:能否成为国内开发者的 Cloudflare Pages 最佳平替? Astro 中使用 Lenis 增加鼠标滚动阻尼感 一组手机和电脑动态壁纸分享【分享】 Astro 添加 Twikoo 评论组件 Astro主题-优雅的vhAstro-Theme【使用文档】 Fetch的GET、POST简单HTTP请求封装 一些实拍的手机壁纸 大理And威海【图】 很喜欢西湖的水【转自:狮子狮子鱼】 Tarot-塔罗牌占卜 Web Watermark 图片添加水印在线小助手 HanAnalytics访问分析Web统计托管于(Cloudflare Pages) 基于AI的微博动态心情分析 阿里云免费用9年ecs教程【适合轻量化服务如frp】 Cloudflare优选IP➕DnsPod的DDNS自动切换 混沌神器Clash全家桶 卷王都在用的变态休息法 NodeJs文本相似度去重脚本 骤雨重山无限存储图床托管于(Cloudflare Pages) 分享好看的天空和云(长期更新) Typecho评论导出为Hexo的Valine、Twikoo等评论所支持的JSON文件 Safari浏览器内容被地址栏、菜单栏或工具栏遮挡导致的兼容问题 拼夕夕快速提现100元攻略 2024 平安喜乐 通义灵码:重塑编程的未来,引领技术革新 亚马逊CloudFront免费CDN配置教程 树莓派在Docker中部署Samba 树莓派4B(Raspberry Pi OS Lite 64-bit)安装Docker 变相跳出forEach循环 Vue3项目Build后部署在Nginx上F5刷新页面空白或404 Ant Design Vue 4.0 侧边导航栏Menu组件封装 Ant Design Vue 4.0 a-modal弹窗组件封装 Vue3 + Vite + Vue Router 4后端返回路由配置动态路由权限管理 手撸call apply bind class中函数的this指向 Vue 2与Vue 3在自定义组件v-model上的区别 Vue.set与this.$set源码 Vue底层判断标签的性能优化方法 Linux系统下使用iftop结合iptables服务解决带宽被恶意请求的问题 JS压缩图片并保留图片元信息 蓝奏云盘解析API接口 开源 原型继承和 Class 继承 DOM同级传递事件 2023年有哪些良心的流量卡推荐?爆肝给大家整理好了最新的流量卡合集 火爆全球的ChatGPT,最全的使用方法! 最实用的JavaScript一行代码 AWS教程——解决WordPress网站加载缓慢的大难题 今日热榜HotList-Web前端开源Vue - (聚合热榜) 在Fly.io上部署Alist网盘程序 利用CloudFlare的Workers和Pages反代Github并缓存实现Github文件加速访问 简单逆向某色情网站图片加密(原创) 骚扰电话API接口 开源 知乎热榜API、百度热点API、微博热搜API(开源)- 聚合热榜API开源 韩小韩API上架腾讯云HiFlow 羊了个羊在线刷通关数999999 斐讯N1盒子刷OpenWrt做主路由/旁路由(详细付配置) Adobe After Effects 2022 最新免激活版 FFMPEG视频切片TS文件添加PNG文件头伪图片上传 分享我喜欢的风景图~ 微信小程序调用摄像头实现拍照功能 烈日炎炎的夏天想要一场雨 王者荣耀、和平精英、腾讯手游扫码登录工具如何实现? 摸鱼人日历-每天60秒读懂世界-每日美女-IP签名档-API接口 按照图片尺寸自动分类 手机分辨率 电脑分辨率 python脚本 JS正则常用校验大全(精华篇) Vue项目element组件遇到的坑(记录篇持续更新) 微信小程序原生wx.request简单封装(自用版) 微信小程序登陆封装(自用版)欢迎指正 GitHub技巧之五大隐藏技巧 WPS2019中石油专用版v11.8.2.10972 JS正则判断校验姓名、手机号及身份证号码(笔记) 记个笔记 纯CSS简单图 鼠标拖拽移动DIV 记录一下 Coding免费图床方案 白嫖破解Typora1.1.5最新版 在CloudFlare workers部署你的Hexo静态博客 胎教级搭建Hexo静态博客安装Fluid主题 2022年5个好用的 BT/ 磁力链接下载工具推荐 |Windows 、安卓系统 CloudFlare Argo Tunnel配置 - 实现内网穿透 分享9个可免费使用的网站CDN加速服务 利用免费oss对象存储实现域名防红 情侣要做的好多件事 2022年2月20日 周末·天气晴朗·心情超好·南京浦口码头 2022年2月7号 冬·雪·南京 腾讯云2022新年特惠活动 树莓派ubuntu64位系统安装宝塔 植物大战僵尸 MAC M1 版本 Mac应用程序无法打开或文件损坏的处理方法 Vue项目Element-UI表格el-table的分页el-pagination功能简单封装 前端存储之indexDB 宝塔LNMP搭建Cloudreve进程守护添加SSL证书Nginx代理 微信小程序自用Tree树形控件 2022你好 (白嫖觉)永久免费的虚拟主机合集 Typecho-Joe-Theme主题帮助文档
Typecho转到Hexo(主题由Typecho-Joe-Theme转Butterfly主题)
.𝙃𝙖𝙣 · 2026-04-11 · via 韩小韩博客

avatar

.𝙃𝙖𝙣

605 3分钟

Code

Typecho转到Hexo(主题由Joe主题转Butterfly主题)

前言

使用了好久好久好久的动态博客,身为一个前端的我,总是想着把动态博客转为静态博客,但是一直没有动手,最近博客被持续的攻击,无法正常访问等因素,终于决定把博客迁移到Hexo上,下面就来分享一下迁移过程。

文档导出

因为之前使用的是TypechoTypecho-Joe-Theme主题,主题中包含了很多自定义标签,所以我们在导出的过程中要处理一下数据,把Typecho-Joe-Theme的标签转换成HexoButterfly主题的标签,身为前端的我无脑选择使用NodeJs手撸一个简单的脚本来导出Typecho博客的文章数据。

const mysql = require("mysql");
const fs = require("fs");
const moment = require("moment");
var con = mysql.createConnection({
  host: "数据库地址",
  database: "数据库名",
  user: "数据库用户名",
  password: "数据库密码"
});

// 数据库前缀
const prefix = "typecho_";

con.connect(function (err) {
  if (err) {
    return console.log(err);
  }
});

// 数据库查询语句
const sql = `select title,slug,text,created,modified,category,tags from ${prefix}contents c,(select cid,group_concat(m.name) tags from ${prefix}metas m,${prefix}relationships r where m.mid=r.mid and m.type='tag' group by cid ) t1,(select cid,m.name category from ${prefix}metas m,${prefix}relationships r where m.mid=r.mid and m.type='category') t2 where t1.cid=t2.cid and c.cid=t1.cid`;

con.query(sql, function (err, posts) {
  if (err) {
    console.log(err.message);
    return;
  }

  posts.forEach(function (post) {
    const { title, slug, tags, created: oldCreated, modified: oldModified, text: oldText, category: cat } = post;
    let text = oldText.replace("<!--markdown-->", "");
    const created = moment.unix(oldCreated).format("YYYY-MM-DD HH:mm:ss");
    const updated = moment.unix(oldModified).format("YYYY-MM-DD HH:mm:ss");
    // 封面图
    const regex = /https:\/\/jsd\.onmicrosoft\.cn\/gh\/uxiaohan\/uxiaohan\.github\.io@master\/v2\/(\d{4}\/\d{2}\/\d+)\.(png|jpg|jpeg|gif|mp4)/;
    const match = text.match(regex);
    const cover = match ? match[0] : "";

    // Typecho Joe主题标签 转 Hexo 的 Butterfly 主题标签
    text = text
      .replace(/\{message type="([^"]+)" content="([^"]+)"\/\}/g, (match, type, content) => `{% note purple 'fas fa-info-circle' flat %}\n${content}\n{% endnote %}`)
      .replace(/\{anote\s+icon="([^"]+)"\s+href="([^"]+)"\s+type="([^"]+)"\s+content="([^"]+)"\s*\/\}/g, "[$4 ]($2)")
      .replace(/\{abtn\s+icon="([^"]*)"\s+color="([^"]*)"\s+href="([^"]*)"\s+radius="([^"]*)"\s+content="([^"]*)"\s*\/\}/g, "[$5]($3)")
      .replace(/\{cloud\s+title="([^"]+)"\s+type="([^"]+)"\s+url="([^"]+)"\s+password="([^"]*)"\/\}/g, "[$1]($3)")
      .replace(/\{callout color="([^"]+)"\}/g, "{% note default no-icon %}")
      .replace(/\{gird\s+column="([^"]+)"\s+gap="([^"]+)"\}/g, "{% note default no-icon %}")
      .replace(/\{dplayer\s+src="([^"]+)"\/\}/g, '{% dplayer "url=$1" %}')
      .replace(/{\/callout}/g, "{% endnote %}", "{% gallery %}")
      .replace(/\{\/gird\}/g, "{% endnote %}", "{% endgallery %}")
      .replace(/\{alert type="([^"]+)"\}/g, "{% note default modern %}")
      .replace(/{\/alert}/g, "{% endnote %}")
      .replace(/\{gird-item\}/g, "")
      .replace(/\{\/gird-item\}/g, "")
      .replace(/#([\u4e00-\u9fa5]+)/g, "# $1");

    const fileName_ = title.replace(/\//g, " ").replace(/-/g, " ").replace(/\?/g, " ").replace(/\[/g, "(").replace(/\]/g, ")");
    const filename = "./post/" + fileName_ + ".md";
    fs.appendFileSync(filename, "---\n");
    fs.appendFileSync(filename, "title: " + title.replace(/\[/g, "(").replace(/\]/g, ")").replace(/#/g, " ") + "\n");
    fs.appendFileSync(filename, "date: " + created + "\n");
    fs.appendFileSync(filename, "updated: " + updated + "\n");
    fs.appendFileSync(filename, "categories: " + cat + "\n");
    fs.appendFileSync(filename, "tags:\n- " + tags.replace(/,/g, "\n- ") + "\n");
    fs.appendFileSync(filename, "id: " + slug + "\n");
    fs.appendFileSync(filename, "cover: " + cover + "\n");
    fs.appendFileSync(filename, "---\n");
    fs.appendFileSync(filename, text);
  });
});

con.end();

// 导出完毕后,在脚本目录的`post`目录下,可以看到所有文章的markdown文件。

博客评论导出移步

Typecho评论导出为Hexo的Valine、Twikoo等评论所支持的JSON文件
Typecho Hexo Typecho-Joe-Theme Butterfly 主题