作者归档:白宦成

关于白宦成

独立开发者, 自由职业者, 写作者

自定义 Excalidraw 的字体大小

自定义 Excalidraw 的字体大小

Excalidraw 是一个非常好用的手绘风格的绘图工具,我给自己部署了一个版本来降低自己写作配图的难度。如果你感兴趣,可以访问 draw.ixiqin.com 体验我自己维护的版本。

白宦成

Excalidraw 默认的字体整体比较小,对于我来说,习惯将图画的大一些,这样在不同的设备上,都可以方便的看清楚图片的内容。

修改 S、M、L、XL 对应的字体大小

Excalidraw 将字体大小的变化定义在 src/actions/actionProperties.tsx 当中,因此,你需要修改不同按钮具体的字体,则需要修改这里的配置。

字体大小修改工具

将下方代码中的 options 中 value 修改为你需要的值,即可实现不同的字体大小。

export const actionChangeFontSize = register({
  name: "changeFontSize",
  perform: (elements, appState, value) => {
    return changeFontSize(elements, appState, () => value, value);
  },
  PanelComponent: ({ elements, appState, updateData }) => (
    <fieldset>
      <legend>{t("labels.fontSize")}</legend>
      <ButtonIconSelect
        group="font-size"
        options={[
          {
            value: 20,
            text: t("labels.small"),
            icon: <FontSizeSmallIcon theme={appState.theme} />,
            testId: "fontSize-small",
          },
          {
            value: 28,
            text: t("labels.medium"),
            icon: <FontSizeMediumIcon theme={appState.theme} />,
            testId: "fontSize-medium",
          },
          {
            value: 36,
            text: t("labels.large"),
            icon: <FontSizeLargeIcon theme={appState.theme} />,
            testId: "fontSize-large",
          },
          {
            value: 50,
            text: t("labels.veryLarge"),
            icon: <FontSizeExtraLargeIcon theme={appState.theme} />,
            testId: "fontSize-veryLarge",
          },
        ]}
        value={getFormValue(
          elements,
          appState,
          (element) => {
            if (isTextElement(element)) {
              return element.fontSize;
            }
            const boundTextElement = getBoundTextElement(element);
            if (boundTextElement) {
              return boundTextElement.fontSize;
            }
            return null;
          },
          appState.currentItemFontSize || DEFAULT_FONT_SIZE,
        )}
        onChange={(value) => updateData(value)}
      />
    </fieldset>
  ),
});

修改默认字体大小

默认字体的大小被定义在 src/constants.ts,你可以修改其中的 DEFAULT_FONT_SIZE 来实现控制默认情况下的字体大小。

export const DEFAULT_FONT_SIZE = 28;

参考代码:https://github.com/bestony/excalidraw/commit/78d2d103b40c48bdccbecd7deb85f1fd0d6b4d2f

https://github.com/bestony/excalidraw/commit/14bca18aa6395280cfda15202beaf56dc966a401

解决 Vercel 在国内访问被墙的问题

解决 Vercel 在国内访问被墙的问题

Vercel 因为被大量使用,自然而然被墙掉了,不过好在 Vercel 官方提供了单独的 IP 和 CNAME 地址给大家,对于国内的用户来说,配置一下单独的解析,依然可以享受 Vercel 提供的服务。

A记录地址:76.223.126.88

CNAME 记录地址:cname-china.vercel-dns.com

来源:https://www.vercel-status.com/incidents/r758bhbklgfd

OneInStack 下部署 WordPress Multisite 的 Nginx 转发规则

OneInStack 下部署 WordPress Multisite 的 Nginx 转发规则

在 OneIn Stack 下如果需要配置一套 WordPress MU 的话,需要配置 Nginx 相应的转发规则。具体的规则如下:

 if (!-e $request_filename) {            
 	rewrite /wp-admin$ $scheme://$host$uri/ permanent;            
 	rewrite ^(/[^/]+)?(/wp-.*) $2 last;            
 	rewrite ^/[^/]+(/.*.php)$ $1 last;    
 }    
 location / {        
 	try_files $uri $uri/ /index.php?$args;    
 }

