跳至主要內容

搭建一个自己的博客

muzzik大约 4 分钟文章写作

# 成品

点击体验,由 gitee pages 驱动open in new window

# 为什么搭建自己的博客

  • 喷子多,不管理

  • 被删帖,之前发了个把 unity 嵌入 cocos 的帖子后被管理删了

  • 为什么不选择博客园、csdn?广告多,界面不好看

# 选择什么搭建框架?

之前看过了各种框架,中意的有 docusaurusopen in new windowvuepressopen in new window,最终选择了 vuepress

我的需求

  • 博客:存在分类、标签功能,docusaurus 不符合国人操作习惯,vuepress 存在各种主题,甚至完整的博客插件

  • 文档:两个都没问题,但是 vuepress 更方便配置和加功能

优缺点

  • docusaurus

    • 优点:调试快
    • 缺点:前端 Rect 框架(我不了解),文档缺少翻译,开箱即用的主题几乎没有
  • vuepress

    • 优点:入门简单(了解 ts 就能用),插件丰富,开箱即用的主题多
    • 缺点:调试慢

搭建配置

搜索引擎收录

目前只用到了百度,如果需要其他搜索引擎搜索到自己的网站可以去找下

统计服务

为了方便查看浏览量,用户数,可以使用第三方统计服务

我这里使用了 google analyticsopen in new window,不过统计数据上传没问题,如果是请求数据还是需要梯子

F3SVZU_91YZOK8OE.png
F3SVZU_91YZOK8OE.png

自动构建

使用 github actions,可以直接从 github 同步至 gitee,你只需要上传你的文章,github actions 自动构建并同步至 gitee pages,简直不要太方便

imagecb3d0f94a91b9f1d.png
imagecb3d0f94a91b9f1d.png

# 迁移文章

由于我没有多平台发布的习惯,而 cocos 论坛的文章一段时间之后就不能编辑了,这更加坚定了搭建自己博客的需求

试过四五个包括 AI 从 html 标签还原为 markdown 格式都不太行,有各种各样的问题

最终自己花了几小时写了段代码从 html 标签转译为 markdown(存在一些小问题),如下,需要的自取

