点击查看更新记录

更新记录

2020-12-28:起草教程

  1. 添加参考教程内容
  2. 添加TODO
  3. 添加文档简析和基础示例

2020-12-29:第一版编写完成

  1. 添加初级应用
  2. 添加具体案例
点击查看参考教程
参考方向教程原贴
参考了标签基础写法Hexo开发文档-Tag
参考了内置辅助函数的用法Hexo开发文档-辅助函数
参考stylus的基本写法stylus官方文档
Atom的css转stylus插件

简单介绍

Hexo有提供外挂标签的API介绍文档。首先我们要了解什么是外挂标签。它的实质其实就是简化Html的写法,把大片重复的内容交给Hexo编译,我们只需要在外挂标签内提供必要的参数即可。这也是我一度钟爱外挂标签的原因。毕竟很方便,可以拿来偷懒嘛。本帖提供的是一些较为简单的外挂标签写法。更加精深的内容可以参考官方开发文档和现有的外挂标签脚本。本站现有的外挂标签写法基本都已经集成在这篇教程中:

教程正文

此处声明一下开发原则。
外挂标签的编译函数属于Hexo内部函数,所以应该放在scripts文件夹下。
千万不要放在source/js/目录下,然后用inject引入的外部函数引用方法。
本帖的开发原则是将标签函数脚本放在[Blogroot]\themes\butterfly\scripts\tag\目录下。
以下如无另外声明,一律都是放在这个目录了。

文档剖析

点击查看文档剖析

首先来看一个最简单的标签函数结构。

1
2
hexo.extend.tag.register('name', function(args, content){
}, options);

  1. name:表示外挂标签的名字,为字符串,为了避免和之后会提到的参数处理函数名混淆,建议用''包裹。
  2. args:外挂标签传入的参数,可以是一个包含多个参数的字符串,之后再用分割函数处理成数组。
  3. content: 外挂标签涵盖的内容。
  4. options: 标签函数的参数,有endsasync
    • ends:决定是否使用结束标签,此选项默认为false
      如果为true,则需要添加形似endname的结束标签。
      注意,只有ends设为true时,content参数才有效。适用于需要在外挂标签内嵌套外挂标签或者markdown语法的情况。
    • async:决定是否开启非同步渲染模式,此选项默认为false
      它用于决定是否开启在hexo s预览时对外挂标签进行同步渲染。
      如设为false则开启同步渲染。所以建议尽量不要去改它。

如果是示例中这样的写法的话,他的外挂标签函数以及对应的外挂标签应该是:

  1. endsfalse的情况,此时不存在content参数,所以没必要写了。

    1
    2
    3
    4
    5
    //标签函数结构
    hexo.extend.tag.register('name', function(args){
    });
    //对应的外挂标签写法
    {% name args %}
  2. endstrue的情况,此时content参数有效。

    1
    2
    3
    4
    5
    //标签函数结构
    hexo.extend.tag.register('name', function(args, content){
    },{ends:true});
    //对应的外挂标签写法
    {% name args %}content{% endname %}

简单示例

点击查看简单示例
  1. ends为false的情况:

    1
    2
    3
    hexo.extend.tag.register('kbd', function(args) {
    return `<kbd>${args.join(' ')}</kbd>`;
    });
    • 则标签函数写法为
      1
      {% kbd args %}
    • 会被编译成
      1
      <kbd>args</kbd>
  2. ends为true的情况:

    1
    2
    3
    hexo.extend.tag.register('tip',function tip (args, content) {
    return `<div class="tip ${args.join(' ')}">${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div>`
    }, { ends: true })

    这个函数也可以写成如下形式,这样更符合开发体验:

    1
    2
    3
    4
    5
    6
    //参数处理函数
    function tip (args, content) {
    return `<div class="tip ${args.join(' ')}">${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div>`
    }
    //标签注册函数
    hexo.extend.tag.register('tip',tip, { ends: true })
    • 则标签函数写法为
      1
      {% tip args %}content{% endtip %}
    • 会被编译成
      1
      <div class="tip args">content</div>
      此处的args可以是一个字符串,例如args='warning fa fa-icon'
      ${hexo.render.renderSync({ text: content, engine: 'markdown' })}表示使用markdown语法来编译处理content的内容。
      所以content可以是任何markdown语法兼容的内容,乃至其他外挂标签。
      更多辅助函数内容请参阅Hexo开发文档-辅助函数

