hexo-start
摘要内容……
摘要内容……
经常刷 LeetCode 的读者肯定知道鼎鼎有名的 twoSum 问题,我们的旧文 Two Sum 问题的核心思想 对 twoSum 的几个变种做了解析。
但是除了 twoSum 问题,LeetCode 上面还有 3Sum,4Sum 问题,我估计以后出个 5Sum,6Sum 也不是不可能。
那么,对于这种问题有没有什么好办法用套路解决呢?本文就由浅入深,层层推进,用一个函数来解决所有 nSum 类型的问题。
[leetcode1](1. 两数之和 - 力扣(LeetCode) (leetcode-cn.com))
力扣上的 twoSum 问题,题目要求返回的是索引,这里我来编一道 twoSum 题目,不要返回索引,返回元素的值:
如果假设输入一个数组 nums 和一个目标和 target,请你返回 nums 中能够凑出 target 的两个元素的值,比如输入 nums = [5,3,1,6], target = 9,那么算法返回两个元素 [3,6]。可以假设只有且仅有一对儿元素可以凑出 target。
我们可以先对 nums 排序,然后利用前文「双指针技巧汇总」写过的左右双指针技巧,从两端相向而行就行了:
1 | vector<int> twoSum(vector<int>& nums, int target) { |
这样就可以解决这个问题,不过我们要继续魔改题目,把这个题目变得更泛化,更困难一点:
nums 中可能有多对儿元素之和都等于 target,请你的算法返回所有和为 target 的元素对儿,其中不能出现重复。
函数签名如下:
1 | vector<vector<int>> twoSumTarget(vector<int>& nums, int target); |
比如说输入为 nums = [1,3,1,2,2,3], target = 4,那么算法返回的结果就是:[[1,3],[2,2]]。
对于修改后的问题,关键难点是现在可能有多个和为 target 的数对儿,还不能重复,比如上述例子中 [1,3] 和 [3,1] 就算重复,只能算一次。
首先,基本思路肯定还是排序加双指针:
1 | vector<vector<int>> twoSumTarget(vector<int>& nums, int target { |
但是,这样实现会造成重复的结果,比如说 nums = [1,1,1,2,2,3,3], target = 4,得到的结果中 [1,3] 肯定会重复。
出问题的地方在于 sum == target 条件的 if 分支,当给 res 加入一次结果后,lo 和 hi 不应该改变 1 的同时,还应该跳过所有重复的元素:

1 | while (lo < hi) { |
这样就可以保证一个答案只被添加一次,重复的结果都会被跳过,可以得到正确的答案。不过,受这个思路的启发,其实前两个 if 分支也是可以做一点效率优化,跳过相同的元素:
1 | vector<vector<int>> twoSumTarget(vector<int>& nums, int target) { |
这样,一个通用化的 twoSum 函数就写出来了,请确保你理解了该算法的逻辑,我们后面解决 3Sum 和 4Sum 的时候会复用这个函数。
这个函数的时间复杂度非常容易看出来,双指针操作的部分虽然有那么多 while 循环,但是时间复杂度还是 O(N),而排序的时间复杂度是 O(NlogN),所以这个函数的时间复杂度是 O(NlogN)。
这是力扣第 15 题「三数之和」:

题目就是让我们找 nums 中和为 0 的三个元素,返回所有可能的三元组(triple),函数签名如下:
1 | vector<vector<int>> threeSum(vector<int>& nums); |
这样,我们再泛化一下题目,不要光和为 0 的三元组了,计算和为 target 的三元组吧,同上面的 twoSum 一样,也不允许重复的结果:
1 | vector<vector<int>> threeSum(vector<int>& nums) { |
这个问题怎么解决呢?很简单,穷举呗。现在我们想找和为 target 的三个数字,那么对于第一个数字,可能是什么?nums 中的每一个元素 nums[i] 都有可能!
那么,确定了第一个数字之后,剩下的两个数字可以是什么呢?其实就是和为 target - nums[i] 的两个数字呗,那不就是 twoSum 函数解决的问题么🤔
可以直接写代码了,需要把 twoSum 函数稍作修改即可复用:
1 | /* 从 nums[start] 开始,计算有序数组 |
需要注意的是,类似 twoSum,3Sum 的结果也可能重复,比如输入是 nums = [1,1,1,2,3], target = 6,结果就会重复。
关键点在于,不能让第一个数重复,至于后面的两个数,我们复用的 twoSum 函数会保证它们不重复。所以代码中必须用一个 while 循环来保证 3Sum 中第一个元素不重复。
至此,3Sum 问题就解决了,时间复杂度不难算,排序的复杂度为 O(NlogN),twoSumTarget 函数中的双指针操作为 O(N),threeSumTarget 函数在 for 循环中调用 twoSumTarget 所以总的时间复杂度就是 O(NlogN + N^2) = O(N^2)。
这是力扣第 18 题「四数之和」:

函数签名如下:
1 | vector<vector<int>> fourSum(vector<int>& nums, int target); |
都到这份上了,4Sum 完全就可以用相同的思路:穷举第一个数字,然后调用 3Sum 函数计算剩下三个数,最后组合出和为 target 的四元组。
1 | vector<vector<int>> fourSum(vector<int>& nums, int target) { |
这样,按照相同的套路,4Sum 问题就解决了,时间复杂度的分析和之前类似,for 循环中调用了 threeSumTarget 函数,所以总的时间复杂度就是 O(N^3)。
在 LeetCode 上,4Sum 就到头了,但是回想刚才写 3Sum 和 4Sum 的过程,实际上是遵循相同的模式的。我相信你只要稍微修改一下 4Sum 的函数就可以复用并解决 5Sum 问题,然后解决 6Sum 问题……
那么,如果我让你求 100Sum 问题,怎么办呢?其实我们可以观察上面这些解法,统一出一个 nSum 函数:
1 | /* 注意:调用这个函数之前一定要先给 nums 排序 */ |
嗯,看起来很长,实际上就是把之前的题目解法合并起来了,n == 2 时是 twoSum 的双指针解法,n > 2 时就是穷举第一个数字,然后递归调用计算 (n-1)Sum,组装答案。
需要注意的是,调用这个 nSum 函数之前一定要先给 nums 数组排序,因为 nSum 是一个递归函数,如果在 nSum 函数里调用排序函数,那么每次递归都会进行没有必要的排序,效率会非常低。
比如说现在我们写 LeetCode 上的 4Sum 问题:
1 | vector<vector<int>> fourSum(vector<int>& nums, int target) { |
再比如 LeetCode 的 3Sum 问题,找 target == 0 的三元组:
1 | vector<vector<int>> threeSum(vector<int>& nums) { |
那么,如果让你计算 100Sum 问题,直接调用这个函数就完事儿了。
1 | cmd输入: |
MobaXterm是一款功能十分强大的远程控制的工具,集串口,SSH远程登录和FTP传输功能于一体,通过该软件你可以进行远程计算、显示系统网络设置、进行远程文件传输、执行网络监控,可以同时连接多个终端ip。目前软件采用了scp协议,按照ssh路径调整远程主机区域,帮助您轻松建立多个共享系统,从而可以更加方便的链接远程设备们提高工作效率。
同时MobaXterm还支持多模式连接,你可以选择全局连接,也可以选择分割式连接,方便您跟您自己的工作类型来设置相对应的远程控制模式,从而大大提升您的工作效率。除此之外,软件内建多标签和多终端分屏,采用sftp文件传输,还支持运程运行X窗口程序,以其强大的功能而深受大众的喜爱。
本文提供MobaXterm v24.3专业版下载安装教程,软件已汉化
详细安装教程参考下文操作
点击下载:MobaXterm v24.3软件包和注册机 (访问码:n8lx)

得到2个文件夹
拷贝注册机至MobaXterm目录
双击运行注册机
MobaXterm_Keygen_v1.5_By_DeltaFoX.exe


双击打开MobaXterm.exe
查看 “帮助” - “关于MobaXterm”

恭喜你,安装破解完成
1、mobexterm安装路径下,鼠标右键Mobexterm选择属性;
2、弹出窗口“兼容性”——“更改高DPI设置”;
3、在高DPI缩放替代栏,勾选“替代高DPI缩放行为。”,在缩放执行下拉列表内勾选“系统”(或系统增强)——点击“确定”完成设置。
4、重新打开Mobexterm显示恢复正常。
环境:Ubuntu20
设备:HP M1005
局域网设置静态路由表,使192.168.100.x-192.168.127.x实现跨网互访。
以下操作均使用ROOT用户身份并开启SSH登录选项。如未开启,则先手动执行以下命令开启ROOT身份的SSH选项。
1 | vim /etc/ssh/sshd_config |
接下来执行安装CUPS软件
1 | apt-get install hplip |
手动修改CUPS访问权限
1 | cupsctl --remote-admin --remote-any --share-printers |
此时,你的CUPS已经可以正常访问,在浏览器输入地址https://ip:631回车访问,**一定使用SSH的root账号密码登录**。
CUPS界面
安装hp插件
1 | hp-plugin |

如下载慢卡在0%,可下载链接内博主已经上传完毕的文件,放入/root根目录,并选择p,手动指定/root路径进行安装。下载地址(访问码:ay6x)
当提示Done并且无报错时,则表示惠普插件安装完毕。
现在,去浏览器界面找到Administration标签,点击add printert添加新的打印机。如果提示已禁止,则证明此时你使用的登录身份不是root,所以无法添加。


接下来在Local Printers选择你的打印机,并点击Continue。在下一步的页面中自定义打印机的名称,并勾选Share,否则打印机将无法被他人可见。

然后再最后这个页面选择和你打印机相同的驱动,一定选择带hpijs后缀的驱动。

然后一台打印机就展现在你的打印机列表里了,现在选择Print Test Page,看看打印机是不是响起来了!?

接下来在电脑和手机添加打印机地址,就可以实现局域网内无线打印啦!
以上就是在Ubuntu下安装CUPS使惠普打印机HP M1005实现局域网手机电脑Airprint无线打印的方法。
在使用梯子时,Clash Verge 的自定义规则可能时常不好用,经常导致 Steam 连接到国外服务器,导致国内下载很慢 / 耗流量。
本文使用 Clash Verge 2.0.3 来编写 Steam 规则。
我们可以通过 Clash 的 全局扩展脚本(通常在配置文件中名为 rule-providers 和 rules 部分)来精细控制 Steam 的走代理行为,避免它连接到国外服务器下载游戏。
在主界面找到【全局扩展脚本】,右键,编辑文件,复制下面内容覆盖原文件
1 | const prependRules = [ |
你可以将 Steam 社区和商店页面指定走代理,但下载相关域名设为直连。
这里的 DIRECT,可以替换为你所需要的,如果你想用代理下载,可以替换为你的策略组名字。
在 Clash Verge 中打开「连接」界面,观察访问 store.steampowered.com 时是否走代理,而 content.steampowered.com 是否走直连即可。
你也可以查看 Clash 的日志输出,确认每个域名是否命中预期规则。
steamcontent.com 和 steamusercontent.com,这部分建议走直连。steamcommunity.com 等社区功能如果不走代理可能无法加载头像或聊天功能。1 | #!/bin/bash |
#Hadoop基础
Hadoop 的核心组件包括 HDFS、MapReduce、YARN 以及 Hadoop Common。
| 方面 | Hadoop 1.x | Hadoop 2.x |
|---|---|---|
| 资源管理 | JobTracker 同时负责资源管理和作业调度,存在单点故障和扩展性瓶颈 | YARN 将资源管理与作业监控分离:ResourceManager + NodeManager + ApplicationMaster |
| 作业跟踪 | MapReduce 作业由 JobTracker 统一跟踪,任务过多时压力巨大 | ApplicationMaster 负责单个作业的生命周期,ResourceManager 只负责分配资源 |
| 支持框架 | 仅支持 MapReduce | 支持 MapReduce、Spark、Flink、Tez 等多种框架 |
| 扩展性 | 集群规模受限(JobTracker 内存压力),通常不超过 4000 节点 | 可扩展至上万节点,ResourceManager 可水平扩展(HA) |
| 容错 | JobTracker 故障导致所有作业失败 | ResourceManager 和 ApplicationMaster 均有 HA 方案,单点故障影响小 |
简单记忆:
1.x = HDFS + MapReduce(紧耦合,资源管理在 MapReduce 内)。
2.x = HDFS + YARN + MapReduce(YARN 独立管理资源,MapReduce 降为运行在 YARN 上的应用)。
Hadoop 主要用于解决海量数据(TB/PB 级)的存储与处理问题,适合以下场景:
不适合:低延迟随机读写(改用 HBase 或 Kudu)、实时流处理(改用 Spark Streaming/Flink)、事务性要求高的场景。
伪分布模式:所有守护进程(NameNode、DataNode、ResourceManager、NodeManager)运行在同一台机器上,但每个进程独立 JVM,模拟分布式行为。
安装 JDK(1.8 或 11)
bash
1 | sudo apt install openjdk-8-jdk # Ubuntu |
设置 SSH 免密登录(本机)
bash
1 | ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa |
下载并解压 Hadoop
bash
1 | wget https://archive.apache.org/dist/hadoop/common/hadoop-3.3.6/hadoop-3.3.6.tar.gz |
修改环境变量(~/.bashrc 或 /etc/profile)
bash
1 | export HADOOP_HOME=/usr/local/hadoop-3.3.6 |
修改 Hadoop 配置文件(位于 $HADOOP_HOME/etc/hadoop)
core-site.xml
xml
1 | <configuration> |
hdfs-site.xml
xml
1 | <configuration> |
mapred-site.xml
xml
1 | <configuration> |
yarn-site.xml
xml
1 | <configuration> |
设置 Hadoop 环境变量文件(可选 hadoop-env.sh 中指定 JAVA_HOME)
格式化 NameNode(仅首次执行)
bash
1 | hdfs namenode -format |
启动 Hadoop 服务
bash
1 | start-dfs.sh # 启动 HDFS (NameNode + DataNode) |
或一键启动 start-all.sh(已弃用,建议分开)。
验证进程
bash
1 | jps |
应看到:NameNode、DataNode、SecondaryNameNode、ResourceManager、NodeManager。
访问 Web 界面
http://localhost:9870(Hadoop 3.x)http://localhost:8088测试运行(例如执行自带 wordcount)
bash
1 | hdfs dfs -mkdir /input |
在一台或多台机器的集群安装中,通常需要修改以下 4 个核心 XML 文件(位于 $HADOOP_HOME/etc/hadoop/):
| 文件 | 作用 | 关键配置示例 |
|---|---|---|
core-site.xml |
Hadoop 核心通用配置 | fs.defaultFS(HDFS 访问地址) |
hdfs-site.xml |
HDFS 专属配置 | dfs.replication(副本数)、dfs.namenode.name.dir、dfs.datanode.data.dir |
mapred-site.xml |
MapReduce 配置 | mapreduce.framework.name(设为 yarn) |
yarn-site.xml |
YARN 资源管理配置 | yarn.resourcemanager.hostname、yarn.nodemanager.aux-services |
此外,有时还需要修改:
workers**(旧名 slaves):列出所有 DataNode 和 NodeManager 的主机名(每行一个)。hadoop-env.sh**:设置 JAVA_HOME 环境变量。yarn-env.sh**:可选的 YARN 环境变量。对于伪分布模式,
workers文件里只写localhost即可。
如果你需要更详细的安装教程(比如完全分布式集群的配置)或对每个配置项的解释,我可以进一步展开说明。
Command-line client for Quark Drive based on libquarkpan
Readme4 VersionsDependenciesDependentsSecurity
quarkpan 是基于 libquarkpan 的夸克网盘命令行工具。
它是面向直接使用终端的场景,负责把底层库能力包装成可恢复、可观察、可取消的命令行体验。
当前命令行支持:
auth 管理持久化 Cookielist 列出目录内容folder create 创建目录delete 删除一个或多个文件或目录项rename 重命名文件或目录项download 下载文件download-dir 下载整个目录upload 上传文件upload-dir 上传整个目录同时支持:
--color auto|always|never.quark.task 任务文件-c, --continue 恢复传输quarkpan 会把底层 libquarkpan 的 TLS backend feature 透传出来,命名与 reqwest 0.13 对齐,默认使用 default-tls。
示例:
1 | cargo install quarkpan |
1 | cargo install quarkpan |
1 | cargo run --bin quarkpan -- --help |
CLI 需要夸克登录后的 Cookie,支持三种方式:
--cookie 'k1=v1; k2=v2'--cookie-file ./cookie.txtQUARK_COOKIEauth set-cookie 持久化到系统配置目录Cookie 内容应为完整的 key=value; key2=value2 格式。 auth set-cookie 需要显式指定来源:
--cookie--from-stdin--from-nano--from-vi1 | quarkpan --cookie 'k1=v1; k2=v2' list |
1 | quarkpan auth set-cookie --from-stdin |
也可以显式传入:
1 | quarkpan auth set-cookie --cookie 'k1=v1; k2=v2' |
也支持通过标准输入:
1 | printf 'k1=v1; k2=v2\n' | quarkpan auth set-cookie --from-stdin |
如果直接在终端运行:
1 | quarkpan auth set-cookie --from-stdin |
CLI 会先提示:
1 | paste cookie, then press Enter: |
也支持通过编辑器:
1 | quarkpan auth set-cookie --from-nano |
1 | quarkpan --cookie 'k1=v1; k2=v2' list --pdir-fid 0 --more |
1 | quarkpan --cookie 'k1=v1; k2=v2' folder create --pdir-fid 0 --file-name 我的文档 |
1 | quarkpan --cookie 'k1=v1; k2=v2' rename --fid <fid> --file-name 新名字 |
1 | quarkpan --cookie 'k1=v1; k2=v2' delete --fid <fid1> --fid <fid2> |
1 | quarkpan --cookie 'k1=v1; k2=v2' download --fid <fid> --output ./file.bin |
1 | quarkpan --cookie 'k1=v1; k2=v2' download --fid <fid> --output ./file.bin -c |
1 | quarkpan download-dir --pdir-fid <pdir_fid> --output ./backup |
1 | quarkpan download-dir --pdir-fid <pdir_fid> --output ./backup -c |
1 | quarkpan --cookie 'k1=v1; k2=v2' upload --file ./file.bin --pdir-fid 0 |
1 | quarkpan --cookie 'k1=v1; k2=v2' upload --file ./file.bin --pdir-fid 0 -c |
1 | quarkpan upload-dir --dir ./photos --pdir-fid 0 |
1 | quarkpan upload-dir --dir ./photos --pdir-fid 0 -c |
下载和上传在中断、报错或收到 Ctrl+C 后,会保留:
1 | ${filename}.quark.task |
目录任务使用与目录同级同名的任务文件,例如:
1 | photos.quark.task |
用途:
成功完成后,任务文件会自动删除。
Ctrl+C 时:
-c 恢复进度条显示规则:
size/md5/sha1--json 输出模式1 | GPL-3.0-only |
平时开发过程中遇到的一些问题,我都会整理到文档中。有些感觉不错的,会二次整理成文章发布到我的博客中。但是有些文章如果存在隐私内容,或者不打算公开的话,就不能放在博客中了。
我的博客是使用 Hexo 来搭建的,并不能设置某些文章不可见。但如果不在电脑旁或者出门没有带电脑又想要查看一下之前记录的内容,就很不方便了。
我也尝试在 github 上去找一些可以设置账户的开源的博客框架,但测试过一些后发现并没有符合自己需求的,而自己开发却没有时间。
思来想去,就想看看有没有插件能够实现 Hexo 博客的加密操作。最终让我找到了一款名为 Hexo-Blog-Encrypt 的插件。
为了防止以下的修改可能出现版本差异,这里我先声明我使用的 Hexo 版本信息:
1 | hexo: 4.2.1 |
1 | npm install --save hexo-blog-encrypt |
该插件的使用也很方便,这里我仅作简单介绍,详细的可以查看官方文档。 D0n9X1n/hexo-blog-encrypt: Yet, just another hexo plugin for security.
要为一篇文章添加密码查看功能,只需要在文章信息头部添加 password 字段即可:
1 | --- |
分别为每篇文章设置密码,虽然很灵活,但是配置或者修改起来非常麻烦。为此,可以通过设置统一配置来实现全局加密。
通过添加指定 tag 的方式,可以为所有需要加密的文章添加统一加密操作。只需要在需要加密的文章中,添加设置的 tag值 即可。
在Hexo主配置文件 _config.yml 中添加如下配置:
1 | # Security |
之后,需要清除缓存后重新生成 hexo clean && hexo s -g。
其中的 tag 部分:
1 | tags: |
表示当在文章中指定了 private 这个 tag 后,该文章就会自动加密并使用对应的值 hello 作为密码,输入密码后才可查看。
相应的文章头部设置:
1 | --- |
可能有这样的情况,属于 private 标签下的某篇文章在一段时间内想要开放访问。如果在描述中加上密码提示: 当前文章密码为xxx,请输入密码后查看 ,来让用户每次查看时都要先输入密码后再查看,这样的操作又会给访客带来不便。
这时可以单独设置允许某篇文章不设置密码。
只需要在使用 加密tag 的前提下,结合 password 来实现即可。在博客文章的头部添加 password 并设置为 "" 就能取消当前文章的 Tag 加密。
相应的设置示例如下:
1 | --- |
在全局加密配置下,我们可以通过设置多个 加密tag 来为多篇不同类型的文章设置相同的查看密码:
1 | tags: |
那么可能有这样的场景:
属于 private 标签下的某篇文章想要设置成不一样的密码,防止用户恶意通过一个密码来查看同标签下的所有文章。此时,仍可以通过 password 参数来实现:
1 | --- |
说明:
该文章通过tag值 private 做了加密,按说密码应该为 hello ,但是又在信息头中设置了 password ,因为配置的优先级是 文章信息头 > 按标签加密,所以最后的密码为 buyiyang 。
在为某些文章设置了 加密后查看 之后,不经意间发现这些文章的目录在解密后却不显示了。
从插件的 github issues 中我找到了相关的讨论:
原因:
加密的时候,
post.content会变成加密后的串,所以原来的TOC生成逻辑就会针对加密后的内容。
所以这边我只能把原来的内容存进post.origin字段。
找到文件 themes/next/layout/_macro/sidebar.swig ,编辑如下部分:
插件 hexo-blog-encrypt 对文章内容进行加密后,会将原始文章内容保存到字段 origin 中,当生成 TOC 时,我们可以通过 page.origin 来得到原始内容,生成文章目录。
相应的代码为:
1 | <aside class="sidebar"> |
修改完成后,执行 hexo clean && hexo s -g 并重新预览。
效果如下:
不过,这样的效果貌似不是我想要的。我理想中的效果应该是:
站点概览 部分,不需要看到 文章目录 部分。站点概览 和 文章目录 两部分。而现在加密后的文章未解密之前也可以看到 文章目录 ,虽然该目录不可点击。
当然,如果你不是很介意,那么到这里就可以结束了。如果你和我一样有一些 追求完美的强迫症 的话,我们继续。
查看了 hexo-blog-encrypt 相关的 issues ,我找到了一种 折中 的解决方法。
从 issue Archer主题解密后TOC依旧不显示(已按手册修改) 中我们可以知道:
我们可以在文章加密的前提下,通过将目录部分加入到一个 不可见的div 中来实现 隐藏目录 的效果。在源码中的 hexo-blog-encrypt/lib/hbe.js 部分我们也可以看到,解密后通过设置 id 值为 toc-div 的元素为 display:inline 来控制显示隐藏。
1 | {%- if (page.encrypt) %} |
对文件 themes/next/layout/_macro/sidebar.swig 修改后的代码如下:
1 | <!--noindex--> |
但这种方法并不是完全的加密,而是采用 障眼法 的方式,通过查看html源文件还是可以看到目录内容的,只是不显示罢了。
对于这个问题,hexo-blog-encrypt 插件的作者也作了说明:next 主题内没有 article.ejs 文件【TOC 相关】 · Issue #162 · D0n9X1n/hexo-blog-encrypt
因为该插件中目前只有一个参数 page.encrypt 可以用来判断当前的文章是否进行了 加密处理 ,而不能获知该文章当前是处于 加密后的锁定 状态,还是处于 加密后的解锁 状态。如果再有一个参数结合起来一起处理就好了。
所以,目前只能在解锁前隐藏目录,解锁后再显示目录。但在解锁前目录区域还是会展开,只是没有内容显示罢了。
类似于我的博客文章列表中的 文章置顶 的提示效果,考虑在文章列表中对加密的文章增加类似的 加密 提示信息。
上面对于文章的加密处理,一方面是在 配置文件 中添加的 tag 全局配置,另一方面是在单个 md源文件 中添加的 password 参数。所以我们需要对这两种情况分别做处理。
针对于 password 字段,参考获取其他字段的方法,比如获取标题用 post.title ,获取置顶用 post.top ,那么获取 password 就是 post.password 了。
可以参考我之前添加置顶提示信息的操作,对文件 themes/next/layout/_macro/post.swig 的修改如下:
1 | {# 加密文章添加提示信息-for password #} |
针对于 tag 标签的获取,可以从文件 themes/next/layout/_macro/post.swig 中找到类似的处理方法:
1 | {%- for tag in post.tags.toArray() %} |
即可以用最简单的 遍历法 来处理:
我们获取到配置文件中设置的所有 加密tag值 ,再找到文章中的 tag标签 。二者一对比,有匹配的项则说明该文章设置了 tag值 加密。
要在 .swig 文件中实现相应的对比逻辑,就需要了解其使用的语法格式。而对于 swig 文件,使用的是 Swig 语法。
Swig是一个非常棒的、类似Django/jinja的node.js模板引擎。
不过看到这个代码库 paularmstrong/swig: Take a swig of the best template engine for JavaScript. 已经 归档 了。
但因为 Swig 是类似于 jinja 的模板引擎,那么我们直接去参考 jinja 的语法就可以了。
获取全局配置中 encrypt.tags 的值:
1 | {%- if (config.encrypt) and (config.encrypt.tags) %} |
在文章列表中获取当前文章包含的 tags 列表:
1 | {%- if post.tags %} |
对于其中展示的文本格式,可以参考已有的 发表于 更新于 这些副标题的格式来实现。
例如:
1 | <span class="post-meta-item"> |
对其进行优化,我们只需要显示提示文字,不需要后面的带下划线部分,最终得到的就是:
1 | <span class="post-meta-item"> |
整合上面的代码,对于文章中包含 password 的文档,通过如下方式来显示:
相应代码:
1 | {# 加密文章添加提示信息-for password #} |
对于文章中包含指定加密 tags 的文档,通过如下方式来显示:
相应代码:
1 | {# 加密文章添加提示信息-for config tags #} |
对于两种都有的文档,我们只需要通过一个 判断 来处理就好了:优先判断文档中的 password 字段。当文档中包含 password 时,就说明是加密文章;否则就去判断配置文件看是否为加密文章。
最后的代码为:
1 | {# 加密文章添加提示信息-for password #} |
稍微不好的一点就是,上面的操作是通过 两个for循环 来处理的,会导致一些性能问题。不过这个操作是在编译过程 hexo g 的时候来处理的,不影响博客浏览,也就可以忽略了。
对于需要显示的图标,可以从网站 Icons | Font Awesome 中获取。
例如,我这里选择的是 锁 的icon图标,得到的代码如下:
1 | <i class="fas fa-lock"></i> |