// 帖子链接 url
fetch("https://forum.cocos.org/t/topic/137919", {
	method: "GET",
	headers: {
		Accept:
			"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
		"Accept-Encoding": "gzip, deflate, br",
		"Accept-Language": "zh-CN,zh;q=0.9",
	},
})
	.then((response) => response.text())
	.then((data) => {
		let start_s = `<div class='post' itemprop='articleBody'>`;
		let end_s = `<meta itemprop=`;
		let start_n = data.indexOf(start_s) + start_s.length;
		let html_s = data.slice(
			start_n,
			data.lastIndexOf("</div>", data.indexOf(end_s, start_n))
		);

		html_s = html_s
			// 去除无用标签
			.replace(/\<span class="badge([^(<\/)]+)\<\/span\>/g, "")
			// 转换超链接
			.replace(/(\<a href="([^"]+)"\>)([^\<]+)\<\/a\>/g, function (...args) {
				return `[${args[3]}](${args[2]})`;
			})
			// 换行
			.replace(/<br>/g, "\n")
			// <
			.replace(/&lt;/g, "<")
			// >
			.replace(/&gt;/g, ">");

		let convert_string_f = (value_s_: string, connect_b_ = false) => {
			if (!value_s_) {
				return value_s_;
			}

			let result_ss: string[] = [];

			while (true) {
				let match_result_as = [
					// 0 标题
					value_s_.match(/<h\d>([^]+?)<\/h\d>/),
					// 1 图片
					value_s_.match(
						/<div class="lightbox-wrapper">([^]+?)<img src="([^]+?)"([^]+?)width="([^]+?)" height="([^]+?)"([^>\n]*)/
					),
					// 2 引用
					value_s_.match(/<blockquote>([^(blockquote)]+)<\/blockquote>/),
					// 3 内容
					value_s_.match(/<p>([^]*?)<\/p>/),
					// 4 选项标题
					value_s_.match(/<li>([^]+?)<ul>/),
					// 5 选项
					value_s_.match(/<li>([^]+?)<\/li>/),
					// 6 代码块
					value_s_.match(/<code([^]+?)>([^]+?)([\n]*)<\/code>/),
					// 7 单代码块
					value_s_.match(/<code>([^]+?)([\n]*)<\/code>/),
					// 8 加粗
					value_s_.match(/<strong>([^]+?)<\/strong>/),
					// 9 下划线
					value_s_.match(/<hr>/),
					// 10 图片
					value_s_.match(
						/<img src="([^]+?)"([^]+?)width="([^]+?)" height="([^]+?)"([^>]*)/
					),
				];

				/** 最接近的下标 */
				let closest_index_n = -1;

				// 查找最近数据
				{
					match_result_as.forEach((v, k_n) => {
						if (!v) {
							return;
						}

						if (
							closest_index_n === -1 ||
							v.index! < match_result_as[closest_index_n]!.index! ||
							(v.index! === match_result_as[closest_index_n]!.index! &&
								v[0].length < match_result_as[closest_index_n]![0]!.length)
						) {
							closest_index_n = k_n;
						}
					});
				}

				if (closest_index_n === -1) {
					break;
				}

				let match_result = match_result_as[closest_index_n]!;

				// 链接头
				if (!connect_b_) {
					result_ss.push(value_s_.slice(0, match_result.index!));
				}

				// 更新内容
				value_s_ = value_s_.slice(match_result.index! + match_result[0].length);

				// 转换数据
				switch (closest_index_n) {
					// 标题
					case 0: {
						result_ss.push(
							`${new Array(Number(match_result[0].match(/\d/)![0]))
								.fill("#")
								.join("")} ${match_result[1]}`
						);
						break;
					}
					// 图片
					case 1: {
						result_ss.push(
							`![](${match_result[2]} =${match_result[4]}x${match_result[5]})`
						);
						break;
					}
					// 图片
					case 10: {
						result_ss.push(
							`![](${match_result[1]} =${match_result[3]}x${match_result[4]})`
						);
						break;
					}
					// 引用
					case 2: {
						result_ss.push(
							match_result[1]
								.replace(/\<\/p\>\<p\>/g, "\n")
								.replace(/(\<p\>)|(\<\/p\>)/g, "")
								.replace(/\n/g, "\n> ")
								.slice(1, -3)
						);
						break;
					}
					// 内容
					case 3: {
						result_ss.push(convert_string_f(match_result[1]));
						break;
					}
					// 标题
					case 4: {
						result_ss.push(`- ${convert_string_f(match_result[1])}`);
						break;
					}
					// 选项标题
					case 5: {
						result_ss.push(`   - ${convert_string_f(match_result[1])}`);
						break;
					}
					// 代码块
					case 6: {
						let code_s = match_result[2].replace(
							/<span class="hljs-([^]+?)">([^]+?)<\/span>/g,
							function (...args) {
								return args[2];
							}
						);

						let language_s =
							match_result[1].match(/class="lang-([^( |")]+)/)?.[1] ?? "";

						result_ss.push(`\`\`\`${language_s}\n${code_s}\n\`\`\``);
						break;
					}
					// 单代码块
					case 7: {
						let code_s = match_result[1].replace(
							/<span class="hljs-([^]+?)">([^]+?)<\/span>/g,
							function (...args) {
								return args[2];
							}
						);

						result_ss.push(`\`${code_s}\``);
						break;
					}
					// 加粗
					case 8: {
						result_ss.push(`*${convert_string_f(match_result[1])}*`);
						break;
					}
					// 下划线
					case 9: {
						result_ss.push(`\n---\n`);
						break;
					}
				}
			}

			return result_ss.length === 0
				? value_s_
				: result_ss.join(connect_b_ ? "\n" : "");
		};
		html_s = convert_string_f(html_s, true);
		console.log(html_s);
	});

📣 觉得很赞?分享给你的朋友吧!