个性化的内容越来越多,About页面放不下了,于是决定单独写一篇文章记录本博客的配置
主题
NexT.Gemini
不建议用npm安装,因为那样没法魔改。所以一如既往的直接clone就可以了。
背景图片(ribbon)
本来打算上传背景的,但是图片太大了,最后采用了动态生成的ribbon。
在博客的_config.yml,把canvas_ribbon的enable设置成true。
但是原版的ribbon.js有个小问题,就是如果在手机上点击,会连续刷新两次背景。看了一眼代码,问题出在这儿。
1 2 document .onclick = redraw;document .ontouchstart = redraw;
因为不喜欢背景频繁变动,我把这两行给删了,同时也就不能用CDN提供的js文件了。
好在hexo允许自行配置vendors。在next的_config.yml里头找到vendors项目,然后加入下面内容(注意改成自己的js文件路径)
1 2 # 这里js文件被我放在 next\source\js\ribbon.min.js canvas_ribbon: /js/ribbon.min.js
显示hexo和next版本号
页脚显示版本号这个特性在v7的next主题是有的,但是v8给去掉了。我个人比较喜欢这个特性,于是琢磨了半天nunjucks,把显示版本号给魔改回来了。
在footer.njk中把对应内容替换成下面这些~
1 2 3 4 5 6 7 8 9 10 11 12 13 {%- if theme.footer.powered %} <div class ="powered -info "> <span class ="post -meta -item "> {{- __ ('footer.powered' , next_url ('https://hexo.io' , 'Hexo' , {class : 'theme-link' }) + ' v' + hexo_version) }} </span> <span class ="post -meta -item "> {%- set next_site = 'https://theme-next.js.org' if theme.scheme === 'Gemini' else 'https://theme-next.js.org/' + theme.scheme | lower + '/' %} {{- __ (' 主题 – ' + next_url (next_site, 'NexT.' + theme.scheme, {class : 'theme-link' }) + ' v' + next_version) }} </span> </div> {%- endif %}
然后在locals.js替换下面内容
1 2 3 4 5 6 7 const { version, config } = hexo;locals.hexo_version = version;
版权信息和字数统计并排
这个也是v7的next主题有的特性,升级到v8又给改没了。。。
此布局也已恢复在当前主题中;关闭版权信息时,字数统计仍会单独显示。
这个改起来就很简单了,无非就是把字数统计的span放到版权信息的div里头,如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <div class ="copyright "> {%- set copyright_year = date (null , 'YYYY' ) %} © {% if theme.footer.since and theme.footer.since != copyright_year %}{{ theme.footer.since }} – {% endif %} <span itemprop="copyrightYear" >{{ copyright_year }}</span> <span class ="with -love "> <i class =" {{ theme.footer.icon.name }}"></i> </span> <span class=" author" itemprop=" copyrightHolder">{{ theme.footer.copyright or author }}</span> {%- if config.symbols_count_time.total_symbols or config.symbols_count_time.total_time %} {%- if config.symbols_count_time.total_symbols %} <span class=" post-meta-item"> <span class=" post-meta-item-icon"> <i class=" fa fa-chart-line"></i> </span> {%- if theme.symbols_count_time.item_text_total %} <span>{{ __('symbols_count_time.count_total') + __('symbol.colon') }}</span> {%- endif %} <span title=" {{ __ ('symbols_count_time.count_total' ) }}">{{ symbolsCountTotal(site) }}</span> </span> {%- endif %} {%- if config.symbols_count_time.total_time %} <span class=" post-meta-item"> <span class=" post-meta-item-icon"> <i class=" fa fa-coffee"></i> </span> {%- if theme.symbols_count_time.item_text_total %} <span>{{ __('symbols_count_time.time_total') }} ≈</span> {%- endif %} <span title=" {{ __ ('symbols_count_time.time_total' ) }}">{{ symbolsTimeTotal(site, config.symbols_count_time.awl, config.symbols_count_time.wpm, __('symbols_count_time.time_minutes')) }}</span> </span> {%- endif %} {%- endif %} </div>
页面载入动画速度
v8 不再使用 anime.js,动画序列改由 motion.js 中的 integrator 调度。文章列表默认使用 overlap: 100 错峰启动;把它改为 200(与默认 motion.duration 相同),就能让列表中的动画同时启动,减少逐项出现的等待感。当前主题已应用此修改。
1 2 3 4 5 6 7 sequence.push ({ targets, complete : () => targets.classList .add ('animated' , animation), overlap : 200 });
overlap 控制的是动画项的启动间隔,不是单项动画的播放时长。单项视觉动画的时长由 Animate.css 控制;如果要缩短淡入等效果本身,还需要调整 Animate.css 的动画时长。
字数统计和阅读时长
hexo-word-counter
版本:v0.1.0
代码块不计入字数(exclude_codeblock: true)
注意:安装完之后一定要执行hexo clean!
阅读进度条
next主题的_config.yml里找到Reading progress bar开启
首页隐藏分类(比如公告)
hexo-generator-index2
分页页码省略
首页及归档、分类、标签页的分页由 themes/next/scripts/helpers/next-paginator.js 调用 Hexo paginator 生成。默认中间页码显示范围较窄,页数较多时会以省略号代替部分页码。
通过按总页数设置 show_all,可以让总页数不超过 5 页时显示全部页码;超过 5 页时继续使用原有省略方式:
1 show_all : this .page .total <= 5 ,
禁用更新日期
next主题的_config.yml > post_meta > updated_at > enable: false
全英语链接
全英语链接方便搜索引擎收录,这里简单修改hexo站点的_config.yml即可,下面给出本博客的配置
我的.md文件名都是英语,所以URL > permalink可以设置为:category/:title.html
文章的类别大多都是中文名,可以通过Category & Tag > category_map进行映射
1 2 3 4 5 6 :category/:title.html category_map: 技术: tech
图片相关
图床(GitHub)
图床我直接使用的 GitHub,新建一个 repo,然后开启 GitHub Page(Settings > Pages)。Branch 选择 main,path 选择 root(根目录)。
然后就可以通过下面方式访问图片了。
1 2 # 假设图片放在 repo 的 img 文件夹里 
图片延迟加载(lazyload)
lazyload就是延迟加载,只有在看到图片的时候才加载,从而加快网页载入速度。
注:构建仍会显示 NexT 关于 lazyload 已弃用的警告,但当前实现有效
在 next 主题的 _config.yml 中启用 lazyload。当前实现会在 Markdown 图片转成 HTML 时处理文章和独立页面中的图片。
需要排除的图片可在 lazyload_exclude 中填写其 src 的一段文本;匹配是逐张图片进行的,不会因为某张图片命中就跳过整篇文章。比如 osu-sig 会让 About 页面上的 osu 统计图片保持原样。
其他图片会先显示加载占位图,再由 lozad 加载原图。下面是当前 themes/next/scripts/filters/post.js 的完整内容(替换该文件即可);占位图地址可在 placeholderUrl 中修改。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 'use strict' ;const { unescapeHTML } = require ('hexo-util' );const placeholderUrl = 'https://oscarcx.com/hexo_resource/img/loading_cow.png' ;function lazyloadImages (content, exclude ) { return content.replace (/<img\b[^>]*>/ig , image => { if (/\sdata-src\s*=/i .test (image)) return image; return image.replace (/\ssrc=(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i , (attribute, doubleQuoted, singleQuoted, unquoted ) => { const src = doubleQuoted ?? singleQuoted ?? unquoted; if (exclude && src.includes (exclude)) return attribute; return ` src="${placeholderUrl} " data-src="${src} "` ; }); }); } hexo.extend .filter .register ('after_render:html' , (html, locals ) => { const { lazyload, lazyload_exclude } = hexo.theme .config ; const content = locals.page ?.content ; if (!lazyload || typeof content !== 'string' || !content) return html; const images = content.match (/<img\b[^>]*>/ig ) || []; return images.reduce ((result, image ) => { const lazyImage = lazyloadImages (image, lazyload_exclude); return lazyImage === image ? result : result.replace (image, lazyImage); }, html); }); hexo.extend .filter .register ('after_post_render' , data => { const { config } = hexo; const theme = hexo.theme .config ; if (!theme.exturl && !theme.lazyload ) return ; if (theme.lazyload ) { data.content = lazyloadImages (data.content , theme.lazyload_exclude ); } if (theme.exturl ) { const siteHost = URL .parse (config.url )?.hostname || config.url ; const exturlIcon = theme.exturl_icon ? '<i class="fa fa-external-link-alt"></i>' : '' ; data.content = data.content .replace (/<a[^>]*\shref="([^"]+)"[^>]*>([^<]+)<\/a>/ig , (match, href, html ) => { if (!href) return match; const link = URL .parse (href); if (!link?.protocol || link.hostname === siteHost) return match; const title = match.match (/title="([^"]+)"/ ); const encoded = Buffer .from (unescapeHTML (href)).toString ('base64' ); if (title) return `<span class="exturl" data-url="${encoded} " title="${title[1 ]} ">${html} ${exturlIcon} </span>` ; return `<span class="exturl" data-url="${encoded} ">${html} ${exturlIcon} </span>` ; }); } }, 0 );
配置如下:
1 2 3 4 lazyload: true lazyload_exclude: osu-sig
图片缩放(mediumzoom)
mediumzoom是一个点击放大图片的插件,挺实用的。
next主题的_config.yml,把mediumzoom设置成true
黑幕(spoiler)
文字模糊处理,点击可见(比如练习题答案)
插件项目地址:unnamed42/hexo-spoiler
安装:npm install hexo-spoiler --save(在博客根目录使用)
使用方式如下所示
1 2 {% spoiler text %} {% spoiler option:value text... %}
渲染引擎(renderer)
把 hexo 自带的 hexo-renderer-marked 卸载了,现在使用的是 hexo-renderer-markdown-it-plus
配置如下所示:
1 2 3 markdown_it_plus: typographer: false quotes: “”‘’
typographer 这个功能是默认开启的,会在渲染过程中,自动把所有的英语引号全部换成中文引号。具体解释可以看 6.4.0版本之后的两个问题 。
可以把下面两行复制到文章中进行测试,如果左右渲染出来一样,就是被自动替换了。
'(U+0027) ---> ’(U+2019)
"(U+0022) ---> “(U+201C) + ”(U+201D)
所以只需要 typographer: false 就能禁用这个坑爹的功能
公式显示
直接使用 katex,体积小,而且支持公式的自适应换行,安装方法见这篇官方教程:Math Equations | NexT 。
hexo 自带的renderer 不支持 katex,所以我安装的是升级版 hexo-renderer-markdown-it-plus 。
折叠块
本来想自己手搓一个的,发现有人已经写过,效果还不错,就不重复造轮子啦
插件:hexo-content-blocks
需要在所有页面共用的 <head> 布局中加载插件样式。本博客使用 NexT v8,对应文件为 themes/next/layout/_partials/head/head.njk。在主样式表引用后添加:
1 2 3 {%- if config.content_blocks.enable %} <style type="text/css">{{ content_blocks_css() }}</style> {%- endif %}
Hexo 根目录 _config.yml 中还需要启用插件并配置折叠块类型;本博客已有 content_blocks 配置。插件的完整选项见 hexo-content-blocks README 。
效果如下:
我是折叠块
效果还不错吧~
其它改动
微调行距,字体大小等,并且在移动端也显示目录
全部统一放在 source\_data\styles.styl
然后把next主题的_config.yml的这部分取消注释就可以了。写在这个文件里的css会被添加到末尾,所以可以直接覆盖默认样式。
1 2 3 4 5 # Define custom file paths. # Create your custom files in site directory `source/_data` and uncomment needed files below. custom_file_path: (省略若干) style: source/_data/styles.styl