将上述规则放置在 /usr/local/nginx/conf/rewrite/wordpressmu.conf ,并在创建 VHost 时选择对应的主机即可。

电子书助手

电子书助手

我自己是一个很喜欢看书的人,所以买了很多平台的电子书会员(Kindle、微信读书、华章书院),但一直以来,都有一个问题在困扰我,就是如何确认一本书在哪个平台上有?

虽然下意识上我们认为不同的电子书平台上的书籍应该是相同的,但在实际的操作层面,确实是有所不同的。受限于版权、出版社合作关系等等,有些书可以在微信读书上找到,但无法在 Kindle 上找到;有些书可以在图灵社区找到而无法在 Kindle 找到。

这使得作为读者的我十分困扰,如何才能更加明确的知道我想看的那本书在那个电子书平台上能找到。

终于,现在有了这个工具 —— eBooks Assistant 油猴脚本

这个脚本通过自己实现的爬虫,爬取了各平台拥有的电子书数据,从而实现在你访问某个豆瓣电子书页面时,告诉你那些平台有对应的电子书,一键跳转到对应的平台进行阅读,降低搜寻电子书的成本。

脚本地址:https://greasyfork.org/en/scripts/412479-ebooks-assistant

脚本及服务器源码:https://github.com/caspartse/eBooksAssistant

算法推荐与个人精选

算法推荐与个人精选

一直以来,我其实对于人工智能赋能于个人十分关注。

信息流算法帮助我们获取到了更多的信息。但在体验信息流算法的时候, 也看到了算法推荐的另一个反面 —— 我们被算法控制,算法让我们相信它希望我们相信的东西。

为此,我开始抗拒算法推荐,开始使用一些更加传统的方式来完成我的信息获取 —— 使用 RSS 来阅读新闻;使用 Apple Music 来收听信息。实际上,近几年的 Newsletter 的复兴,也是一种对于算法推荐的对抗。

但这不过是我在时代的洪流之下的微弱的抵抗,并不能从根本上解决信息茧房的问题。也很难让自己得到满意的结果。究其原因,是因为现有的算法代表的是企业的利益,而不是个人的利益。现有的算法推荐都是由企业定义的,而非个人定义的。所以无法让算法真正意义上为个人服务。

我们的算法和 AI ,还需要更加的普适。

TailwindCSS 下的响应式设计

TailwindCSS 下的响应式设计

前言

我自己在最近的一段时间里,整体是比较喜欢 TailwindCSS 这类样式框架的,它可以非常灵活的定义样式,从而可以十分方便的进行创意类的 UI 设计,实现一些独特的 UI 特性。不过,由于我并非一个专业的前端,也不曾研究过响应式设计。这让我在进行前端开发过程中,吃尽了苦头。

痛定思痛,认真的学习了一下 TailwindCSS 下的响应式设计,为以后的开发做好准备。磨刀不误砍柴工嘛。

正文

设计理念

在进行 TailwindCSS 下的响应式设计时,需要考虑到其整个设计系统的基础 —— Mobile First(移动优先)。

基于移动优先的理念并不新奇,诸如 Bootstrap 之类的框架早已经教会我们移动优先。

Mobile first, responsive design is the goal.

Bootstrap

在这种设计理念上,我们应该做的是先设计移动端的样式,并根据屏幕的不断扩张,变成一个更加丰富的 UI 和界面。

这一点对于做研发的我来说,是一个非常反直觉的事情:在绝大多数场景下,我在开发产品的时候,都是看到的桌面端的样式 & 功能,我下意识的以为,桌面端才是应该首要设计的界面。但无论是 Bootstrap,还是 TailwindCSS,其实都是首要设计移动端的

