diff --git a/.github/workflows/CDN-URL.yaml b/.github/workflows/CDN-URL.yaml
index 749c5bd..8cebc29 100644
--- a/.github/workflows/CDN-URL.yaml
+++ b/.github/workflows/CDN-URL.yaml
@@ -14,13 +14,15 @@ jobs:
- uses: actions/checkout@v2
- name: Find and Replace Release
- uses: jacobtomlinson/gha-find-replace@0.1.1
+ uses: jacobtomlinson/gha-find-replace@2.0.0
with:
find: "blog-1301127393.cos.ap-shanghai.myqcloud.com"
replace: "blog-1301127393.file.myqcloud.com"
+ include: "**/*.md"
+
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v3
+ uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "Change img CDN URL"
diff --git a/.github/workflows/azure-static-web-apps-nice-glacier-095b09e00.yml b/.github/workflows/azure-static-web-apps-nice-glacier-095b09e00.yml
new file mode 100644
index 0000000..8ec7c76
--- /dev/null
+++ b/.github/workflows/azure-static-web-apps-nice-glacier-095b09e00.yml
@@ -0,0 +1,47 @@
+name: Azure Static Web Apps CI/CD
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ types: [opened, synchronize, reopened, closed]
+ branches:
+ - master
+
+jobs:
+ build_and_deploy_job:
+ if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
+ runs-on: ubuntu-latest
+ name: Build and Deploy Job
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ submodules: true
+ - name: Build And Deploy
+ id: builddeploy
+ uses: Azure/static-web-apps-deploy@v1
+ with:
+ azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_GLACIER_095B09E00 }}
+ repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
+ action: "upload"
+ ###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
+ # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
+ app_location: "/" # App source code path
+ api_location: "" # Api source code path - optional
+ output_location: "public" # Built app content directory - optional
+ ###### End of Repository/Build Configurations ######
+ env:
+ HUGO_VERSION: 0.91.2
+
+ close_pull_request_job:
+ if: github.event_name == 'pull_request' && github.event.action == 'closed'
+ runs-on: ubuntu-latest
+ name: Close Pull Request Job
+ steps:
+ - name: Close Pull Request
+ id: closepullrequest
+ uses: Azure/static-web-apps-deploy@v1
+ with:
+ azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_NICE_GLACIER_095B09E00 }}
+ action: "close"
diff --git a/.github/workflows/mardkwon-SEO.yaml b/.github/workflows/mardkwon-SEO.yaml
index d417d27..320c002 100644
--- a/.github/workflows/mardkwon-SEO.yaml
+++ b/.github/workflows/mardkwon-SEO.yaml
@@ -1,8 +1,6 @@
-name: SEO check
+name: MD SEO check
-on:
- push:
- branches: [ master ]
+on: [pull_request]
jobs:
seocheck:
@@ -13,7 +11,7 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Markdown SEO Check
- uses: zentered/markdown-seo-check@v1.1.0
+ uses: zentered/markdown-seo-check@v1.1.5
with:
max_title_length: 70
max_description_length: 150
diff --git a/README.md b/README.md
index 2f324ca..b1f0222 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,17 @@
# Colinx-Blog
+[](https://app.netlify.com/sites/colins-blog/deploys)
+
+
+
Colin's Personal Blog http://blog.colinx.one
+
+## Mirrors
+This site has been deployed to multiple static web hosting providers, for load balacing and performance testing.
+* Netlify
+[colins-blog.netlify.app](https://colins-blog.netlify.app)
+* Vercel
+[colinx-blog.vercel.app](https://colinx-blog.vercel.app)
+* CloudFlare Pages
+[colinx-blog.pages.dev](https://colinx-blog.pages.dev)
+* Azure Static Web
+[nice-glacier-095b09e00.1.azurestaticapps.net](https://nice-glacier-095b09e00.1.azurestaticapps.net)
\ No newline at end of file
diff --git a/config.toml b/config.toml
index 18750bf..e1d6314 100644
--- a/config.toml
+++ b/config.toml
@@ -2,6 +2,7 @@ baseurl = "/"
languageCode = "en-us"
defaultContentLanguage = "zh-cn"
defaultContentLanguageInSubdir = false
+hasCJKLanguage = true
theme = "hello-friend"
paginate = 10
enableRobotsTXT = true
@@ -21,6 +22,9 @@ showReadingTime = false
# leave empty to disable, enter display text to enable
lastModDisplay = "最后修改"
rssFullText = true
+# custom params
+# The values nested under params: will populate the .Site.Params variable for use in templates
+canonicalRelLinkBase = 'https://blog.colinx.one/'
[languages]
[languages.en]
@@ -37,12 +41,10 @@ rssFullText = true
minuteReadingTime = "min read"
dateFormatSingle = "2006-01-02"
dateFormatList = "2006-01-02"
-
[languages.en.params.logo]
logoText = "Colinx Blog"
logoHomeLink = "/"
# or
- #
# path = "/img/your-example-logo.svg"
# alt = "Your example logo alt text"
@@ -67,7 +69,7 @@ rssFullText = true
[languages.zh-cn]
title = "Colinx Blog"
subtitle = "Colin的个人博客"
-keywords = "Colin,个人博客"
+keywords = "Colin,个人博客,技术,后端,Linux,前端"
copyright = ""
menuMore = "显示更多"
writtenBy = "作者"
diff --git a/content/_index.md b/content/_index.md
new file mode 100644
index 0000000..1df5dd2
--- /dev/null
+++ b/content/_index.md
@@ -0,0 +1,9 @@
++++
+framed = true
++++
+
+# Hi there!
+
+Welcome to my blog👋 Check these
+
+[💻 技术文章](/categories/%E6%8A%80%E6%9C%AF/) | [📖 My Readings](https://reading.colinx.one) | [💡 My Github](https://github.com/Colin-XKL/)
diff --git a/content/posts/Colin's Blog 1.0 构建心得.md b/content/posts/Colin's Blog 1.0 构建心得.md
index 5854aff..5cb94fd 100644
--- a/content/posts/Colin's Blog 1.0 构建心得.md
+++ b/content/posts/Colin's Blog 1.0 构建心得.md
@@ -4,7 +4,7 @@ date: 2019-04-08
lastmod: 2020-04-29
description: 经过两三天的折腾,从 Linux 结构及指令,到 LNMP 框架搭建,再到数据库的配置,最后端口转发 + 内网穿透,博客终于成功上线!在此将部署过程及踩过的坑记录下来,一方面是纪念,另一方面希望能够后来人提供一点帮助。
categories:
-- 踩坑记
+- 技术
tags:
- Blog
- 网站
diff --git a/content/posts/Colin's 实验室 - 2021春.md b/content/posts/Colin's 实验室 - 2021春.md
index 53582b8..c722f04 100644
--- a/content/posts/Colin's 实验室 - 2021春.md
+++ b/content/posts/Colin's 实验室 - 2021春.md
@@ -4,7 +4,7 @@ date: 2021-02-25
lastmod: 2021-03-30
description: 小玩具及他们的demo
categories:
-- 杂记
+- 技术
tags:
- 技术
- Python
@@ -22,7 +22,7 @@ tags:
> 自动分割给定的英文文本,提取词元后在数据库中搜索,根据给定的词汇量和难度等级进行筛选,只能提取阅读障碍词汇并高亮当前备考项目(如四级)的重点单词
- 
+ 
## 知乎爬虫及JS逆向
@@ -40,7 +40,7 @@ tags:
> 1核2G学生机,从2人联机频频崩溃到8人挖矿毫无压力,学习了JVM GC种种,对服务端程序的一些参数也渐渐熟悉。优化效果喜人,总有还能压榨的性能,就像资本家看手下的骡子一样hhh
-
+
@@ -48,7 +48,7 @@ tags:
> 一款跨平台的灵感素材收集与简易管理App,基于Flutter构建,跨平台,颜值在线。
-
+
> 持续开发中,附roadmap
>
diff --git a/content/posts/Flutter 拖动排序列表与跨平台优化实践.md b/content/posts/Flutter 拖动排序列表与跨平台优化实践.md
index 4fad03c..8ae14ba 100644
--- a/content/posts/Flutter 拖动排序列表与跨平台优化实践.md
+++ b/content/posts/Flutter 拖动排序列表与跨平台优化实践.md
@@ -4,7 +4,7 @@ date: 2021-03-30
lastmod: 2021-03-30
description: Flutter 拖动排序列表与跨平台优化实践
categories:
-- 教程
+- 技术
tags:
- 技术
- Flutter
@@ -46,7 +46,7 @@ Flutter中实现拖动排序的列表非常简单,使用官方的`ReorderableL
-
+
虽然可以实现拖动了,但是右边有一个按钮很碍眼。不过这个是用来控制拖动的,鼠标移上去才能触发拖动。
@@ -65,7 +65,7 @@ Flutter中实现拖动排序的列表非常简单,使用官方的`ReorderableL
不过相应的,ListTile的`onLongPress`就不能再有响应了。刚好今天完成了滑动删除的实现,现在列表也的删除、排序已经高度可用且多平台统一了。
-
+
附相关代码实现:
diff --git a/content/posts/Huginn指南:为任意网站制作RSS.md b/content/posts/Huginn指南:为任意网站制作RSS.md
new file mode 100644
index 0000000..b20f8e1
--- /dev/null
+++ b/content/posts/Huginn指南:为任意网站制作RSS.md
@@ -0,0 +1,310 @@
+---
+title: Huginn指南:为任意网站制作RSS
+date: 2022-05-08
+lastmod: 2022-05-08
+description: 又一篇介绍使用Huginn制作RSS的教程🕶️
+categories:
+- 技术
+- 指南
+tags:
+- Huginn
+- RSS
+- 爬虫
+- CSS
+- 技术
+---
+
+
+
+Huginn使用多个不同功能的Agent组合搭配来实现一系列功能,一个Agent可以执行特定的操作,并产生一个Event,你可以指定他产生的Event由哪个Agent接收处理。
+
+比如我们需要使用WebSite Agent来爬取某个网站上的列表内容,爬取后列表的每一项会生成一个Event,我们可以指定一个Output Agent来接收这些Event,并将其转换为RSS的格式进行输出,复制Output Agent返回给你的URL就可以进行订阅啦,Huginn爬取网站生成RSS的基本原理就是这样。
+
+## Huginn爬取普通网页制作RSS
+
+
+
+右键网页打开开发者工具,屏幕会分出一部分空间显示开发者工具窗口,点击左上角的按钮再把鼠标移动到页面上可以选择页面的某一个元素,比如这里我们要爬取推荐文章列表,推荐文章列表的每一项都有同样的样式,我们可以使用CSS选择器来指定爬取该项
+
+
+
+
+
+该元素可以用CSS选择器`.meiwen`选择到。
+
+**Tips:** class=xxx则使用`.xxx`,如果为id=xxx则使用`#xxx`
+
+该标签是a标签,我们可以继续限定一下条件,使用`a.meiwen`
+
+如果要限制必须是h2 标签下的带有meiwen的class属性的a标签,可以使用`h2 a.meiwen`
+
+如果要再加一个限制,是列表元素li下面的h2标签里带有meiwen的class属性的a标签,可以使用`li h2 a.meiwen`
+
+添加其他附加限定条件以此类推
+
+你也可以在右侧Style面板里点击加号添加一个自定义样式,输入CSS选择器,浏览器会自动高亮符合条件的网页元素,你可以使用这个功能来检验你写的CSS选择器是否正确以及是不是提取的你想要的内容
+
+
+
+
+
+
+
+接下来在Huginn里创建一个Scenario,然后点击新建一个Agent,类型选择WebSite Agent,填写一个名称,并在最下面的配置处指定你要爬取的网页元素
+
+> ###### **Website Agent**
+>
+> The Website Agent scrapes a website, XML document, or JSON feed and creates Events based on the results.
+
+```json
+url: {
+ css: li h2 a.meiwen
+ value: @href
+}
+```
+
+以爬取url为例,css表示使用css选择器选择网页元素,value表示从哪里获取对应的值,对于刚才我们选取的一个元素来说
+
+```html
+缘起则聚,缘灭则散
+```
+
+href属性里面的内容是他的链接,title属性里面的内容则是他的标题。接下来在value中填写`@href`指定从href属性提取内容,就可以取到链接地址了
+
+> **Pro Tips:**
+>
+> 如果是纯文本节点或是想提取标签内嵌的文本,value里可以填写`string(.)`
+>
+> 如果想删除多余的空格,可以使用`normalize-space(.)`
+
+> **Pro Tips 2:**
+>
+> 字符串处理函数和标签属性值变量可以一起使用,如`normalize-space(@title)`可以获取该标签的title属性值并删除多余的空白字符
+
+
+
+接下来点击Dry Run按钮进行测试,不出意外我们会得到一个json的输出,里面包括我们爬取到的每一项他的url和title。
+
+如果没有成功,你可能需要删掉上面没有使用到的hovertext节点,因为该项指定的内容在我们刚才的网页中并不存在。
+
+
+
+
+
+点击Save保存,我们开始下一步输出RSS。在刚才的Scenario中再新建一个Agent,选择Data Output Agent,并设置他的名字和Source Agent
+
+> ###### Data output Agent
+>
+> The Data Output Agent outputs received events as either RSS or JSON. Use it to output a public or private stream of Huginn data.
+
+
+
+
+
+**Propagate immediately**是指即时处理来自Source Agent的Event,启用他方便我们调试,但会略微增加服务器负载,你可以自行决定是否使用。
+
+
+
+在secret字段中为你的这个RSS标注一个英文的名字,修改title字段标注你的RSS的名字。item字段是每条文章会有的属性,一般来说主要就title和link,分别设置为上文我们提取的值的变量名。这里添加一个guid字段,这是一篇文章的唯一标识符,避免RSS阅读器读到的文章标题不同但是内容相同,常见于某篇文章的标题被修改,这会导致RSS阅读器内出现多篇重复文章。
+
+此外建议增加一个link字段,值设置为与爬取的网站的主域名一致,避免网站内使用相对链接开头的资源无法正常加载。
+
+
+
+
+
+
+
+点击Save保存,回到Scenario界面,第一次需要手动点击运行一下刚才的Website Agent。稍等片刻后台会进行爬取,右上角会显示产生了多少个Event。再点开刚才设置的Data Output Agent查看详情,vola!右侧就会显示生成的RSS链接了,复制以xml结尾的链接到RSS阅读器中就可以订阅啦🎉
+
+
+
+
+
+
+
+如果你的配置正确但是WebSite Agent又没有输出任何内容的话,那么你要爬取的站点的内容应该是通过JavaScript在你带开浏览器时动态生成的。
+
+> **Pro Tips:**
+>
+> 你可以右键网页在开发人员菜单中点击显示源代码,然后用Ctrl+F搜索你在页面上见到的想爬取的某一条内容,如果有说明该网站的页面时静态的,否则说明你要爬取的内容并不是静态的。
+
+要爬取这样的站点,我们需要模拟浏览器操作,执行页面上的JavaScript脚本,待数据生成完毕后再使用上面的方法去爬取内容。要模拟浏览器操作,这里介绍两个方案:一个是利用browserless的无头浏览器,另一个是使用在线PhatomJS服务。
+
+
+
+## 使用Huginn+Browserless为动态网页生成RSS
+
+
+
+部署了[RSS Man X](https://github.com/Colin-XKL/RSSmanX)的完整版的话默认已经包含huginn和browserless服务,无需重复安装。且huginn可以通过`service.browserless:3000`访问到browserless服务。
+
+总体步骤与上文一样,不过因为被抓取的内容是通过JavaScript动态生成的,所以直接使用WebSite Agent是抓取不到东西的,我们需要先使用Post Agent向browserless服务发送指令,让他帮我们模拟浏览器操作,再将最终完整的网页返回给我们,再使用WebSite Agent进行后续处理。
+
+> ###### **Post Agent**
+>
+> A Post Agent receives events from other agents (or runs periodically), merges those events with the Liquid-interpolated contents of payload, and sends the results as POST (or GET) requests to a specified url. To skip merging in the incoming event, but still send the interpolated payload, set no_merge to true.
+
+接下来以[这个网站](https://pccz.court.gov.cn/pcajxxw/pcgg/ggdh?lx=0)为例介绍一下,这个列表页的内容是由JavaScript动态生成的
+
+
+
+按照以下内容设置你的Post Agent
+
+```json
+{
+ "post_url": "http://service.browserless:3000/content",
+ "expected_receive_period_in_days": "1",
+ "content_type": "json",
+ "method": "post",
+ "payload": {
+ "url": "https://pccz.court.gov.cn/pcajxxw/pcgg/ggdh?lx=0"
+ },
+ "headers": {
+ "Cache-Control": "no-cache",
+ "Content-Type": "application/json"
+ },
+ "emit_events": "true",
+ "no_merge": "false",
+ "output_mode": "clean"
+}
+```
+
+其中`post_url`为你的browserless实例地址,如果你使用了RSS MAN X里的Huginn可以直接向上面一样填写。`payload`中的`url`字段填写你需要的网页地址。注意emit_events要设置为`true`,这样才方便我们后续使用WebSite Agent操作。
+
+点击Dry Run,如果能返回一个带有`body`字段且里面有文本内容说明调用成功
+
+
+
+接下来点击Save保存,再新建一个Website Agent,Source设置为刚才的Post Agent。
+
+```json
+{
+ "expected_update_period_in_days": "2",
+ "data_from_event": "{{ body }}",
+ "type": "html",
+ "mode": "on_change",
+ "extract": {
+ "url": {
+ "css": "ul#wslb li a",
+ "value": "normalize-space(@href)"
+ },
+ "title": {
+ "css": "ul#wslb li a",
+ "value": "@title"
+ },
+ "author": {
+ "css": "ul#wslb li div.center",
+ "value": "normalize-space(.)"
+ }
+ }
+}
+```
+
+
+
+注意修改`data_from_event`的值,其他地方与爬取普通网站一样。再新建并配置一下Output Agent,RSS的链接就出来了
+
+
+
+
+
+## 使用PhantomJS为动态页面生成RSS
+
+首先需要到[Phantom Js Cloud的官网](https://phantomjscloud.com)注册一个账户,每个账户官方提供了一定的免费额度,每天大概可以爬取500个页面,对于做RSS来说妥妥的够用了。注册之后可以得到一个API KEY,这个待会会使用到。
+
+接下来新建一个Phantom JS Cloud Agent,填写基本的名称、API KEY和目标URL,render type选择html。底下User Agent建议改用真实的浏览器UA,减少触发反爬虫的可能性。如果不知道自己的UA可以到这个网站查看当前浏览器的UA,复制字符串即可。如果懒得查也可以用这个
+
+```
+Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.81 Safari/537.36
+```
+
+> ###### Phantom JS Cloud Agent
+>
+> This Agent generates PhantomJs Cloud URLs that can be used to render JavaScript-heavy webpages for content extraction.
+>
+> URLs generated by this Agent are formulated in accordance with the PhantomJs Cloud API. The generated URLs can then be supplied to a Website Agent to fetch and parse the content. Sign up to get an api key, and add it in Huginn credentials.
+
+点击Dry Run后会返回一条url,返回格式类似这样
+
+```json
+[
+ {
+ "url": "https://phantomjscloud.com/api/browser/xxxxxxx"
+ }
+]
+```
+
+之后创建一个WebSite Agent,Source Agent设置为上面的Phantom JS Cloud Agent,然后稍微改一下url的部分
+
+```json
+{
+ "expected_update_period_in_days": "2",
+ "url_from_event": "{{url}}",
+ "type": "html",
+ "mode": "on_change",
+ "extract": {...}
+}
+```
+
+注意将原来的`url:??`的部分更改为`"url_from_event": "{{url}}"`,这样就指定使用Phantom JS Cloud为我们获取的完整网页,接下来的操作就大同小异了。配置好要爬取的字段和规则后点击Dry Run就可以看到结果
+
+
+
+
+
+这里是刚才的Agent产生的一个Event。这里除了url和title我还提取了date字段。在Output Agent中,可以配置为每一条文章输出发布时间的信息。对于这种规整的日期字母串,可以使用`{{ date | date: %F }}`进行解析并格式化输出为rss规范的时间格式如果没有配置的话,每篇文章的发布时间显示的都是一样的,为Huginn爬虫更新的时间。
+
+```json
+"item": {
+ "title": "{{title}}",
+ "link": "{{url}}",
+ "pubDate": "{{ date | date: %F }}"
+ },
+```
+
+> **Pro Tips:**
+>
+> Huginn解析日期
+>
+> 注意`{{ date | date: %F }}`里面,第一个`date`是上面的Website Agent产生的Event里面的变量名,第二个`date`是Huginn使用的Liquid模版引擎语法里内置的一个filter,可以理解为有特定功能的函数
+
+
+
+
+
+
+
+
+
+
+
+## FAQ
+
+* **为什么启动docker容器后访问Huginn显示网络错误?**
+
+ Huignn冷启动较慢,需要等待三五分钟。如果还是不行,检查端口映射和防火墙设置
+
+* **为什么抓取到的包含相对路径的结果,网页上可以点击访问,但是生成的RSS不能正常使用?**
+
+ 检查link的设置,有些网站只是域名,有些网站有子目录,具体查看该网页源码中head节点里base url的设置
+
+* 如何对爬取到的某一项的字符串做更高级更复杂的处理?
+
+ 可以参考[Hugnn官方对Liquid语法的文档](https://github.com/huginn/huginn/wiki/Formatting-Events-using-Liquid)以及[Shopify官方关于Liquid模板的语法文档](https://shopify.dev/api/liquid)
+
+* **为什么部署了Huginn,等了很长时间都无法访问后台页面?**
+
+ 若部署后某个应用一直无法通过浏览器访问,请检查是否绑定到了6000/6666等特殊端口,浏览器会拦截对这些端口的访问参见[这里](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)
+
+
+
+## 扩展阅读
+
+* [Huginn官方文档](https://github.com/huginn/huginn/wiki/)
+* [Liquid模板引擎语法官方文档](https://shopify.dev/api/liquid/filters/)
+* [RSS Man X部署指南](https://blog.colinx.one/posts/rssmanx%E5%AE%89%E8%A3%85%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97/)
+* [docker compose 的错误使用姿势](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)
+
+
+
diff --git a/content/posts/JAMStack初体验 - 基于Pocket 和 Gatsby 构建你的「网络日志」.md b/content/posts/JAMStack初体验 - 基于Pocket 和 Gatsby 构建你的「网络日志」.md
index 2074416..6aa4082 100644
--- a/content/posts/JAMStack初体验 - 基于Pocket 和 Gatsby 构建你的「网络日志」.md
+++ b/content/posts/JAMStack初体验 - 基于Pocket 和 Gatsby 构建你的「网络日志」.md
@@ -4,7 +4,7 @@ date: 2021-01-09
lastmod: 2021-01-10
description: 折腾了自己的专属RSS信息流,每天都能从那些高质量的信息源中获得不少干货知识,一般就会顺手收藏一下。有一天突然想起自己收藏的那些文章,本身不就是经过二次筛选的高质量文章吗?于是便在构想能不能通过某种方式将这个信息源也公开出来,一方面是记录,另一方面也是间接地展示自己。恰逢遇见JAMStack,最近在国外非常火,国内的阿里和腾讯也在跟进,搞静态托管那一套。经多方物色,最终确定基于Pocket API+Gatsby来构建这样一个自己的「网络日志」。
categories:
-- 教程
+- 技术
tags:
- 技术
- JAMStack
diff --git a/content/posts/Mac平台配置学习环境.md b/content/posts/Mac平台配置学习环境.md
index b67fc9f..fb66036 100644
--- a/content/posts/Mac平台配置学习环境.md
+++ b/content/posts/Mac平台配置学习环境.md
@@ -4,7 +4,7 @@ date: 2020-12-18
lastmod: 2020-12-19
description: Mac 平台配置C/Python/Java学习环境
categories:
-- 教程
+- 技术
- 指南
tags:
- C
@@ -36,7 +36,7 @@ tags:
C语言的编译需要编译器,一般可以选择gcc或是clang。Mac系统默认安装了clang同时兼容了gcc的指令。在终端中进行查看:
-
+
输入`gcc -v`指令测试gcc命令是否可用并查看其版本,由上图输出可以看到,该命令可用,版本信息显示的则是clang的信息。一般来说,刚学习C语言无需关注两者的异同。
@@ -48,35 +48,35 @@ C语言的编译需要编译器,一般可以选择gcc或是clang。Mac系统
如果下载速度太慢,可以参考[这篇文章](https://zhuanlan.zhihu.com/p/112215618)。
-
+
安装完毕后,打开会看到如下图所示的界面。默认界面为英文,下面对其进行汉化并安装一些必要的插件。
-
+
单击方形图标,打开扩展面板。
-
+
搜索`chinese`安装汉化插件。
-
+
搜索`code runner`安装Code Runner插件。并按指示重启应用(Reload字样)
-
(截图中因为本地已安装故只显示了Uninstall卸载按钮。未安装的情况下会显示Install按钮可点击安装)
+
(截图中因为本地已安装故只显示了Uninstall卸载按钮。未安装的情况下会显示Install按钮可点击安装)
其他插件可根据需要安装。此处推荐安装C/C++插件以实现C代码的高亮和补全等功能。
-
+
-重启后进入应用,界面自动切换到中文。再点击扩展图标,展开扩展列表,在已安装扩展中找到**Code Runner**,点击齿轮图标展开菜单,点击进入扩展设置。
+重启后进入应用,界面自动切换到中文。再点击扩展图标,展开扩展列表,在已安装扩展中找到**Code Runner**,点击齿轮图标展开菜单,点击进入扩展设置。
-在输入栏中,在当前选项卡为**用户**的情况下,输入`run`并按回车进行搜索。修改`Run in Terminal`和 `Save File Before Run`的设置项。
+在输入栏中,在当前选项卡为**用户**的情况下,输入`run`并按回车进行搜索。修改`Run in Terminal`和 `Save File Before Run`的设置项。
@@ -86,19 +86,19 @@ C语言的编译需要编译器,一般可以选择gcc或是clang。Mac系统
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
-
+
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.c`
-
+
键入代码。
-
+
点击右上角的三角形按钮即可自动编译运行你的C语言代码。在窗口下方的终端即可看到输出的`Hello,C!`字样。
-
+
### 完成✅
@@ -116,13 +116,13 @@ C语言的编译需要编译器,一般可以选择gcc或是clang。Mac系统
Mac系统会自带有Python环境。在终端中输入python并回车。
-
+
可以看到系统已经安装有Python,但是显示版本为2.7。现在的主流版本是Python3,Python2与Python3的语法并不兼容。
在`>>>`后面键入`exit()`退出python2的交互程序。再次在终端输入`python3`
-
+
@@ -132,7 +132,7 @@ Mac系统会自带有Python环境。在终端中输入python并回车。
在交互式命令行界面,我们可以直接输入python语句并执行。
-
+
一句一句地输入代码再执行显然太低效了。我们需要一个趁手的代码编辑器。
@@ -146,25 +146,25 @@ Mac系统会自带有Python环境。在终端中输入python并回车。
-
+
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
-
+
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.py`
-
+
键入代码。
-
+
点击右上角的三角形按钮开始运行我们编写的代码
-
+
@@ -201,13 +201,13 @@ Mac OS并没有内置Java语言的支持,需要我们另外安装。
下载完成后点击打开,出现如下的安装界面。根据指引完成安装。
-
+
安装完成后,在终端中输入`java -version`并回车确认。看到如下输出说明已经正确安装且Java的版本为`11.0.9.1`即Java 11.
-
+
下面来为Java的学习配置一个趁手的代码编辑器,以VSCode为例。
@@ -221,23 +221,23 @@ Mac OS并没有内置Java语言的支持,需要我们另外安装。
在左侧扩展面板的搜索栏中搜索`java`,选择`Language Support for Java`并安装。
-
+
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
-
+
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.java`
-
+
键入代码。
-
+
可以看到,在窗口下方的终端面板中,已经成功出现了**Hello, Java!**字样,代码运行成功。
-
+
### 完成✅
@@ -253,7 +253,7 @@ Mac OS并没有内置Java语言的支持,需要我们另外安装。
-
+
这是因为插件内置的一些功能需要Java来运行,而这些功能又依赖于一些较新的特性,这些特性最早出现在Java 11中。为了更好地学习和使用Java,这里推荐安装Java 11 或Java 12。网站教程或学校授课常常以Java 8为例,但对于初学者来说,几者无太大区别,Java 8的代码都可以被很好地支持。
diff --git a/content/posts/Minecraft上云笔记 - MC服务器快速搭建&MOD推荐&性能优化.md b/content/posts/Minecraft上云笔记 - MC服务器快速搭建&MOD推荐&性能优化.md
index 0d54404..786a5f3 100644
--- a/content/posts/Minecraft上云笔记 - MC服务器快速搭建&MOD推荐&性能优化.md
+++ b/content/posts/Minecraft上云笔记 - MC服务器快速搭建&MOD推荐&性能优化.md
@@ -4,7 +4,7 @@ date: 2021-02-07
lastmod: 2021-02-07
description: Minecraft上云笔记 - MC服务器快速搭建&MOD推荐&性能优化。MC快速上云,学生机轻松带动,三五好友,畅快联机
categories:
-- 教程
+- 技术
- 指南
tags:
- Java
@@ -89,7 +89,7 @@ services:
ONLINE_MODE: "FALSE" #正版校验开关
ALLOW_FLIGHT: "FALSE"
USE_AIKAR_FLAGS: "false" # 一些优化
- RESOURCE_PACK: "https://blog-1301127393.cos.ap-shanghai.myqcloud.com/MC/Distribution/VNR-1.0.1.zip" # 我自己会用的资源包,这里填url
+ RESOURCE_PACK: "https://blog-1301127393.file.myqcloud.com/MC/Distribution/VNR-1.0.1.zip" # 我自己会用的资源包,这里填url
NETWORK_COMPRESSION_THRESHOLD: 512 # 网络优化
restart: unless-stopped
rcon:
@@ -146,7 +146,7 @@ volumes:
上一张HMCL的主页的图:
-
+
其他没有使用过的启动器暂时不予评价。
@@ -344,7 +344,7 @@ MC服务器的优化主要聚焦在两个地方
* 联机游戏间或卡顿,但很快恢复
* 查看日志发现空载时时竟然仍会`can't keep up`
-
+
@@ -364,8 +364,7 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
* **G1GC天生是为了现代互联网应用环境而设计的**,需要开很多个线程协同来完成垃圾回收工作。他适用于多核处理器+大内存机器上的高负荷运算。而我的服务器是单核,内存也并不富裕。
* **多线程的GC模式跑在单核机器上**时出现的问题就是:单核机器无法并行处理多个任务,其本质上只是在多个任务之间快速切换,来实现各个任务基本“实时”“并行”运行。但是线程之间的切换是有代价的,**性能损耗积少成多**。
-* **G1GC追求在延迟可控的情况下达到更高的吞吐量**。但他的**代价是[更多的内存占用](jvm G1 垃圾收集器有什么缺点? - SegmentFault 思否
- https://segmentfault.com/q/1010000021658061)。**小内存机器并不适合使用G1GC。
+* **G1GC追求在延迟可控的情况下达到更高的吞吐量**。但他的**代价是[更多的内存占用](https://segmentfault.com/q/1010000021658061)。**小内存机器并不适合使用G1GC。
物色了一番,我最终选择换用Serial GC代替原本的G1GC。
@@ -382,19 +381,19 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
1. 优化前MC服务器的资源占用情况
-
+
2. SERIAL GC (1 ONLINE)
-
+
3. 进一步对mod优化后,2 online
-
+
@@ -412,11 +411,11 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
我家:
-
+
-
+
@@ -424,13 +423,13 @@ JVM优化的大头是GC。网上吹的漫天飞的G1GC的确有他的可取之
我安装的光影 Sildurs Vibrant Shaders v1.281 High 效果图
-
+
Better HUD + 旅行地图效果图
-
+
diff --git a/content/posts/Minecraft上云笔记 - MC自定义皮肤并支持联机.md b/content/posts/Minecraft上云笔记 - MC自定义皮肤并支持联机.md
index de96203..2914912 100644
--- a/content/posts/Minecraft上云笔记 - MC自定义皮肤并支持联机.md
+++ b/content/posts/Minecraft上云笔记 - MC自定义皮肤并支持联机.md
@@ -4,7 +4,7 @@ date: 2021-02-22
lastmod: 2021-02-22
description: Minecraft上云笔记 - MC自定义皮肤并支持联机
categories:
-- 教程
+- 技术
- 指南
tags:
- Java
@@ -15,8 +15,6 @@ tags:
- 游戏
- 服务器
-
-
---
diff --git a/content/posts/RSSManX.md b/content/posts/RSSManX.md
index b87c4a2..3cde324 100644
--- a/content/posts/RSSManX.md
+++ b/content/posts/RSSManX.md
@@ -4,7 +4,7 @@ date: 2021-05-08
lastmod: 2021-05-08
description: 网站没有源,海外站的源看不了?这也许是第一个自带海外加速的RSS解决方案
categories:
- - 教程
+ - 技术
- 指南
tags:
- RSS
@@ -12,14 +12,10 @@ tags:
- Github
- 代理
---
-

-
-
-
-
-
+
+
[中文说明](https://github.com/Colin-XKL/RSSmanX/blob/master/README-zh_cn.md) | [English](https://github.com/Colin-XKL/RSSmanX/)
@@ -29,7 +25,7 @@ tags:
**Feature: 简单一键部署,常用组件支持,自动更新支持,服务健康自检支持,海外站点 RSS 解锁**
-## 快速开始
+### 快速开始
(若已安装 `docker` 和 `docker-compose`)
@@ -37,7 +33,7 @@ tags:
mkdir RSSmanX && cd $_ && wget https://cdn.jsdelivr.net/gh/Colin-XKL/RSSmanX/docker-compose.yml && sudo docker-compose up -d
```
-# 说明
+## 说明
本项目旨在为 RSS 的同好提供一个方便地搭建自己的 RSS 服务的捷径。毕竟不是所有 RSS 爱好者都懂代码 😂。如果你想快速地搭建自己的 RSS 服务,能够有 RSS 订阅管理、RSS 在线阅读界面,进阶功能包括服务健康自检、海外站点 RSS 解锁等。希望订阅国内外的各大网站的 RSS 信息源又不想跟着网上漫天飞的教程瞎折腾的话,那么你可以使用本仓库的脚本快速完成安装部署。
@@ -71,15 +67,15 @@ mkdir RSSmanX && cd $_ && wget https://cdn.jsdelivr.net/gh/Colin-XKL/RSSmanX/doc
选择对应版本下载到本地后都 compose 文件需要重命名为标准的`docker-compose.yml`才可使用
-# 安装说明
+## 安装说明
-## 需求
+### 需求
- 一台 Linux 系统的服务器
> 本文以腾讯云 Ubuntu 18.04 系统的服务器为例,其他云服务商的没差,系统为 CentOS 的会有点差异
-## 依赖项
+### 依赖项
- docker
- docker-compose
@@ -111,7 +107,7 @@ sudo apt install docker-compose
- https://docs.docker.com/engine/install/
- https://docs.docker.com/compose/install/
-## 如何安装
+### 如何安装
安装好了 `docker` 和 `docker-compose` 后可以执行文章开头的快速开始的指令。或者可以按照下面的步骤手动操作:
@@ -133,7 +129,7 @@ sudo apt install docker-compose
- TTRSS 相关文档 [https://ttrss.henry.wang/](https://ttrss.henry.wang/)
- RSSHub 相关文档 [https://docs.rsshub.app/](https://docs.rsshub.app/)
-## 功能模块介绍
+### 功能模块介绍
**Tiny Tiny RSS**
RSS 订阅管理与在线阅读工具
@@ -165,7 +161,7 @@ RSS 订阅管理与在线阅读工具
**Clash**
智能路由与正向代理工具,用于解锁海外站点及提供海外 RSS 源的加速
-# Acknowledgement
+## Acknowledgement
- [Tiny tiny RSS](https://tt-rss.org/)
- [OpenCC](https://github.com/BYVoid/OpenCC)
@@ -174,11 +170,11 @@ RSS 订阅管理与在线阅读工具
- [RSShub](https://github.com/DIYgod/RSSHub)
- [Awesome TTRSS](https://github.com/HenryQW/Awesome-TTRSS)
-# License
+## License
GPL-3.0
-# Changelogs
+## Changelogs
- 2020-07-07 v1.0 First release
- 2020-07-14 v1.1 Update quick start shell script
diff --git a/content/posts/RSSManX安装部署指南.md b/content/posts/RSSManX安装部署指南.md
new file mode 100644
index 0000000..1699a91
--- /dev/null
+++ b/content/posts/RSSManX安装部署指南.md
@@ -0,0 +1,265 @@
+---
+title: RSSManX安装部署指南
+date: 2022-05-07
+description: RSS Man X是我两年前入坑RSS后,为了方便更多人更方便地使用RSS所发起的一个项目,主要是用docker-compose整合了一些常用的服务如TTRSS、RSSHub、Huginn、OpenCC等并进行了一些优化调整,如自动更新,反反爬虫等。这篇文章会尽可能详尽地讲解安装部署的步骤以及安装过程中可能会遇到的一些问题。
+categories:
+- 技术
+- 指南
+tags:
+- RSS
+- Linux
+- 教程
+- Docker
+
+---
+
+
+
+RSS Man X是我两年前入坑RSS后,为了方便更多人更方便地使用RSS所发起的一个项目,主要是用docker-compose整合了一些常用的服务如TTRSS、RSSHub、Huginn、OpenCC等并进行了一些优化调整,如自动更新,反反爬虫等。这篇文章会尽可能详尽地讲解安装部署的步骤以及安装过程中可能会遇到的一些问题。
+
+RSS Man X会利用到docker和docker-compose,首先需要确保你的服务器正确安装了这些软件
+
+## 1. Docker环境准备
+
+检查服务器中是否已经安装了docker和docker-compose,并检查他们的版本是否太老。比如输入`docker --version`来检查docker的版本
+
+docker的版本建议不要低于19,docker-compose的版本建议不要低于1.20
+
+```shell
+~ » docker --version
+Docker version 20.10.12, build 20.10.12-0ubuntu2~20.04.1
+```
+
+```shell
+~ » docker-compose --version
+docker-compose version 1.25.0, build unknown
+```
+
+如果上面命令执行后提示`command not found`,那么说明并没有安装对应的软件包(或是安装的路径并不在当前用户的PATH变量中,尝试切换到root操作,详细的原因和解决方法见后文)
+
+### 1.1 Ubuntu/Debian安装Docker
+
+ubuntu和debian主要是用apt安装和管理软件包,可以使用以下命令来安装,根据实际情况选择是否要加sudo。下面以Ubuntu为例。Debian下的安装略有不同,可以参见[Docker官方文档](https://docs.docker.com/engine/install/debian/),以及[清华镜像源](https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/)。其中`download.docker.com`连接不同的可以尝试讲域名部分更换为[中科大提供的镜像](https://mirrors.ustc.edu.cn/help/docker-ce.html)地址`mirrors.ustc.edu.cn/docker-ce`
+
+```shell
+# 首先移除老旧的软件包
+sudo apt-get remove docker docker-engine docker.io containerd runc
+
+sudo apt-get update
+# 安装一些必要的依赖
+sudo apt-get install \
+ ca-certificates \
+ curl \
+ gnupg \
+ lsb-release
+```
+
+如果你的服务器在墙外,可以直接使用docker官方的软件源
+
+```shell
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
+
+echo \
+ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
+ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+```
+
+如果你的服务器在墙内,可以使用由中科大提供的镜像
+
+```shell
+curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
+
+echo \
+ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu \
+ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
+```
+
+导入docker软件源后即可开始安装docker,安装完成后可以输入`docker --version`来检查docker的版本
+
+```shell
+sudo apt-get update
+sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.2 CentOS/Fedora安装Docker
+
+CentOS和Fedora使用yum安装和管理软件包,新版本则是使用dnf,不过两者功能一致且高度兼容。下面以CentOS为例,Fedora可参见[官方文档](https://docs.docker.com/engine/install/fedora/)或[清华镜像源](https://mirrors.tuna.tsinghua.edu.cn/help/docker-ce/)
+
+```shell
+# 1. 首先移除老旧的软件包
+
+sudo yum remove docker \
+ docker-client \
+ docker-client-latest \
+ docker-common \
+ docker-latest \
+ docker-latest-logrotate \
+ docker-logrotate \
+ docker-engine
+# 2.
+sudo yum install -y yum-utils
+
+# 3.A 之后使用官方docker软件库
+sudo yum-config-manager \
+ --add-repo \
+ https://download.docker.com/linux/centos/docker-ce.repo
+
+# 3.B 墙内方案
+sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
+sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
+
+
+# 4. 即可开始安装
+sudo yum update
+sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+
+
+### 1.3 安装或更新docker-compose
+
+docker-compose目前有两个主要版本V1和V2,都是可用的。V1使用Python编写,使用时类似`sudo docker-compose up -d`,V2则是Golang编写,与前者高度兼容,但是是作为docker的插件安装的,使用时类似`sudo docker compose up -d`,中间的短杠不需要了。
+
+如果是按照上文的步骤安装的docker,那么默认已经安装了docker compose v2,可以通过`docker compose version`查看版本
+
+```shell
+~ » docker compose version
+Docker Compose version v2.3.3
+```
+
+如果需要是安装的比较老的v1版本的docker-compose,想要单纯更新docker-compose而又不想动其他东西的话,可以更新安装v1版本的docker-compose。
+
+首先删除老旧版本(如果有的话)
+
+```shell
+rm $DOCKER_CONFIG/cli-plugins/docker-compose
+sudo rm /usr/local/lib/docker/cli-plugins/docker-compose
+pip uninstall docker-compose
+```
+
+然后使用pip来安装
+
+```shell
+pip3 install docker-compose
+```
+
+墙内也可以临时使用镜像源下载
+
+```shell
+pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple
+```
+
+如果提示pip命令不存在需要先安装一下
+```shell
+# Ubuntu/Debian
+sudo apt install python3-pip
+
+# CentOS/Fedora
+sudo yum install python3-pip
+```
+
+如果pip报错试着升级一下pip的版本
+
+```shell
+python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip
+```
+
+
+
+### 1.4 为Docker配置镜像源
+
+如果Docker下载镜像非常慢,你可能需要单独配置一下Docker的镜像源。==**注意:Docker安装软件源的镜像和Docker镜像或者说映像的国内源并不是同一个,英文表述可能更准确一些:**==
+
+* 上文安装docker时配置的是docker的repo,repo里含有docker的软件包,[国内的镜像](https://mirrors.ustc.edu.cn/help/docker-ce.html)为Docker CE安装软件包的镜像
+* 现在我们要配置的是Docker Hub的Mirror,Docker里拉取Image默认会访问[Docker Hub](https://hub.docker.com),国内有多个Docker Hub镜像或是Docker镜像加速器,如[中科大的源](https://mirrors.ustc.edu.cn/help/dockerhub.html)
+
+在`/etc/docker/daemon.json`文件中写入以下内容,如不存在可先行创建,注意json中列表的最后一项末尾是没有逗号的
+
+```json
+{
+ "registry-mirrors": [
+ "https://mirror.ccs.tencentyun.com",
+ "https://docker.mirrors.ustc.edu.cn"
+ ]
+}
+```
+
+配置完成后`sudo systemctl restart docker`重启docker服务,然后输入`sudo docker info`,在输出结果的末尾可以看到`Registry Mirrors`里会出现我们刚刚配置的Docker Hub镜像
+
+群辉等NAS的系统并不是标准版Linux,安装的也是魔改版docker,上面的配置文件地址并不适用,建议自行搜索对应的文档或教程。
+
+## 2. 安装RSS Man X
+
+[RSS MAN X项目](https://github.com/Colin-XKL/RSSmanX)旨在为 RSS 的同好提供一个方便地搭建自己的 RSS 服务的捷径,毕竟不是所有 RSS 爱好者都懂代码 😂。RSS Man X能够有 RSS 订阅管理、RSS 在线阅读界面,进阶功能包括服务健康自检、海外站点 RSS 解锁等,提供不同的版本供选择,三个版本的 `docker-compose` 文件对应不同的需求,包含的组件和服务有差异。
+
+| 组件 / 服务 / 功能名称 | 标准版 | Lite 版 | Ultimate 版 ✨ |
+| ---------------------- | ------ | ------- | ------------- |
+| TTRSS | ✅ | ✅ | ✅ |
+| RSSHub | ✅ | ✅ | ✅ |
+| Huginn | | | ✅ |
+| Mercury | ✅ | | ✅ |
+| OpenCC | | | ✅ |
+| Redis | ✅ | | ✅ |
+| Browserless | | | ✅ |
+| 数据持久化保存 | ✅ | ✅ | ✅ |
+| 容器自动更新 | ✅ | | ✅ |
+| 容器健康检查 | ✅ | | ✅ |
+| 海外站点加速 | | | ✅ |
+| 智能路由 | | | ✅ |
+| 反反爬虫 | | | ✅ |
+
+### 2.1 安装流程
+
+安装好了 `docker` 和 `docker-compose` 后,可以使用`git clone https://github.com/Colin-XKL/RSSmanX --depth=1`快速克隆本仓库,也可以通过[这个镜像地址](https://archive.fastgit.org/Colin-XKL/RSSmanX/archive/refs/heads/master.zip)下载仓库zip文件,[Gitee上也有镜像](https://gitee.com/colin-xkl/RSSmanX)不过不经常更新。
+
+1. cd 进入文件夹,修改`.env`中的值,如密码和TTRSS入口URL等
+2. 运行 `sudo docker-compose up -d`
+3. 等待程序跑完
+4. 安装完成 ✅
+
+### 2.2 相关事宜
+
+1. 访问你设置的 `SELF_URL` 即可看到 Tiny Tiny RSS 的登陆页面,使用默认账户 `admin`,密码 `password` 登陆即可开始使用
+
+2. 如开启海外站点解锁支持,第一次冷启动需要等待 3-5 分钟才能完全启动所有组件。
+
+3. 数据保存位置`/data/docker/`
+
+4. 在 TTRSS 中将原来订阅的 `https://rsshub.app/*` 更改为 `http://rsshub/*` 即可使用 RSS Man X内的自建 RSSHub 实例,并激活反反爬虫和海外源加速等功能
+
+5. 如无法访问rsshub的官方文档站点,可以使用我维护的反代站点[https://rsshub-doc.azure.colinx.one/](https://rsshub-doc.azure.colinx.one/)
+
+6. 关于 ARM 平台的支持可查阅[置顶的 issue](https://github.com/Colin-XKL/RSSmanX/issues/5)
+
+7. 默认情况下只有TTRSS和Huginn可以从外部访问,其他组件互相可以访问但不能直接从内部访问以提高安全性
+
+8. RSS Man X的除 lite 以外的版本默认包含了自托管的 mercury 实例,你只需要在插件配置页面设置 mercury 实例地址为 `service.mercury:3000` 即可,同理,OpenCC实例地址为`service.opencc:3000`
+
+9. 如果部分RSS源不能订阅,检查是否使用了非常规端口。在`.env`文件中设置`RSS_ALLOEW_PORTS`
+
+10. 若部署后某个应用一直无法通过浏览器访问,请检查是否绑定到了`6000`/`6666`等特殊端口,浏览器会拦截对这些端口的访问参见[这里](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)
+
+11. `ls`没有显示`.env`文件是因为以点开头的文件在Linux中都是默认隐藏的,可以使用`ls -a`查看到
+
+12. vi/vim编辑文本太麻烦可以尝试使用nano
+
+
+
+
+
+**获取帮助**
+
+* **For Tiny tiny RSS problems:**
+ [https://tt-rss.org/wiki.php](https://tt-rss.org/wiki.php)
+ [http://ttrss.henry.wang/](http://ttrss.henry.wang/)
+* **For RSShub problems:**
+ [https://docs.rsshub.app/faq.html](https://docs.rsshub.app/faq.html)
+* **For Huginn problems:**
+ [https://github.com/huginn/huginn#readme](https://github.com/huginn/huginn#readme)
+
+### 2.3 链接
+
+* [我的 RSS 方案与心得](https://blog.colinx.one/posts/%E6%88%91%E7%9A%84rss%E6%96%B9%E6%A1%88%E4%B8%8E%E5%BF%83%E5%BE%97/)
+* [RSS Man X GitHub repo](https://github.com/Colin-XKL/RSSmanX)
+* [Huginn 指南:为任意网站制作 RSS](https://blog.colinx.one/posts/huginn%E6%8C%87%E5%8D%97%E4%B8%BA%E4%BB%BB%E6%84%8F%E7%BD%91%E7%AB%99%E5%88%B6%E4%BD%9Crss/)
+* [docker compose 的错误使用姿势](https://blog.colinx.one/posts/docker-compose%E7%9A%84%E9%94%99%E8%AF%AF%E4%BD%BF%E7%94%A8%E5%A7%BF%E5%8A%BF/)
\ No newline at end of file
diff --git a/content/posts/Win 10配置C语言环境的正确姿势.md b/content/posts/Win 10配置C语言环境的正确姿势.md
index 31e6943..6117e4c 100644
--- a/content/posts/Win 10配置C语言环境的正确姿势.md
+++ b/content/posts/Win 10配置C语言环境的正确姿势.md
@@ -4,7 +4,7 @@ date: 2020-12-27
lastmod: 2020-12-27
description: VC6.0太古老,Dev C++没补全不友好,MinGW安装太烦恼?你用着最新的电脑,最新的系统,却在用着上个世纪的软件开始你人生第一门编程课?你需要这篇指南:在现代化的硬件和平台上使用现代化工具学习C语言
categories:
-- 教程
+- 技术
- 指南
tags:
- C
@@ -65,7 +65,7 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
-
+
@@ -73,7 +73,7 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
-
+
@@ -83,13 +83,13 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
网络条件不好的情况下,半分钟以内就会报错说网络连接失败。不过不用担心,接下来可以自己填写国内镜像地址。
-
+
在User URL的输入框输入`https://mirrors.tuna.tsinghua.edu.cn/cygwin/`并点击Add添加。之后点击下一步继续。
-
+
@@ -97,13 +97,13 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
之后会进入一个选择界面。这里选择要安装的组件。我们只需要C语言的编译器,这里在搜索框内输入`gcc`,然后在下方找到`gcc-core` 和 `gcc-g++`,点击右侧的三角形打开下拉菜单,选择9开头的版本。如下图所示。
-
+
选择完成后,一路点击下一步安装。如果出现如下的警告信息,直接用默认的设置,点下一步继续就可以了。
-
+
@@ -115,51 +115,51 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
在开始菜单中找到`Windows系统` - 控制面板。如果这里没有的话,按`Windows徽标键`+`S`可以呼出搜索面板,可以在此搜索控制面板菜单项。
-
+
在控制面板主页找到系统与安全。
-
+
或者如果你的控制面板打开不是上面的布局而是下面这种布局的话,找到系统菜单。
-
+
进入如下的页面,点击高级系统设置。
-
+
切换到高级选项卡,点击下方的环境变量菜单
-
+
在用户变量中,点击`Path`,点击下方编辑按钮进行编辑
-
+
输入Cygwin安装路径下的bin目录。如果你之前没有自定义安装路径,直接设置如图即可。否则设置为你自定义的路径。
**注意:这一步只要添加这一个就好**,不要看我截图里面的很干净,就把其他的都删了
-
+
一路点击确定。修改完之后重启下电脑确保改动生效。
在PowerShell中或者命令提示符中输入gcc并回车。如果显示no input files则表示安装成功。
-
+
### 配置编辑器
安装完了编译器,可以先来Hello world了
-
+
按住Shift键,右键点击文件夹空白处,会出现在此处打开Powershell窗口的选项。
-
+
@@ -167,7 +167,7 @@ Cygwin的安装程序可以[从其官方站点下载](https://cygwin.com/install
输入`./hello.exe`即可执行该exe文件。
-
+
@@ -201,41 +201,41 @@ https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user
-
+
-
+
-
+
-
+
-
+
-
+
-
+
在输入栏中,在当前选项卡为**用户**的情况下,输入`run`并按回车进行搜索。修改`Run in Terminal`和 `Save File Before Run`的设置项。
-
+
@@ -245,20 +245,20 @@ https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user
点击左侧第一个按钮,来到文件管理面板。点击打开文件夹按钮,打开一个空白的文件夹(任意文件夹都可以,只是保存你代码的地方,一般一个干净整洁的新文件夹为宜)
-
+
打开文件夹后,在空白处单击右键,新建一个文件,文件名输入为`hello.c`
-
+
点击右上角的三角形按钮即可自动编译运行你的C语言代码。在窗口下方的终端即可看到输出的`Hello,C!`字样。
-
+
diff --git a/content/posts/docker-compose的错误使用姿势.md b/content/posts/docker-compose的错误使用姿势.md
new file mode 100644
index 0000000..898bde0
--- /dev/null
+++ b/content/posts/docker-compose的错误使用姿势.md
@@ -0,0 +1,162 @@
+---
+title: docker compose的错误使用姿势
+date: 2022-05-11
+description: 这篇文章记录几个docker compose使用过程中几个难以察觉的错误使用姿势。1. 变量值使用`@`符号开头 2. 使用6000或6666端口
+categories:
+- 技术
+- 指南
+tags:
+- YAML
+- Linux
+- Docker
+- docker-compose
+---
+
+
+
+
+
+这篇文章记录几个docker compose使用过程中几个难以察觉的错误使用姿势
+
+## 1. 变量值使用`@`符号开头
+
+我在RSS MAN X的docker-compose配置文件中,huignn的环境变量出来时是这样写的
+
+```yaml
+environment:
+ - DATABASE_ADAPTER=postgresql
+ - DATABASE_HOST=database.huginn
+ - DATABASE_USERNAME=postgres
+ - DATABASE_PASSWORD=@pass_for_DB
+ - DATABASE_PORT=5432
+```
+
+
+
+自己使用的时候没发现什么问题,别人从零创建容器的时候报错了。刚开始排查了很久,后面发现我默认密码这样写其实是有问题的。
+
+上面的使用列表来描述环境变量在docker-compose解析的时候没有任何报错信息。但是使用下面这种key-value的map的形式时,`docker-compose up`命令报错了,说YAML解析时出现问题
+
+```yaml
+environment:
+ DATABASE_ADAPTER: postgresql
+ DATABASE_HOST: database.huginn
+ DATABASE_USERNAME: postgres
+ DATABASE_PASSWORD: @pass_for_DB
+ DATABASE_PORT: 5432
+```
+
+
+
+```
+yaml: line 17: found character that cannot start any token
+```
+
+删除前导`@`符号则一切正常了。
+
+```yaml
+DATABASE_PASSWORD: pass_for_DB
+```
+
+后续测试了几次到底是什么原因导致的
+
+```yaml
+# error
+DATABASE_PASSWORD: @pass_for_DB
+
+# correct
+DATABASE_PASSWORD: pass_for_DB
+
+# correct
+DATABASE_PASSWORD: ${DB_Password:-'pass_for_DB'}
+## in .env
+DB_Password=www_123
+
+# correct
+DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
+## in .env
+DB_Password=www_123
+
+# error
+DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
+## no .env
+
+# error
+DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
+## in .env
+DB_Password=@www_123
+
+# correct
+DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
+## in .env
+DB_Password=A@www_123
+```
+
+最终发现无论是否使用docker-compose变量替换,只要最终设定值的时候,包含前导@符号,最终一定会失败。Huginn的这边的报错为解析容器内的一个YAML文件时失败
+
+```
+huginn1 | foreman stderr |
+huginn1 | Caused by:
+huginn1 | foreman stderr | Psych::SyntaxError: (): found character that cannot start any token while scanning for the next token at line 8 column 13
+huginn1 | foreman stderr | /app/vendor/bundle/ruby/2.6.0/gems/railties-6.0.4.4/lib/rails/application/configuration.rb:232:in `database_configuration'
+```
+
+后面我又进入容器查看了下容器内部读取到的环境变量到底是不是预期的值,发现了问题所在
+
+能正常使用的情况
+
+```shell
+~ » sudo docker exec -it huginn1 /bin/bash
+default@3b652a8413fb:~$ echo $DATABASE_HOST
+database.huginn
+default@3b652a8413fb:~$ echo $DATABASE_PASSWORD
+A@www_123
+```
+
+出错的情况
+
+```shell
+~ » sudo docker exec -it huginn1 /bin/bash
+default@42e19e692b24:~$ echo $DATABASE_HOST
+database.huginn
+default@42e19e692b24:~$ echo $DATABASE_PASSWORD
+'@pass_for_DB'
+```
+
+可以看到,如果以`@`符号开头,最终的环境变量会加上引号,这对于某些应用来说会产生预期之外的结果,如此处测试的Huginn。
+
+
+
+
+
+## 2. 使用6000或6666端口
+
+这也是一定挺特殊的场景,虽然与docker compose关系不大,但是难免会遇到。在映射端口的时候有一个很坑的地方,如果你要部署一个web服务,然后映射的时候填写的是`6000`端口或者是`6666`端口,你会发现无论怎么重启容器、更改容器设置、更换Edge/Chrome,浏览器就是访问不了页面。
+
+实在折腾地快疯了,点开Chrome的错误详情,才发现这么一句
+
+ ***ERR_UNSAFE_PORT***
+
+一查才发现,Chrome等浏览器会限制部分特殊端口的网页访问,这些端口一般都已经有特殊的作用。
+
+https://www.jianshu.com/p/40f79f584eae
+
+这里列出1000以上的部分会有相关问题的端口,别的不说,感觉`6000`和`6666`还是很容易一不小心就会设置的端口。。。。
+
+```c
+ 2049, // nfs
+ 3659, // apple-sasl / PasswordServer
+ 4045, // lockd
+ 6000, // X11
+ 6665, // Alternate IRC
+ 6666, // Alternate IRC
+ 6667, // Standard IRC
+ 6668, // Alternate IRC
+ 6669, // Alternate IRC
+```
+
+Chrome、FireFox等都会有类似的行为,换多少浏览器、换多少版本可能也都不行。。。
+
+根据网友描述,部分特殊情况下,其他可能会被拦截的端口也包括`8080`,`8443`,`10080`。
+
+总之,日常映射端口还是选取`10000`以上的高位端口吧,避免不必要的麻烦:)
\ No newline at end of file
diff --git a/content/posts/一次成功的网络优化 & 吐槽国内糟糕的网络环境.md b/content/posts/一次成功的网络优化 & 吐槽国内糟糕的网络环境.md
index 5ad5fa2..b94cf27 100644
--- a/content/posts/一次成功的网络优化 & 吐槽国内糟糕的网络环境.md
+++ b/content/posts/一次成功的网络优化 & 吐槽国内糟糕的网络环境.md
@@ -4,7 +4,7 @@ date: 2019-10-10
lastmod: 2020-04-29
description: 在内网的树莓派上部署了 AdGuardHome,做 DNS 服务器的同时,也可以为内网所有设备过滤广告。本来嘛拦截了广告理应网络加载会更快,然而实际体验却很糟糕。网页加载要比之前慢得多。AdGuardHome 的面板显示的平均反应时间一度达到了 1000ms。1s 的延时还是会非常影响网络体验的。用 dig 命令看了下 DNS 查询的情况。不看不知道一看吓一跳,随便查询一个域名竟然废了四秒多!这怎么能忍受!
categories:
-- 踩坑记
+- 技术
tags:
- 服务器
- 树莓派
@@ -13,7 +13,8 @@ tags:
在内网的树莓派上部署了 AdGuardHome,做 DNS 服务器的同时,也可以为内网所有设备过滤广告。本来嘛拦截了广告理应网络加载会更快,然而实际体验却很糟糕。网页加载要比之前慢得多。AdGuardHome 的面板显示的平均反应时间一度达到了 1000ms。1s 的延时还是会非常影响网络体验的。用 dig 命令看了下 DNS 查询的情况。不看不知道一看吓一跳,随便查询一个域名竟然废了四秒多!这怎么能忍受!
-
+\[图片已丢失\]
+
看网上其他人的评价,并没有我这种龟速的情况。况且我的上游 DNS 已经更换为了国内几个大厂的 DNS 比如阿里的腾讯的,测试查询一般反应时间也才 50ms。本地这个结果肯定是不能接受的。最开始还想过要根据常用域名手动制作 hosts 直接重定向。但是 dnspython 这个库不好直接指定 dns 查询,adguardhome 的 query 日志又经过特殊加密,这条路困难重重。决定将其作为备用方案。接下来进入漫长的排雷环节。
@@ -23,10 +24,14 @@ tags:
后来发现了这货:
-
+\[图片已丢失\]
+
+
原来,他会把每次查询的域名先交给他服务器做安全性检查,这在国内的互联网环境中完全是鸡肋,而且因为每次都要连接境外服务器,其延迟可想而知。果然禁用了这一项,速度嗖嗖的就起来了:
-
+
+\[图片已丢失\]
+
即便是冷门的实验室官网的域名,也在 100ms 内解决了,对于常见的热门网站由于多设备频繁访问,会直接查询本地缓存。虽然基本只有可怜的差不多 60s 的缓存时间,但是一旦命中,就可以在 < 10ms 的时间响应。如果是过滤器中的域名,更是可以达到 < 5ms。终于,这个 AdGuard Home DNS 可以正式投入使用了。
\ No newline at end of file
diff --git a/content/posts/云服务器入门指南.md b/content/posts/云服务器入门指南.md
index 5951be4..2f60aef 100644
--- a/content/posts/云服务器入门指南.md
+++ b/content/posts/云服务器入门指南.md
@@ -4,7 +4,7 @@ date: 2020-03-15
lastmod: 2020-04-29
description: 各大厂商持续发力云计算,上云的门槛也越来越低。获取云服务器的门槛越来越低,但是真正使用好云服务器的难度一直都很高。本文旨在为新上云的小白提供方向性的指引并引导入坑
categories:
-- 教程
+- 技术
- 指南
tags:
- 服务器
diff --git a/content/posts/从一次异常断网谈防火墙配置.md b/content/posts/从一次异常断网谈防火墙配置.md
index 0766dd0..c9d441a 100644
--- a/content/posts/从一次异常断网谈防火墙配置.md
+++ b/content/posts/从一次异常断网谈防火墙配置.md
@@ -4,7 +4,7 @@ date: 2020-02-08
lastmod: 2020-04-29
description: 经过两三天的折腾,从 Linux 结构及指令,到 LNMP 框架搭建,再到数据库的配置,最后端口转发 + 内网穿透,博客终于成功上线!在此将部署过程及踩过的坑记录下来,一方面是纪念,另一方面希望能够后来人提供一点帮助。
categories:
-- 踩坑记
+- 技术
tags:
- 防火墙
- 服务器
@@ -28,7 +28,7 @@ tags:
由于要分配的公网 IPv6 地址是要由路由器从公网获取一个前缀然后再为局域网的每个支持 IPv6 的设备分配地址,这一项任务不能由内网的树莓派代劳,所以当时就没有改动,没想到现在竟然成了救命稻草。
通过 IPv6 的方式,成功连接上了树莓派。查看了 AdGuardHome 的 DNS 服务以及 DHCP 服务,并没有发现任何异常。
例行 SSH 连上查看日志。`sudo systemctl status AdGuardHome.service`,果然,发现了端倪。
-
+
原来!DHCP 服务!是要单独监听 67 端口的!
而一个小时之前,为了防止暴露在公网上的树莓派遭到攻击,我特地启用了防火墙,并设置规则为,除了放行的 DNS 53 等端口,其他默认屏蔽。想来应该是误伤了 DHCP 的 67 端口。而之前 DHCP 设置每个 IP 地址的租约为一个小时,即,每间隔一个小时才会重新进行一次 DHCP 请求。于是`sudo ufw allow 67/tcp`端口放行 DHCP 服务信息。win10 断网重连以令其重新获取 IP 地址。
没想到还是不成功。AdGuardHome 的 DHCP 租约面板,依然显示没有任何设备连接。依据以往的经验,乖乖去查了 DHCP 所使用的端口信息,发现 DHCP 需要`67/udp`和`68/udp`两个端口,且还是使用 udp 连接。
@@ -43,7 +43,7 @@ tags:
-----
防火墙抵挡了来自外部的威胁,也会对现有的服务造成影响。除了网页访问的 80 和 443 端口,其他有固定端口的特定服务要手动在防火墙中添加规则。对于像 BT 下载这种没有固定端口的,需要根据实际设定来更新防火墙规则。
-
+
图中为 Aria2 的默认监听端口,为了保证正常的 BT 下载,需要保证这个范围的端口也添加进防火墙允许通过的规则。
最简单有效的办法是,将所有出站的请求默认允许,对于外部传入的请求,除了必要的几个服务,其他一概默认禁止。
diff --git a/content/posts/前端静态资源加载的一些优化.md b/content/posts/前端静态资源加载的一些优化.md
new file mode 100644
index 0000000..c0a54f5
--- /dev/null
+++ b/content/posts/前端静态资源加载的一些优化.md
@@ -0,0 +1,154 @@
+---
+title: 前端静态资源加载的一些优化
+date: 2022-05-06
+description: 最近在折腾优化博客,由于全站都是部署在Netlify、Vercel的CDN上,都是海外节点,国内访问延迟高,在想办法优化下访问速度和体验。这篇文章来探讨下前端CSS和JS资源的加载。优化目标主要就两个:1. 尽可能快,但是不希望我引入的辅助性第三方库影响到页面体验,不要阻塞主要内容渲染. 2. 为了快第三方静态资源肯定是上CDN,但是要有容灾,CDN挂了要能fallback到其他url
+categories:
+- 技术
+tags:
+- 技术
+- 前端
+- CDN
+- JavaScript
+---
+
+
+
+最近在折腾优化博客,由于全站都是部署在Netlify、Vercel的CDN上,都是海外节点,国内访问延迟高,在想办法优化下访问速度和体验。线路部分的优化可以看另一篇文章[国外静态网站托管服务商国内速度对比及线路优化](https://blog.colinx.one/posts/%E5%9B%BD%E5%A4%96%E9%9D%99%E6%80%81%E7%BD%91%E7%AB%99%E6%89%98%E7%AE%A1%E5%9C%A8%E5%9B%BD%E5%86%85%E9%80%9F%E5%BA%A6%E5%AF%B9%E6%AF%94%E5%8F%8A%E7%BA%BF%E8%B7%AF%E4%BC%98%E5%8C%96/)。这篇文章来探讨下前端CSS和JS资源的加载。
+
+优化目标主要就两个:
+
+* 尽可能快,但是不希望我引入的辅助性第三方库影响到页面体验,不要阻塞主要内容渲染
+* 为了快第三方静态资源肯定是上CDN,但是要有容灾,CDN挂了要能fallback到其他url
+
+
+
+## 静态资源异步加载
+
+`prefetch`、`preload`这些预加载技术暂且不谈,博客站点没那么多资源。这里主要是用`async`和`defer`来控制脚本异步加载,以避免阻塞DOM解析和页面渲染。
+
+使用`async`异步加载,对于[pangu](https://github.com/vinta/pangu.js/)这种会影响到内容呈现的使用`async`,对于统计类第三方库使用`defer`延迟加载,到DOM加载完再执行
+
+有些第三方库需要手动init,这样就不能使用`defer`、`async`关键字加载资源了,**`defer`和`async`关键字只适用于远程资源**,本以为把远程资源的`
+
+```
+
+
+
+after
+
+```html
+
+
+```
+
+
+
+除了`onload`还有`onerror`,还可以利用`onerror`事件在资源加载失败时fallback到其他CDN,详见下文
+
+这里跑了个测试看下优化前后的差距
+
+**优化前**
+
+
+
+
+
+First Contentful Pain Time在1.5s,整个页面到1.5s才能可见,DOM加载总时间达到了2.5s
+
+本来我都已经把首页不需要加载的三方库都拿走了,但是还剩下一个,这个用于前端性能监控的js阻塞了渲染,挂的是腾讯云的CDN,国内快到飞起,国外就卡到不行(作为对比上图里从jsdelivr加载的js也是快到飞起,墙内就慢得一批)
+
+**优化后**
+
+
+
+优化后页面没有再阻塞,0.8s页面就可用了,总DOM加载时间只有1.5s,相较之前简直直接起飞。
+
+
+
+
+国内某检测平台的结果也显示优化效果明显
+
+## 静态资源Fallback加载
+
+国内好用的静态资源CDN还真没有,新浪那种只提供那么几个热门的库完全不符合需求,BootCDN炸了不是一次两次,字节CDN的资源URL有够ugly,URL里面还带节点信息多半后面会出问题。360奇舞CDN之前也换过域名、备案出问题,感觉每一个能省心用。七牛的目前看上去还行,也不知道后面会不会出什么幺蛾子。。。为了稳妥起见+照顾全球的访客,还是优先使用的cloudflare和jsdelivr的CDN
+
+网站主要三方库都是通过jsdelivr和cloudflare引入的,但是毕竟是海外的节点不知道哪一天就被墙了,所以还要为墙内的访客准备一个fallback方案。这里利用到`script`标签的`onerror`事件
+
+
+
+现代浏览器都支持`script`和`link`标签上的`onload`和`onerror`事件,详细支持情况可以查看这里
+
+[https://pie.gd/test/script-link-events/](https://pie.gd/test/script-link-events/)
+
+
+
+关于`onerror`,中文互联网上有好几篇文章说他会捕获`script`标签里的代码的执行错误。。。简直离谱。稍微查下MDN之类的文档就可以发现这玩意本来就是只捕获资源加载错误的
+
+> The onerror event is triggered if an error occurs while loading an external file (e.g. a document or an image).
+>
+> https://www.w3schools.com/jsref/event_onerror.asp
+
+
+
+利用好这个特性,就可以实现在资源加载失败时fallback从另一个url加载资源。
+
+```html
+
+
+
+
+
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/layouts/partials/extended_footer.html b/layouts/partials/extended_footer.html
new file mode 100644
index 0000000..7883b45
--- /dev/null
+++ b/layouts/partials/extended_footer.html
@@ -0,0 +1,18 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/layouts/partials/extended_head.html b/layouts/partials/extended_head.html
index b608c20..e70d253 100644
--- a/layouts/partials/extended_head.html
+++ b/layouts/partials/extended_head.html
@@ -1,7 +1,47 @@
-
-
+
+
+
+
+
+
+
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html
index adfeec0..dda4819 100644
--- a/layouts/partials/footer.html
+++ b/layouts/partials/footer.html
@@ -1,23 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
{{- partial "extended_footer.html" . }}
\ No newline at end of file
diff --git a/layouts/partials/head.html b/layouts/partials/head.html
new file mode 100644
index 0000000..01f6b9b
--- /dev/null
+++ b/layouts/partials/head.html
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+{{- partial "prepended_head.html" . }}
+
+
+
+
+
+
+
+
+
+
+
+{{ template "_internal/opengraph.html" . }}
+
+
+{{ range .AlternativeOutputFormats -}}
+ {{ printf `` .Rel .MediaType.Type .RelPermalink $.Site.Title | safeHTML }}
+{{ end -}}
+
+
+{{- partial "extended_head.html" . }}
diff --git a/static/admin/config.yml b/static/config.yml
similarity index 100%
rename from static/admin/config.yml
rename to static/config.yml
diff --git a/static/style.css b/static/style.css
new file mode 100644
index 0000000..9b76c77
--- /dev/null
+++ b/static/style.css
@@ -0,0 +1,118 @@
+/* gittalk comment style */
+#gitalk-container {
+ margin: 20px auto;
+ max-width: 800px;
+ padding: 20px;
+ width: 100%;
+ text-align: left;
+}
+
+/* toc style */
+@media (min-width: 1500px) {
+ .js-toc {
+ display: block !important;
+ }
+}
+
+.js-toc {
+ display: none;
+ /* IE and Edge */
+ -ms-overflow-style: none;
+ /* Firefox */
+ scrollbar-width: none;
+}
+
+.js-toc::-webkit-scrollbar {
+ /* Chrome, Safari and Opera */
+ display: none;
+}
+
+.js-toc {
+ position: fixed;
+ width: 20%;
+ max-width: 400px;
+ right: 3rem;
+ top: 10em;
+ text-align: left;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ padding: 1rem 0rem;
+}
+
+ol.toc-list > li > a:hover {
+ text-underline-position: under;
+ font-weight: bolder;
+}
+
+.toc-list li {
+ list-style: none;
+}
+
+.toc-list a {
+ text-decoration: none;
+ text-overflow: ellipsis;
+ display: inline-block;
+ white-space: nowrap;
+ font-size: 1rem;
+}
+
+.is-active-link::before {
+ background-color: #d71a1b !important;
+}
+
+.logo__cursor {
+ background: #d71a1b;
+}
+
+/* 超链接样式 */
+
+.post-tags a,
+.post-content a {
+ text-decoration: none;
+ border-bottom: 1px dashed #d71a1b;
+ -webkit-transition: all 0.2s;
+ transition: all 0.2s;
+}
+
+.post-tags a:hover,
+.post-content a:hover,
+nav a:hover {
+ text-decoration: none;
+ border-bottom: 2px solid #d71a1b;
+ -webkit-transition: all 0.1s ease;
+ transition: all 0.1s ease;
+}
+
+/* custom ::selection */
+::selection {
+ background: #b5b5b5;
+ color: #fff;
+}
+
+::-moz-selection {
+ background: #b5b5b5;
+ color: #fff;
+}
+
+::-webkit-selection {
+ background: #b5b5b5;
+ color: #fff;
+}
+
+/* abandoned link style */
+
+/* .post-content a {
+ transition: background-size 0.1s ease;
+ background: linear-gradient(to bottom, transparent 62%, #fff56644 0) center center/0% 75% no-repeat;
+ color: #52c41a;
+ cursor: pointer;
+}
+
+.post-content a:hover {
+ background-size: 100% 100%;
+ color: #389e0d;
+}
+
+.post-content a:active {
+ background-size: 80% 100%;
+} */
diff --git a/themes/hello-friend b/themes/hello-friend
index cf5e597..3ffa812 160000
--- a/themes/hello-friend
+++ b/themes/hello-friend
@@ -1 +1 @@
-Subproject commit cf5e59749143e6bd32444c5d35f4992399a1e7da
+Subproject commit 3ffa8121a004a29d6fd5f1133257ab2ebfea22c4