技术交流

好好学习,天天向上。

0%

2021-12-31小记

[toc]

背景

 前几天结束了本年度的述职工作,同事们又给我提了些宝贵的建议。述职是公司每半年一次的例行事项,大概流程就是每个人先表述自己过去的半年一年干了些什么事情,然后项目组的人再给表述者一些评价。大家会对表述者过去一段时间做得好的地方进行表扬,也会针对做得不好的地方提一些建议。我比较在意大家的建议。我这次得到的建议关于两点:1、文档写作质量太差,文档内容只能自己看,没有站在读者的角度写作;2、文档内容没有自己进一步的转化,很像是内容摘抄。其实这两点问题我自己也知道,自己之前确实比较疏于关注文档质量。究其原因,还是自己确实不喜欢写东西。我喜欢解决问题,相对于文档写作,解决各种稀奇古怪的问题更能让我获得成就感。

 但是同时我也知道,只会解决问题是不够的。一个人必须学会扩大自己的影响力,因为影响力可以转化为其它自己想要的东西。就拿Bilibili那些UP主举个例子吧,他们可能也是像你我一样的普通人,但是他们愿意去表述自己。难道他们的视频一定很有趣吗?这得看从谁的角度看。很多UP主就是分享生活日常,比如拆个包裹,逗逗猫狗。要说多有趣,如果是UP视角,可能就是生活中平凡的小事。但是在观众角度看,就会觉得有趣。不然那些UP也不会动辄数十甚至上百万的关注者了。这些关注者就能给他们带来收益呀,转化过程就实现了。

 再提下稚晖君,这个UP早期在vivo工作的时候我就知道了。他确实很有趣,擅长使用自己学过的各种技术做些小玩意,之前我还向他请教过他的技术栈的相关问题。现在稚晖君已经以天才少年的身份入职华为了,华为的天才少年可是有百万年薪的。稚晖君的特点一是动手能力强,二是能在社区有效圈粉。其实就能力这方面来说,稚晖君的技术栈,除去3D建模等工业设计这一块内容我不会以外,其它的我都能做。是的,他清华的,那一个技术点他2天搞定,我5天怎么也搞定了。毕竟现在做IT的,什么东西搜索引擎上没有。我唯一佩服的是他的圈粉能力(也就是影响力),这是我望尘莫及的。所以他是天才少年,我不是。

 这个社会真的是遍地是黄金。我很喜欢一句话,“这个世界可以给你任何想要的东西,前提是你得说清楚。”小到组内,中到部门,大到各种技术社区,都是的舞台。只靠能解决问题在这些舞台上是表演不好的,而文章写得好则可以,视频做得好也可以,有新奇想法仍然可以。

 今天是2021年的最后一天,在这里给明年定个目标吧。明年要坚持两件事:第一件事是坚持读书,包括但不限于各种技术书籍;第二件事是坚持写作,而且是高质量的写作。

 我决定今天就开始行动。当前目标是尝试详细的记录一件事情;中期目标是逐步把这个网站上所发布文章的内容重新整理,主要处理那些错别字、错拼写的单词以及凌乱的表述;长期目标是提升自己的思维方式以及写作能力。


我在Typora和Hexo的使用过程中碰到了一个问题,下面我就尝试对该问题的产生背景和解决过程进行详细描述


介绍

 如背景中所描述的,其实我前两天就开始思考怎么行动了。最终决定就先从我这个博客网站开始入手。这个网站建立也一年多了,之前只是粗糙地放一些粗糙的文章。所谓“工欲善其事,必先利其器。”后面我想将网站做精致一点,所以这几天又系统的学习了Hexo(本网站的实现框架)的写作语法,还对网站配置重新做了调整。现在这个网站看起来确实比以前好些了。

 我平时写文章所用的软件叫Typora,是一款采用Markdown语法的文档编辑器。如果我需要把写好的文章放到博客上,就会将文件交给Hexo渲染。我碰到的问题就产生在Typora和Hexo的配合过程中。

 Typora的图片插入语法是标准的Markdown语法,如下所示