理念的变化没有跟上,导致我对于 TailwindCSS 的类样式的理解不到位,在设计时会出现错误。

断点(breakpoint)的作用

在进行响应式开发的时候,断点是非常重要的,借助于 CSS 3 提供的 Media Query,我们得以在不同的样式尺寸下应用不同的样式设计。

而在 TailwindCSS 当中,根据最小屏幕宽度(为什么是最小而不是最大?因为默认应用在移动设备上,更大的尺寸使用 Media Query 来控制)默认提供了 5 组不同的断点,分别是 sm(640px)、md(768px)、lg(1024px)、xl(1280px)、2xl(1536px),以及不加任何断点情况下的 default 样式。

对于绝大多数的应用来说,处理好 default(手机)、md(平板)和 lg(PC),就已经足够,对于一些面向更 Geek 的场景(比如开发者),他们使用的设备性能和参数更高,可以再定向配置 xl 和 2xl 的样式。

自定义断点

在实际开发过程中,根据用户的场景的不同,TailwindCSS 的默认断点可能并不能满足你的诉求,这种情况下,你还可以根据自己的需要,修改默认的断点的配置(甚至是将其从移动优先调整为 PC 优先:将 min-width 模式调整为 max-width 即可)。

具体可以参考 TailwindCSS Customize Screen Size

总结

在 Tailiwind CSS 下进行响应式开发时,切记从小到大,而非从大到小,不然会让你调试样式的时候十分痛苦。

延展阅读

从一个失败案例来看独立开发过程中不应该犯的 10 个错误

从一个失败案例来看独立开发过程中不应该犯的 10 个错误

最近在 V2ex 上看到一个「8 万变80 万」的帖子,描述了作者作为独立开发者,希望借助独立开发获得自由,但最终负债累累的故事。我将作者的犯下的错,进行了梳理,得到了以下的结果,将其分享给你,帮助你来梳理自己在做的事情。

关于作者

在你读下面的内容之前,我建议你先读一读作者的两个帖子,这样让你对于作者有更多的理解。

我的点评

1. 没有构建 MVP 就持续做产品建设

做外包开发和做独立开发是不一样的,独立开发你没有甲方帮你托底,你所面对的需求也是不明确的。而在这样的一个大背景之下,在尚未完成产品的原型和需求验证的情况下,投入数年来开发一个产品,可以说是非常愚蠢了。当然,我知道很多研发同学出来做东西都是这个问题。切忌不可闭门造车。有些东西没人做不是因为只有你慧眼识珠,也可能是你碰上了一个假需求。

2. ALL IN 在一个在暂时没有现金流的事情

ALL IN 如果成了,固然很漂亮。但 ALL IN 在绝大多数的时候是在悬崖上走钢丝。现实生活中并没有那么多故事给你听。很多时候为什么一些创业者去找 VC 投资?还不是为了给自己增加一些保护,不要让自己的创业影响到自己的生活。ALL IN 对于独立开发者而言,不可取。

前期没有现金流的情况下,低成本运作,小步快跑。

3. 杂而不精

作者在一开始就学了 WordPress、Angular、Unity 等一系列技术,严重的分散了其精力。

任何人进入新的领域都应该做的是专攻一门,快速建立自己的能力和影响力,站稳再研究另外的领域。

4. 创业不是让你补短板,而是要发挥长板

短板的问题短期可以通过外包来解决。特别是发现自己耗费很长的时间都不能做好一件事,这个时候就应该花钱让别人来解决这个问题。不然只会让自己的时间一直浪费下去,失去了重要的机会。

5. 盲目上杠杆

在作者的另外一个帖子你会发现,很早就上了杠杆。而且是在没有现金流的情况下上杠杆,那除了利滚利,还有其他的选择?

杠杆适合放大你的收益,而不是放大你的错误。

6. 关注一些不那么重要的东西

