diff --git a/.github/workflows/blog-deploy.yml b/.github/workflows/blog-deploy.yml index 679e02d..a45a44d 100644 --- a/.github/workflows/blog-deploy.yml +++ b/.github/workflows/blog-deploy.yml @@ -1,15 +1,15 @@ # This is a basic workflow to help you get started with Actions -name: deploy-blog +name: deploy-blogs # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch on: push: branches: [ master ] -# paths: -# - packages/blog/**.* -# - .github/workflows/blog-deploy.yml +# paths: +# - packages/blogs/**.* +# - .github/workflows/blogs-deploy.yml # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -27,13 +27,13 @@ jobs: - name: Install NPM packages run: yarn - name: Build artifact - run: yarn workspace blog build + run: yarn workspace blogs build - name: Vercel Action uses: amondnet/vercel-action@v19 with: vercel-token: ${{ secrets.ZEIT_TOKEN }} # Required vercel-org-id: ${{ secrets.ZEIT_ORG_ID}} #Required - vercel-project-id: ${{ secrets.ZEIT_PROJECT_ID}} #Required + vercel-project-id: ${{ secrets.ZEIT_PROJECT_ID}} #Required working-directory: ./ vercel-args: '--prod' diff --git a/.idea/playground.iml b/.idea/playground.iml index f85446a..30ff418 100644 --- a/.idea/playground.iml +++ b/.idea/playground.iml @@ -5,7 +5,6 @@ - diff --git a/package.json b/package.json index 6bb0575..25fc4fc 100644 --- a/package.json +++ b/package.json @@ -60,10 +60,7 @@ "source-map-loader": "^0.2.3", "style-loader": "^1.1.3", "ts-node": "^7.0.1", - "typescript": "^3.7.5", - "webpack": "^4.44.1", - "webpack-cli": "^3.1.0", - "webpack-dev-server": "^3.7.2" + "typescript": "^4.6.2" }, "resolutions": { "dot-prop": "5.2.0" diff --git a/packages/blog/.eslintignore b/packages/blog/.eslintignore deleted file mode 100644 index 28802e0..0000000 --- a/packages/blog/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -public -static -.cache -content \ No newline at end of file diff --git a/packages/blog/.eslintrc.js b/packages/blog/.eslintrc.js deleted file mode 100644 index 9b05243..0000000 --- a/packages/blog/.eslintrc.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - rules: { - '@typescript-eslint/camelcase': 0, - '@typescript-eslint/ban-ts-ignore': 0, - }, -}; diff --git a/packages/blog/.gitignore b/packages/blog/.gitignore deleted file mode 100644 index d60ee68..0000000 --- a/packages/blog/.gitignore +++ /dev/null @@ -1,71 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# dotenv environment variable files -.env* - -# gatsby files -.cache/ -public - -# Mac files -.DS_Store - -# Yarn -yarn-error.log -.pnp/ -.pnp.js -# Yarn Integrity file -.yarn-integrity - -.now \ No newline at end of file diff --git a/packages/blog/README.md b/packages/blog/README.md deleted file mode 100644 index 9734592..0000000 --- a/packages/blog/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Introduction -This is a personal blog based on Gatsby. -It gets the artical data from both Wordpress and Markdown. - -Tech stack: TypeScript, React, Sass, Eslint, Prettier - - -## Basics -Start the dev server: -> yarn start - -Build artifact: -> yarn build - -## Troubleshooting -* When you encounter the situation that the website's behavior does not work with the code changes, you may find it useful by running `yarn clean` -* If you want to test the artifact created from `yarn build`, you can simply run `yarn serve` to start a express http server for the built artifact. diff --git a/packages/blog/build/createPages.ts b/packages/blog/build/createPages.ts deleted file mode 100644 index 353d9c3..0000000 --- a/packages/blog/build/createPages.ts +++ /dev/null @@ -1,220 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -const path = require(`path`); -import { GatsbyNode } from 'gatsby'; - -export const createPages: GatsbyNode['createPages'] = async ({ - graphql, - actions, -}) => { - const { createPage } = actions; - - const [markdownPosts, wordPressPages] = await Promise.all([ - getPostsFromMarkdown(graphql), - getPostsFromWordPress(graphql), - ]); - - const posts = [...markdownPosts, ...wordPressPages].sort( - (post1, post2) => post2.date.getTime() - post1.date.getTime() - ); - - createBlogPages(posts); - await createBlogIndexPages(posts); - - function createBlogPages(posts: Post[]) { - const blogPost = path.resolve(`./src/templates/BlogPost.tsx`); - posts.forEach((post, index) => { - const previous = index === posts.length - 1 ? null : posts[index + 1]; - const next = index === 0 ? null : posts[index - 1]; - - createPage({ - path: decodeURI(post.slug), - component: blogPost, - context: { - slug: post.slug, - previous, - next, - }, - }); - }); - } - - async function createBlogIndexPages(posts: Post[]) { - const template = path.resolve(`./src/templates/BlogList.tsx`); - const postsPerPage = await getPostsPerPage(); - const totalPages = Math.ceil(posts.length / postsPerPage); - let pageIndex = 0; - while (true) { - const postsForOnePage = posts.slice( - pageIndex * postsPerPage, - (pageIndex + 1) * postsPerPage - ); - - if (!postsForOnePage.length) { - break; - } - - const mdStartIndex = postsForOnePage.find(post => post.source === 'md') - ?.index; - const mdLastIndex = postsForOnePage - .slice() - .reverse() - .find(post => post.source === 'md')?.index; - const mdCount = - mdStartIndex === undefined - ? 0 - : (mdLastIndex as number) - mdStartIndex + 1; - - const wpStartIndex = postsForOnePage.find(post => post.source === 'wp') - ?.index; - const wpLastIndex = postsForOnePage - .slice() - .reverse() - .find(post => post.source === 'wp')?.index; - const wpCount = - wpStartIndex === undefined - ? 0 - : (wpLastIndex as number) - wpStartIndex + 1; - - createPage({ - path: pageIndex === 0 ? '/' : `/page/${pageIndex + 1}`, - component: template, - context: { - pageIndex, - totalPages, - mdStartIndex: mdStartIndex === undefined ? -1 : mdStartIndex, - mdCount, - wpStartIndex: wpStartIndex === undefined ? -1 : wpStartIndex, - wpCount, - }, - }); - - pageIndex++; - } - } - - async function getPostsPerPage() { - const siteConfig = await graphql( - ` - { - site { - siteMetadata { - blogList { - pagination - } - } - } - } - ` - ); - - return (siteConfig.data as { - site: { siteMetadata: { blogList: { pagination: number } } }; - }).site.siteMetadata.blogList.pagination; - } -}; - -export interface PageContext { - slug: string; - previous: Post | null; - next: Post | null; -} - -export interface BlogListContext { - pageIndex: number; // starting from 0 - totalPages: number; - mdStartIndex: number; - mdCount: number; - wpStartIndex: number; - wpCount: number; -} - -async function getPostsFromMarkdown(graphql: any): Promise { - const markdownResults: { - data: { - allMarkdownRemark: { - edges: { - node: { - fields: { slug: string }; - frontmatter: { title: string; date: string }; - }; - }[]; - }; - }; - } = await graphql( - ` - { - allMarkdownRemark { - edges { - node { - fields { - slug - } - frontmatter { - date - title - } - } - } - } - } - ` - ); - - const posts = markdownResults.data.allMarkdownRemark.edges; - return posts - .map(post => ({ - slug: post.node.fields.slug, - title: post.node.frontmatter.title, - date: new Date(post.node.frontmatter.date), - source: 'md' as const, - })) - .sort((post1, post2) => post2.date.getTime() - post1.date.getTime()) - .map((post, index) => ({ ...post, index })); -} - -async function getPostsFromWordPress(graphql: any): Promise { - const wordpressResult: { - data: { - allWordpressPost: { - edges: { - node: { - title: string; - date: string; - slug: string; - }; - }[]; - }; - }; - } = await graphql( - ` - { - allWordpressPost { - edges { - node { - title - date - slug - } - } - } - } - ` - ); - - const posts = wordpressResult.data.allWordpressPost.edges; - return posts.map((post, index) => ({ - slug: post.node.slug, - title: post.node.title, - date: new Date(post.node.date), - index, - source: 'wp', - })); -} - -interface Post { - slug: string; - title: string; - date: Date; - index: number; - source: 'md' | 'wp'; -} diff --git a/packages/blog/content/assets/app-icon.jpg b/packages/blog/content/assets/app-icon.jpg deleted file mode 100644 index 6b4bc20..0000000 Binary files a/packages/blog/content/assets/app-icon.jpg and /dev/null differ diff --git a/packages/blog/content/assets/gatsby-icon.png b/packages/blog/content/assets/gatsby-icon.png deleted file mode 100644 index 908bc78..0000000 Binary files a/packages/blog/content/assets/gatsby-icon.png and /dev/null differ diff --git a/packages/blog/content/assets/profile-image.jpeg b/packages/blog/content/assets/profile-image.jpeg deleted file mode 100644 index 7ec5ff0..0000000 Binary files a/packages/blog/content/assets/profile-image.jpeg and /dev/null differ diff --git "a/packages/blog/content/blog/2021-01-\345\221\250\346\234\253/index.md" "b/packages/blog/content/blog/2021-01-\345\221\250\346\234\253/index.md" deleted file mode 100644 index 30d3c15..0000000 --- "a/packages/blog/content/blog/2021-01-\345\221\250\346\234\253/index.md" +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: 周末 -date: "2020-12-13" ---- - -一个周末又要告一段落,你都做了什么有趣的事情?他是繁忙的还是安逸的,快乐的还是悲伤的? - -周末之前立得flag,大概是没有都实现的。说好的在家整理照片,学学aws没有实现。但是也做了很多有点用的事情。 - -几个月来终于洗了一次车,做了保养,虽然那风吹的我有一种没穿秋裤的错觉。 - -周六是双十二,这一次没有太多的关注大促的事情,但是还是给自己添置了个胶囊咖啡机,给醒醒买了她的第一套乐高,给跃跃什么也没买(尴尬脸😓),给大家买了一堆吃的,希望这些物件能给生活更多的乐趣吧。 - -周六去丈母娘家,吃了顿很棒的火锅,没想到周日去姥姥家,又吃了一顿。在这寒冷的冬日,也许温暖的不仅仅是火锅,还有亲人们的团圆。 - -但是到周日晚上的时分,我发现自己还是不饿,打得嗝竟然还是早餐韭黄饺子的味道。我意识到自己的这个周末,有些过分地暴饮暴食,以至于超过了身体的极限。以后还是要多多注意啊。 - -不管走在哪里,醒醒永远是一个焦点。接近十五个月的她,正在解锁更多技能。虽然她还是会摔跤,大概每天都会因为磕头夹手哭上几次,但她还是在亲人的注视之中,慢慢长大。很高兴能够在这周末有更多跟她一起相处的时光,虽然可能因此我没哟机会写一下午代码,或者在一个书店里度过自在的时光。 - -关于开始那个问题的答案,这个周末对我来说,大概是繁忙的,快乐的。但是我还是希望我的下个周末,能够多几个小时去写写代码,那也是繁忙而快乐的呀。 - -周一要来了,还是要加油认真的生活和工作 diff --git a/packages/blog/content/blog/2021-7-8-media-query/image-20210708233625363.png b/packages/blog/content/blog/2021-7-8-media-query/image-20210708233625363.png deleted file mode 100644 index fe06173..0000000 Binary files a/packages/blog/content/blog/2021-7-8-media-query/image-20210708233625363.png and /dev/null differ diff --git a/packages/blog/content/blog/2021-7-8-media-query/image-20210709165558898.png b/packages/blog/content/blog/2021-7-8-media-query/image-20210709165558898.png deleted file mode 100644 index 3404001..0000000 Binary files a/packages/blog/content/blog/2021-7-8-media-query/image-20210709165558898.png and /dev/null differ diff --git a/packages/blog/content/blog/2021-7-8-media-query/index.md b/packages/blog/content/blog/2021-7-8-media-query/index.md deleted file mode 100644 index 3b568fd..0000000 --- a/packages/blog/content/blog/2021-7-8-media-query/index.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: Media Query与屏幕像素 -date: "2021-07-08" -description: "也许Media Query是一个看起来很简单的task, 在CSS代码中加一些@media似乎就能解决所有的问题。但是实际上,可以访问一个网站的设备千千万万,需要考虑的问题还有很多。本文着重讨论Media Query中的px与设备分辨率的关系" ---- - -# 前言 - -基于CSS的Media Query是解决Web响应式(Responsive)的常见方法。 - -它的格式非常简单,例如如下的代码,就表示当屏幕的像素不大于600px时,括号里的CSS样式生效 - -```scss - @media only screen and (max-width: 600px) { - font-size: 14px; - } -``` - -除了支持基于screen的响应式,也支持一些其他的媒体类型,例如基于打印的: - -```scss - @media only print and (max-width: 600px) { - font-size: 14px; - } -``` - -甚至一些更复杂feature: - -```scss -@media (prefers-color-scheme: dark) { - .day.dark-scheme { background: #333; color: white; } - .night.dark-scheme { background: black; color: #ddd; } -} - -@media (orientation: landscape) { - body { - flex-direction: row; - } -} - -@media (min-resolution: 72dpi) { - p { - text-decoration: underline; - } -} -``` - -你可以打开这里查看更多: [Using media queries - CSS: Cascading Style Sheets | MDN (mozilla.org)](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#media_features) - - - -# 问题 - -当我们使用基于屏幕或者打印纸的响应式设计时,往往需要跟像素打交道。 - -对于下面的代码, - -```scss - @media only screen and (max-width: 600px) { - font-size: 14px; - } -``` - -它会在IPhone X中生效,因为通过ChromeDevTools我们可以看到Iphone X的屏幕宽度是375px,低于我们在这里设置的600px。 - -但是如果你足够细心,会发现这并不是IphoneX的真实屏幕分辨率,它的分辨率高达1125*2436 pixels - -![image-20210708233625363](./image-20210708233625363.png) - - - -为什么会存在这样的gap?真实的分辨率与media query中的分辨率又是如何换算的? - - - -# 解释 - -## 为什么需要换算? - -因为基于实际分辨率来执行media query是有bug的。 - -例如5.8寸的IPhone X的分辨率是1125\*2436 pixel,而我正在使用的这台27寸显示器的分辨率是2560\*1440 pixel,这两个设备分辨率相似,但是尺寸差了n倍,使用同一套响应式设计显然说不通。 - -IphoneX显然应该使用与它尺寸类似的Iphone 6相同的响应式设计,而后者的分辨率只有750\*1334。 - - - -所以,浏览器在处理media query时,都会使用一套换算机制,这套机制似乎是基于屏幕的尺寸大小而不是分辨率来计算的,比如Iphone 6与Iphone X的宽度都被当作了375px。 - - - -## 如何换算? - -我从很早就知道media query中的px并不等同于设备的实际分辨率,但是对于如何换算却一直没有深入研究。 - -研究了Web标准( [CSS Values and Units Module Level 3 (w3.org)](https://www.w3.org/TR/css-values-3/#absolute-lengths)),才发现答案原来是如此简单,然而我之前的理解是错误的。 - - - -关于“如何换算”这个问题的答案,是`根本没有换算`。 - -在标准中,px作为一种距离单位,被划入了"Absolute Length Unit",也就是说,它跟cm, inch, mm这一类的单位一样,都是可以被物理测量的。正因为如此,这些单位之间存在固定的换算关系(例如1cm=10mm),也因此被叫做“绝对长度单位”。 - -在标准中,px的定义是`1/96th of 1in`, 也就是`一英寸(2.54厘米)的1/96`。也就是说,在Web领域,一个屏幕的宽度是多少px,跟屏幕分辨率或者像素密度完全没有关系,只跟屏幕的尺寸相关。 - - - -一切似乎到此为止了,我本着认真负责的精神,基于IPhone X 375\*812的尺寸,计算了下它的对角线长度 - -```javascript -export function playground() { - const screenSize = 5.8; // 5.8英寸,屏幕的物理尺寸(对角线长度) - const width = 375; // 宽度 - const height = 812; // 高度 - const diagonal = Math.sqrt( - Math.pow(width / 96, 2) + Math.pow(height / 96, 2) - ); - console.log(screenSize, diagonal); // 5.8 9.316769388595908 -} -``` - -发现得到的结果完全不对,怎么算出来的对角线长度成了9.32inch,与标称的5.8英寸屏幕相差甚远。 -如果长宽各除以一个1.6, 结果与预期差不多 - -```javascript -export function playground() { - const screenSize = 5.8; // 5.8英寸,屏幕的物理尺寸(对角线长度) - const width = 375 / 1.6; // 宽度 - const height = 812 / 1.6; // 高度 - const diagonal = Math.sqrt( - Math.pow(width / 96, 2) + Math.pow(height / 96, 2) - ); - console.log(screenSize, diagonal); // 5.8 5.822980867872443 -} -``` - - - -于是进一步的学习了标准。 - -绝对距离单位,例如cm, inch, mm, 虽然可以被物理测量,且存在相互间换算关系,但是在屏幕,纸张(打印)等不同介质中,含义是不同的。举个例子,屏幕的1cm跟纸张的1cm,基本上不是一个东西。 - -理解这个,需要再了解几个概念 - -### 几个概念 - -#### Anchor - -在浏览器创建CSSDOM过程中,需要计算computted value(比如将width: 100%处理成实际的长度,或者处理优先级以确定apply到一个元素上的最终css property)。 - -在计算computed value的过程中,会围绕着某一种距离单位进行 - -对于纸张等介质,anchor会围绕着物理单位进行,比如会把所有的数值都换算成inch。 - -但对于屏幕介质,anchor会围绕着reference pixel进行,即将px换算成reference pixel。 - - - -#### Reference pixel - -Reference pixel是一个角度单位。 -Reference pixel/Viewport pixel/CSS pixel是同一个东西。 -1px = 1/96 inch,这也是对的,但是这里的inch也是CSS的inch,并不一定代表`物理的1/96 inch`。 - -> The reference pixel is *the visual angle* of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm’s length. - -这个官方的定义听起来有一些拗口,总结一下就是reference pixel是一个角度,它是一个常量。 - -设备的距离不同,reference pixel代表的大小也就不同: - -![image-20210709165558898](image-20210709165558898.png) - -## 最终的答案 - -* px是一个`角度`单位 -* 每一个屏幕媒介的视距不同,角度不同,因此视角也不同 -* 视角决定屏幕的px/reference pixel是多少 - - -总结一下,为什么pixel是一个角度,而不是物理长度,这是因为角度更能反应`一个物体对于观者有多大`这一个事实(透视原理)。 -27寸显示器与6寸手机屏幕的观看距离是类似的,但显示器更大,这也就是为什么显示器的宽度pixel值更大。 -使用pixel,我就不需要关心一个元素在不同的屏幕上显示的物理尺寸问题了。将一段文字设置为16px的font-size,那这些文字在观者看来,在所有不同屏幕媒介上的观者大小应该是差不多的。 - -# 总结 - - -* 最后总结一下,px其实是一个角度尺寸。 -* px与屏幕的像素不是一个概念。 -* px的定义跟介质类型有关。 -* inch也不一定代表物理上的一英寸 - -* 一个屏幕离使用者的距离越远,px代表的物理尺寸越大 -* 多数情况设计者不需要考虑px代表的物理大小,而只需要考虑他的“可视角度大小”。 - diff --git a/packages/blog/content/blog/2022-3-19-A-Clash-DNS-setting/index.md b/packages/blog/content/blog/2022-3-19-A-Clash-DNS-setting/index.md deleted file mode 100644 index 74fe1fd..0000000 --- a/packages/blog/content/blog/2022-3-19-A-Clash-DNS-setting/index.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: A Clash DNS index setting using redir-host -date: "2022-3-19" -description: "记录一下一个可以工作基于redir-host的Clash DNS setting" ---- - -最近Clash for Windows启动了一个傻瓜的TUN模式选项,只能用fake-ip模式,根据官方的说法,fake-ip因为会直接将假的DNS解析结果返回客户端,相对redir-host可能会有更好的性能(When a client initiates a DNS request, Clash will return a spurious IP directly to the client. At the same time, clash send the domain names that need to be resolved to each upstream DNS server. Finally, the first result with the fastest return is correlated with a fake IP. ) -但可能也是因为它的实现原理,触发了某些客户端(例如qtorrent)的安全机制,导致其正常工作。 - -我并不care fake-ip提供的那一点性能加成,稳定更重要,参考文档,还是配置出了一套基于redir-host的Clash Mixin: - -```yaml -mixin: - dns: - enable: true - enhanced-mode: redir-host - nameserver: - - 114.114.114.114 - - 223.5.5.5 - fallback: - - https://dns.google/dns-query - - https://dns.cloudflare.com/dns-query - tun: - enable: true - stack: gvisor - dns-hijack: - - 198.18.0.2:53 - auto-route: true - auto-detect-interface: true -``` - -简单解释一下: -* enhanced-mode: 开启redir-host模式 -* nameserver: 默认的DNS server,可以设置多个,支持DNS over DCP。Clash会同时像这些server发请求,并取最快返回的response -* fallback: 当目标不在大陆时使用的DNS(GEOIP!='CN'),工作原理同上,区别是这些DNS不能受DNS污染的影响,也就是说应该选择境外的DNS。(Known DNS Providers)[https://kb.adguard.com/en/general/dns-providers] -* 更多的配置如果不清楚不要随便修改,想要了解更多可以参考:(Clash配置文档)[https://lancellc.gitbook.io/clash/clash-config-file/dns] - - -Reference: -https://lancellc.gitbook.io/clash/clash-config-file/dns diff --git a/packages/blog/content/blog/SigninFormBestPractice/index.md b/packages/blog/content/blog/SigninFormBestPractice/index.md deleted file mode 100644 index 6569bed..0000000 --- a/packages/blog/content/blog/SigninFormBestPractice/index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: 登陆表单的最佳实践 -date: "2020-12-30" -description: "凑巧在同事的电脑上看到这篇Signin Form Best Practice的video。原来表单的最佳实践,不是什么高端的pattern,而是回归原生,回归纯粹,下面是一些简要笔记" ---- - - - - -Tips: -* 使用`
`, ``, `