1
![alt text](url "title")

 其中“title”字段是可选的。比如我要插入张三自拍照,那么可以写成

1
![zhangsan_selfie.png](/image_folder/zhangsan_serlfie.png)

 之后Hexo会将这个句话渲染成HTML语法

1
<img src="/image_folder/zhangsan_serlfie.png" class="" title="zhangsan_selfie.png">

 上面这个过程工作得很好,Hexo是支持原生Markdown语法渲染的。但是有一点不方便,如果期望两套软件能正常配合,那么在Typora中写作的时候,图片资源路径必须保持和Hexo渲染之后的图片资源路径保持一致,否则Hexo就会找不到图片,导致网站页面图片无法显示。这就意味着我必须在用Typora写作的时候,将所有的图片资源放到某个固定的文件夹中。如果这么做,图片的组织将非常凌乱,因为所有文章的图片都将存放到同一个目录下。

 Typora的设计倒是很人性化,它可以让用户自行设定每次用户插入图片后可以对图片执行的动作,如下图

image-20211231201855382

 比如将图片自动拷贝到某个的固定目录中,只需要设定“复制到指定路径”,再配置好具体路径就好了。但如前面所说,这是我不喜欢的。Typora还可以将图片拷贝到和文章文件同级别的目录下,也就是将路径设定为./${filename}。之后效果就会变成下面这样,属于2021-12-31.md的图片会被Typora自动拷贝到2021-12-31目录中。

 在Typora中插入图片,用户需要做的,就是在需要插入图片的地方粘贴即可,Typora会自动的按照配置内容在图片粘贴处插入Markdown图片插入语句。如果是相对路径,那么语句就类似下面这样。

1
![image-20211231201855382.png](2021-12-31/image-20211231201855382.png)

 此外,Typora还支持图片的缩放,只需要对着图片右击,然后选择缩放比例即可

image-20211231203333113

 原生的Markdown语法不支持图片缩放,Typora是通过HTML语法实现的,缩放后的图片插入语句会变成下面这种HTML语句。

1
<img src="2021-12-31/image-20211231201855382.png" alt="image-20211231201855382" style="zoom: 67%;" />

 Hexo支持渲染两种图片插入语法,Markdown原生语法,或者是Hexo标签语法。如果是Markdown原生语法,则不支持相对路径。如果是Hexo标签语法,则既支持图片缩放,还支持相对路径。另外,如果Markdown文件中嵌入了HMTL的图片插入语法,则Hexo会默认不做修改。

Hexo的标签语法就像下面这样。首先这个语法我肯定不会在Typora中用,Typora不支持Hexo的专用语法。其次我也不会在每次文章写完后手动的转换,你看这个语法就知道用起来挺复杂的。

1
{% img [class names] /path/to/image [width] [height] '"title text" "alt text"' %}

问题产生

 从我的Typora使用习惯可以知道,我既需要相对路径,又需要图片缩放功能。那么Hexo有没有办法同时满足我这两点需求呢?答案是不能完全满足。有一个名为hexo-image-link(地址)的Hexo插件试图解决类似问题。Hexo为方便用户定制功能,是支持扩展插件的。这个插件的主要功能就是将采用相对路径的Markdown图片插入语法,转为Hexo的标签语法。

1
![image file label](./markdown-file-name/local-image.png) -> {% asset_img label local-image.png %}

 通过这个插件,那么我可以使用相对路径,但是图片缩放就不行了。

分析原理

 我决定自己实现图片缩放功能,就从hexo-image-link的源码入手。该插件的源码仓包括三个文件

 README.md按照惯例是项目描述,pacage.json看起来像是包描述内容,所以我的目标放在了index.js上。从index.js的后缀名我知道插件是JavaScript写的,我不懂JavaScript。但好在index.js的内容不多,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
'use strict';