在作者的两个帖子里你可以发现,他有不少的精力都放在了注册美国公司,办理相关的事情上了。一方面,信息差让他以为只能这么干。另一方面,推出一个产品的时候并不一定需要先有收款选项。

用户如果真的需要你的产品,他会比你还想要付款给你,因为怕你死了。

7.在 First Release 之前,做了一堆乱七八糟的事情,且没有给自己放 Milestone

Milestone 是给自己的一个压力。此外,也是给自己一个休止符。如果时间足够,我们总是能发现自己还有各种 Bug 和 Feature,但是无休止的开发会让你失去自己的状态,也可能会让你在错误的道路上越走越远。

8. 技术上的过度优化

产品还没有 release 就开始「微服务」,典型的被技术公众号和大厂忽悠瘸了。你什么业务规模啊,就上微服务。微服务的好处和代价思考过适合你么?

9.关于投资

资本不仅仅能帮助你提供金钱的支撑,还可以给你提供更多的视角,比如你这个业务是否值得做?你的这个业务的发展是否还有别的点是你没关注到的?资本公司

10. 初心是逃避

就像我们说,跳槽不是为了从当前的火坑逃出去,而应该是看到了更好的机会。

他创业的原因是看不惯现有的工作单位。初心不对,意味着全凭运气。初心不对,心态不对,一旦遇到问题,可能就会给自己造成很大的压力。

使用 Stylish 巧妙破解基于 CSS 的复制限制

使用 Stylish 巧妙破解基于 CSS 的复制限制

本文内容仅用于学习和技术研究。请不要用此作恶。

白宦成

在一些网站上,出于版权或增长的诉求,一些网站会在站点内部加入防止复制内容的限制。作为一个内容创作者,我是支持(因为版权原因而不得不选择)这样的行为的。但另一方面,我自己也需要进行一定的笔记,对于长段的内容,显然,直接复制原作者的内容更适合我。因此,我也不得不研究一下,如何破解这种样式的限制。

为什么 CSS 能禁止复制?

CSS 当中提供了一个属性 user-select 可以用于设定文字是否可以被选中,对于非技术人员来说,无法被选中,自然无法使用 Ctrl + C 来复制内容。在这种情况下,对于非技术人员,就可以实现很好的防复制了。

不过,CSS 防复制不算多见,我见的最多的还是以 Javascript 的方式来禁用复制和 Devtools 的。

这个属性的值有以下五种,其中 none 是用于防止复制的,设定为 None 后,即使你的内容是文本内容,也无法被选中,就无法直接使用 Ctrl + C 来完成复制了。而 text 则是可以选择文本,其他的几个属性,你可以在 MDN 的语法说明中找到。

user-select: none;
user-select: auto;
user-select: text;
user-select: contain;
user-select: all;

使用 Stylish 来破解 CSS 的限制

类似油猴脚本可以在目标网页上加载 Javascript 文件,Stylish 可以在目标网页上加载 CSS ,并按照 CSS 的计算权重,让我们的代码可以得到执行。基于这个能力,我们可以覆盖原本网页上样式,来实现将 user-select 的值修改为我们需要的值。

1. 安装 Stylish

前往 Google Chrome Extension Store 安装 Stylish

2. 找到不能复制的文字对应的样式类

在浏览器中打开开发者工具,定位到你需要复制的文本元素,在右侧的调试工具中切换到「计算样式」,就可以在其中找到 user-select属性,并可以看到对应的样式类选择器,复制选择器。

3. 在 Stylish 中新建一个样式文件,并在其中添加对应样式类的代码

因为我们只需要修改复制,所以只需要将对应的属性的值做一个简单的修改即可。

4.设置生效网站

为了减少这段代码影响到的页面,你可以在下方的应用对象这里设定具体生效的网站,从而降低对于其他站点的影响。

总结

本次针对 CSS 禁止复制的研究帮助我节省了大量的研究的时间,有效的提升了我进行研究的效率,真的不错!

看纸质书/电纸书,而不是社会化读书