初级应用

点击查看初级应用

从上文的介绍来看,想必各位已经了解了基本用法,此处建议开发者采用如下方案进行标签函数的编写。将整个标签函数分为参数处理函数标签注册函数

1
2
3
4
5
6
7
8
9
//参数处理函数
function poem (args, content) {
args = args.join(' ').split(',')
let p0 = args[0]
let p1 = args[1]?args[1]:''
return `<div class='poem'><div class='poem-title'>${p0}</div><div class='poem-author'>${p1}</div>${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div>`
}
//标签注册函数
hexo.extend.tag.register('poem',poem,{ ends: true });
  1. args = args.join(' ').split(',')表示对字符串args做分割处理,使用,作为分割标记,然后强制转换成数组。
    例如
    1
    2
    3
    4
    5
    6
    7
    //原本
    args='a,ab,abc,abcd'
    //运行args = args.join(' ').split(',')后
    args=[a,ab,abc,abcd]
    //此时
    args[0]='a' args[1]='ab' ......
    //以此类推,要注意数组是从0开始计数的
  2. 这里的let p1 = args[1]?args[1]:''javascript的三元运算符。
    • 语法为:条件表达式?表达式1:表达式2
    • 说明:问号前面的位置是判断的条件,判断结果为布尔型,为true时调用表达式1,为false时调用表达式2。
    • 使用这个方式,我们可以配置对应参数的默认值。
      (因为分割好的数组args的实质是个动态数组,所以未取到的值应该为空null,如果转化成布尔型的话,就是false)

具体案例

点击查看具体案例

例如我要将iconfontsymbol引用法做成外挂标签。
具体教程内容详见:

  1. 首先我们需要提取三个要素,

    • 最终的HTML结构,我们需要参考它来编写参数处理函数;例如本次的最终结构是
      1
      2
      3
      <svg class="icon" aria-hidden="true">
      <use xlink:href="#icon-xxx"></use>
      </svg>
    • 需要引入的样式依赖(可能是js也可能是css或者两者都有,常规inject即可,添加样式不是本帖的主要内容,所以不做赘述);
    • 可能用到的具体参数(例如本次案例中,图标名称图标大小都可以作为参数参考值)。
  2. 其次需要确定我们需要的外挂标签样式。因为只是图标,所以应该不需要content内容了,因此采用ends: false的编写方式。并且要用到两个参数,一个是图标名称,一个是图标大小。

    1
    {% icon [icon-xxxx],[font-size] %}
  3. 然后就可以根据这些信息编写参数处理函数,此处提供一个小技巧,可以用内联样式来引入一些特定参数,比如此处的图标大小

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //参数处理函数
    function iconFont(args) {
    //使用逗号分割参数字符串,得到多个参数
    args = args.join(' ').split(',')
    let p0 = args[0]
    // 使用三元运算符设置字体大小的默认值
    let p1 = args[1]?args[1]:1
    //用style="..."的内联样式写法添加特定参数
    return `<svg class="icon" style="width:${p1}em; height:${p1}em" aria-hidden="true"><use xlink:href="#${p0}"></use></svg>`;
    }
    //标签注册函数
    hexo.extend.tag.register('icon',iconFont);
  4. 然后按照上述写法,可以得到最后的编译结果,假定我设置图标为icon-rat,图标大小为5

    1
    2
    3
    4
    5
    6
    <!-- 外挂标签结构 -->
    {% icon icon-rat,5 %}
    <!-- 编译好的HTML结构 -->
    <svg class="icon" style="width:5em; height:5em" aria-hidden="true">
    <use xlink:href="#icon-rat"></use>
    </svg>