// match markdown image and covert to asset_img
hexo.extend.filter.register('before_post_render', function(data){

data.content = data.content.replace(/!{1}\[([^\[\]]*)\]\((\S*)\s?(?:".*")?\)/g,
function(match_str, label, path){

// if only one /
if( (path.split("/")).length == 2){
console.debug("Markdown Image Path: " + match_str);
console.debug("asset_img string: " + "{% asset_img " + (path.split("/"))[1] + " " + label + " %}" );
return "{% asset_img " + (path.split("/"))[1] + " " + label + " %}"
}else{
console.debug("Markdown Image Path does not exists!");
return match_str;
}

});

return data;
});

  天呐,看不懂。按道理到这里就该放弃了,但是我没有,毕竟我可是超能折腾的。我仔细分析了下它的代码,然后得到下面我加注释的版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
'use strict';
// 像是控制语句生效阶段的,猜想Hexo的渲染工作是分阶段的,类似于某些测试框架,分Pre,Process,Post
hexo.extend.filter.register('before_post_render', function(data){ // 这里是将function这个回调注册到框架pre阶段,data由框架传入
// 下面应该是将data的content做替换,凡是被正则表达式匹配到的句子都用function处理
data.content = data.content.replace(/!{1}\[([^\[\]]*)\]\((\S*)\s?(?:".*")?\)/g,
function(match_str, label, path){ // 实在搞不懂match_str, label, path这几个参数怎么传进来的

// if only one /
if( (path.split("/")).length == 2){
console.debug("Markdown Image Path: " + match_str);
console.debug("asset_img string: " + "{% asset_img " + (path.split("/"))[1] + " " + label + " %}" );
return "{% asset_img " + (path.split("/"))[1] + " " + label + " %}"
}else{
console.debug("Markdown Image Path does not exists!");
return match_str;
}

});

return data;
});

 我查了一下Hexo官发对于插件扩展的介绍,印证了部分我的猜测。然后还知道了data是Hexo对文章内容的抽象,data.content是文章全文字符串,data.path是文章渲染后的路径。

 现在唯一让我困惑的是match_str, label, path这几个参数是怎么拿到的,我怀疑这是Hexo框架做的工作(后面发现实际不是)。

学习技术

  为了解决这个疑惑,我决定先复习一下正则表达式。正则表达式我之前学过,但是早忘光了。所以我系统的看完这个正则表达式教程以及JavaScript的replace用法,这个过程消耗数个小时。之后我就知道文件中的正则表达式和参数是怎么回事了,但是这篇文章的读者不一定关心,所以这里我就不描述了。

解决问题

  经过几十分钟的编码调试,我得到了下面这段代码。将其追加在index.js后面,就可以实现我想要的功能了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
hexo.extend.filter.register('before_post_render', function(data){

data.content = data.content.replace(/<img\s+src\s*=\s*"([^"]*)"\s+alt\s*=\s*"([^"]*)"\s+style\s*=\s*"zoom\s*:\s*([1-9][0-9]*)%\s*;\s*"\s*\/>/g,
function(match_str, path){
// if only one /
if( (path.split("/")).length == 2){
console.debug("Html Image Path: " + match_str);
console.debug("File Path: " + data.path + " " +
"Image Path: " + path);
return match_str.replace(path, "/" + data.path + (path.split("/"))[1]);
}else{
console.debug("Html Image Error: " + match_str);
return match_str;
}

});

return data;
});

 具体而言,该代码可以实现下述转换

1
2
3
<img src="2021-12-31/image-20211231201855382.png" alt="image-20211231201855382" style="zoom: 67%;" />
convert to
<img src="/2021/12/31/life/image-20211231201855382.png" alt="image-20211231201855382" style="zoom: 67%;" />

 效果就是我既可以在Typora中使用图片缩放和相对路径,也可以在Hexo正常渲染。

问题总结

 其实我们的预研工作就类似于这样,总会碰到各种奇怪的问题。但只要持着一颗爱折腾的心去发挥学习能力,总是能解决各种问题的。解决问题的能力也会随着解决问题的次数增多而增强。举例来说,为什么我能在完全不懂JavaScript的情况下修改其代码?因为我已经会了C++、Python还有Java等编程语言,熟悉这里碰到的类似于lambda的语法。之前对正则表达式的了解,这里也发挥了作用。

 分析问题,学习知识,解决问题,就是我一直以来面对问题的法宝。