看纸质书/电纸书,而不是社会化读书

首先,在文章的开始,我先要强调,我并不是绝对不使用社会化读书软件(如:微信读书),但我使用微信读书有自己的方式

接下来是具体的观点内容

我们在读书的时候,应该尽可能的选择纸质书/ Kindle

在各种购买推荐的时候,你都会发现,所有针对 Kindle 的推荐都会提到 「无打扰」,这同样是我推荐你看纸质书/Kindle的原因。

作为手机不离身的一代人,我们现在已经习惯了「被打扰」,但不意味着这是对的,不断的被打扰,让我们无法集中精力去做应该做的事情。当我们不断被打断,我们就更应该去寻找稀缺的集中。

而在这件事上,无论是纸质书还是 Kindle ,都可以实现类似的效果。你可以沏一杯茶(或者是煮一壶咖啡),将手机关静音,放在另外的房间里,拿着一本书,或者是你的 Kindle ,在桌前仔细的阅读。

你可能会担心自己看不到消息。但这世界上有多少事情是「你一个小时不看手机」就会产生问题的。

借助一个和通讯设备分类的工具,我们可以很好的实现想要的「宁静」、「专注」的效果。

但这些,社会化读书软件是无法实现的。

社会化读书软件本来就是帮助人们建立起更全面的连接

几乎所有的企业都希望开发出一款拥有「网络效应」的应用。

网络外部性(network externality),又称网络效应(network effect)或需求方规模经济(demand-side economies of scale),指在经济学或商业中,消费者选用某项商品或服务,其所获得的效用与“使用该商品或服务的其他用户人数”具有相关性时,此商品或服务即被称为具有网络外部性。 最常见的例子是电话或社交网络服务:采用某一种社交媒体的用户人数越多,每一位用户获得越高的使用价值。

对于企业来说,网络效应是一个很好的工具,可以帮助留下用户,但对于用户来说,一方面它的工具性随着网络效应而获得提升,但另一方面,我们也会因为网络效应而被限制在应用当中。

微信读书等一系列社会化软件会通过产品功能的设计,让你不断的被触发,不断接入其中,让你读书也不会那么的纯粹和集中。评论、弹幕,都不断的把你从阅读中拉扯出来,进入到一个社会化的环境当中。

包括从某种角度来看,我在 B 站/ Youtube 上看视频的时候,也很少会开启弹幕(除非我看的内容本来就是很无厘头的内容),我会希望能够静下心来安安静静的欣赏一个作品,而不是不断被拖走,不断的被打断。

社会化读书的用法

我在前面提到过,我其实并不是完全不使用微信读书。我自己使用微信读书的场景是这样的:

  1. 读小说:Kindle 上的小说大多是已经完本的。如果希望看一些更加接近当下的网络作家的小说,那么微信读书是一个很好的选择。而微信读书有阅读赠送书币的设定,你可以通过读小说来获取书币。再通过书币购买新的小说章节。
  2. 读公众号:微信读书可以阅读微信公众号,这一点相比于微信公众号自带的阅读机制,会更好,你可以像图书一样翻阅一公众号,并在其上做标记、批注,对于如果你要深度研究某个特定的公众号,是非常有帮助的(比如很有个人特色的大 V、投资人等)。
  3. 发现新书:我现在发现新书的方式基本上是去线下的书店看有没有什么有意思的新书、去 Amazon 看看最近的优惠是什么书以及去微信读书当中看看朋友的书架里都是什么书(不过我自己的书架其实是隐藏的,因为我不希望让别人发现我在微信读书看的都是小说)。
梦想的房子(5):弱电箱、书房弱电环境

梦想的房子(5):弱电箱、书房弱电环境

作为一个计算机相关行业的从业者,我自然少不了在家中配置一些电子设备。而且我也会花费大量的时间用来在家庭中编程、生活,因此,一个好的家庭网络环境是必要的。

弱电箱

从我当前的租房的状态来看,我可能会在弱电箱中需要以下一些东西:

  1. 光猫:这是当下必备的了,毕竟已经光纤入户,那我们就必须要有相应的光猫来完成光信号的解析。所以这个是不可或缺的。
  2. 交换机:我的家中可能会有大量的设备,因此,交换机对于我来说是必要的。实际上,简单一算可能就会发现我需要的设备需要不止一根网线 mac Mini + PC、NAS、单独接入无线路由器、可能还需要给电视预留网线的接口,再考虑到后续可能会有儿童房、卧室电视之类的,这样就至少需要六口交换机了,需要提前预留(但不一定会用到)
  3. 插座:光猫和交换机需要相应的电力供应,因此,弱电箱中至少要有 5 个左右的插头,以确保不同的设备有充足的电力供应
  4. 风扇:确保弱电箱内部的热量可以散发出去(如果是一个比较大的弱电箱的话,就可以免于买风扇,考其自然散热)。

通过这样的方式,就可以将网络信号从外部问题转化为稳定的内部问题。接下来要处理的就是如何将信号传递到不同的位置。

对于电视,可以直接通过墙内的线路进行信号的传递,直接购买千兆的超6类线来进行线路的部署即可。

此外,还涉及到家中会用到的无线网络。无线网络需要通过网线从交换机侧接入,并辅以 AP 来完成家庭内部的网络覆盖。

对于需要用到网线的书房,需要通过单独的网线,从弱电箱将信号牵引至书房,从而可以在书房内获得信号。出于使用场景的问题,书房内需要单独设定路由器来进行信号的分流。

书房

书房中我的电子设备较多,因此也需要有更多的网络接口来使用。从弱电箱进入到书房后,需要有一个单独的路由器来进行网络承载,这样也可以在书房内构建一个小型局域网,方便在局域网内进行高速的传输。

在路由器方面,我希望是至少支持 1 – 2 个光纤入口的路由器,这样可以让我的 NAS 和 PC 能够以光纤的方式进行接入。另一方面,还要考虑到 NAS 能够被其他设备所访问和其他的电脑(比如 mac 笔记本)的接入,因此,书房应该也有一个单独的空间用于放置路由器和 NAS。

总体来看,我需要一个能够满足如下需求的书房弱点环境:

  1. 路由器:用来建设书房的局域网;
  2. NAS:我的是 QNAP 的 TS231P2,挺好。
  3. 插座:至少需要 2- 3 口的插座,来完成电路的接入。

梦想的房子(4):玄关篇

梦想的房子(4):玄关篇

租房多年,也对于玄关有了一些简单的理解。因此,也就有了自己的需求。

尺寸

够用就行,没啥特别的追求。

功能设施

鞋柜

我们每个人都会有不止一双鞋子。女性更是有不同功能的鞋子,因此,玄关的鞋柜至关重要。在我看来,两个人的话,最少需要 10 ~ 15 双鞋子的存储空间,才能确保地上没有多余的鞋子。

收纳柜

玄关区域除了鞋子以外,其实还有更多的东西,比如钥匙、门卡、口罩、洗手凝胶、一次性拖鞋、耳机等物品。

有了一个单独的收纳柜,可以将这些东西存储在收纳柜中,并在使用时随时拿出来。

在收纳柜上可以有一个区域/小篮子,来放日常出门的钥匙。

下沉式玄关

下沉式玄关和非下沉式玄关的一个很大的区别是它人为的区分出了一个区域,从而可以更好的实现外鞋不进屋。

不过,下沉式玄关挺依赖房子本身的属性的,也不一定能搞定。

可视门禁控制器

现在的新房基本都有这个,不过放在哪也是个讲究。我觉得放在门口比较合适。放在厨房/客厅其实感觉不太实用。

总结

玄关区域不大,但细节不少。特别是在疫情当下,玄关作为家的入口,还是很值得关注一下的。