4

I am trying to create tabbed code-blocks (as a tag plugin) in hexo but I cannot figure out where to put my js function. I thought I could load the function using the js helper but I don't know where to include the helper. I tried, and failed, to add it into the tag plugin. This is the tag plugin code (saved as testtag.js):

hexo.extend.tag.register('testtag', function(args, content){
  var className =  args.join(' ');

  var result = '';
  result += "<\%- js('\\themes\\bootstrap-blog\\scripts\\tab.js') \%>"
  result += '<div class="tabs">';
  result += '<ul>';
  result += '<li class="li_tab1" onclick="tab(&apos;tab1&apos;)"><a>Tab 1</a></li>';
  result += '<li class="li_tab2" onclick="tab(&apos;tab2&apos;)"><a>Tab 2</a></li>';
  result += '</ul>';
  result += '<div class="contentarea">';
  result += '<div id="tab1">';
  result += '<p>' + content + '</p>';
  result += '</div>';
  result += '<div id="tab2" style="display: none;">'
  result += '<p>This is the text for tab 2.</p>'
  result += '</div>'
  result += '</div>'
  result += '</div>'

  return result;

}, {ends: true});

which does work. However, the onclick event of the tags just raises the error that it can't find the tab function. Note that the first line of result above was my failed attempt to use the helper.

This is my tab function, tab.js:

function tab(tab) {
document.getElementById('tab1').style.display = 'none';
document.getElementById('tab2').style.display = 'none';
document.getElementById('li_tab1').setAttribute("class", "");
document.getElementById('li_tab2').setAttribute("class", "");
document.getElementById(tab).style.display = 'block';
document.getElementById('li_'+tab).setAttribute("class", "active");
}

Both tab.js and testtag.js as saved in the *\themes\bootstrap-blog\scripts* folder.

I saw this answer which I though might help but I can't figure out what a view is. I couldn't find anything about views in the Hexo docs.

4

2 回答 2

9

你的代码中有太多错误,所以我更愿意给你一个完整的例子和解释。

这是我们需要的:

  1. 用于构建此多个代码块的 HTML 结构的自定义标记
  2. 用于样式化代码块和代码着色的 CSS 文件
  3. 用于为代码块设置动画的 JS 脚本(选项卡)

自定义标签:m_codeblock(JS服务器端)

我们需要允许用户定义:

  • 名称或链接
  • 此选项卡中有多个代码块,因此我们定义了一个标签来分隔并列出每个选项卡

这是语法:

{% m_codeblock [name] [link] %}
    <!-- tab [lang] -->
        source_code
    <!-- endtab -->
{% endm_codeblock %}

和一个例子:

{% m_codeblock stack overflow https://example.fr %}
    <!-- tab html -->
        <html>
            <body>
                <h1>Hey dan</h1>
            </body>
        </html>
    <!-- endtab -->
    <!-- tab css -->
        h1 {
            color:red;
        }
    <!-- endtab -->
{% endm_codeblock %}        

在您的博客文件夹(不是主题文件夹)中安装这些依赖项:

  • npm install jsdom --save
  • npm install jquery --save

这是这个自定义标签的源代码themes/theme_name/scripts/m_codeblock.js

'use strict';

var util = require('hexo-util');
var highlight = util.highlight;
var stripIndent = require('strip-indent');
var rCaptionUrl = /(\S[\S\s]*)\s+(https?:\/\/)(\S+)/i;
var rCaption = /(\S[\S\s]*)/;
var rTab = /<!--\s*tab (\w*)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g;

// create a window with a document to use jQuery library
require("jsdom").env("", function(err, window) {
    if (err) {
        console.error(err);
        return;
    }

    var $ = require("jquery")(window);

    /**
     * Multi code block
     * @param args
     * @param content
     * @returns {string}
     */
    function multiCodeBlock(args, content) {
        var arg = args.join(' ');
        // get blog config
        var config = hexo.config.highlight || {};

        if (!config.enable) {
            return '<pre><code>' + content + '</code></pre>';
        }

        var html;
        var matches = [];
        var match;
        var caption = '';
        var codes = '';

        // extract languages and source codes
        while (match = rTab.exec(content)) {
            matches.push(match[1]);
            matches.push(match[2]);
        }
        // create tabs and tabs content
        for (var i = 0; i < matches.length; i += 2) {
            var lang = matches[i];
            var code = matches[i + 1];
            var $code;
            // trim code
            code = stripIndent(code).trim();
            // add tab
            // active the first tab
            if (i == 0) {
                caption += '<li class="tab active">' + lang + '</li>';
            }
            else {
                caption += '<li class="tab">' + lang + '</li>';
            }
            // highlight code
            code = highlight(code, {
                lang: lang,
                gutter: config.line_number,
                tab: config.tab_replace,
                autoDetect: config.auto_detect
            });
            // used to parse HTML code and ease DOM manipulation
            // display the first code block
            $code = $('<div>').append(code).find('>:first-child');
            if (i == 0) {
                $code.css('display', 'block');
            }
            else {
                $code.css('display', 'none');
            }

            codes += $code.prop('outerHTML');
        }
        // build caption
        caption = '<ul class="tabs">' + caption + '</ul>';
        // add caption title
        if (rCaptionUrl.test(arg)) {
            match = arg.match(rCaptionUrl);
            caption = '<a href="' + match[2] + match[3] + '">' + match[1] + '</a>' + caption;
        }
        else if (rCaption.test(arg)) {
            match = arg.match(rCaption);
            caption = '<span>' + match[1] + '</span>' + caption;
        }
        codes = '<div class="tabs-content">' + codes + '</div>';
        // wrap caption
        caption = '<figcaption>' + caption + '</figcaption>';
        html = '<figure class="highlight multi">' + caption + codes + '</figure>';
        return html;
    }

    /**
     * Multi code block tag
     *
     * Syntax:
     *   {% m_codeblock %}
     *   <!-- tab [lang] -->
     *       content
     *   <!-- endtab -->
     *   {% endm_codeblock %}
     * E.g:
     *   {% m_codeblock %}
     *   <!-- tab js -->
     *       var test = 'test';
     *   <!-- endtab -->
     *   <!-- tab css -->
     *       .btn {
     *           color: red;
     *       }
     *   <!-- endtab -->
     *   {% endm_codeblock %}
     */
    hexo.extend.tag.register('m_codeblock', multiCodeBlock, {ends: true});
});

阅读评论以了解代码。

您需要做的就是将您的 JavaScript 文件放在scripts文件夹中,Hexo 将在初始化期间加载它们。

风格化代码块

默认情况下,仅显示第一个选项卡而隐藏其他选项卡,我们在此处的自定义标记源代码中执行此操作:

$code = $('<div>').append(code).find('>:first-child');
if (i == 0) {
  $code.css('display', 'block');
}
else {
  $code.css('display', 'none');
}

所以你只需要更多的 CSS 来改进用户界面和代码着色。将此文件放入theme/theme_name/assets/css/style.css并将其链接到布局。

动画代码块(JS客户端)

我们需要一些 javascript 来为标签设置动画。当我们单击一个选项卡时,所有选项卡内容必须隐藏,只显示右侧选项卡。将此脚本放入theme/theme_name/assets/js/script.js并将其链接到布局。

$(document).ready(function() {
  $('.highlight.multi').find('.tab').click(function() {
    var $codeblock = $(this).parent().parent().parent();
    var $tab = $(this);
    // remove `active` css class on all tabs
    $tab.siblings().removeClass('active');
    // add `active` css class on the clicked tab
    $tab.addClass('active');
    // hide all tab contents
    $codeblock.find('.highlight').hide();
    // show only the right one
    $codeblock.find('.highlight.' + $tab.text()).show();
  });  
});

你的问题是构建这个自定义标签的机会,我将把它集成到我开发的下一个版本的 hexo 主题(Tranquilpeak)中。

结果如下: 结果

JSFiddle上实时检查

于 2016-03-02T14:18:18.623 回答
0

您还可以创建由父级读取的内部标签。

{% code_with_tabs %}
  {% code js title="something" class_name="info" %}
    1. aosjaojsdoajsdoajsd
  {% endcode %}
  {% code js title="something" class_name="info" %}
    2. aosjaojsdoajsdoajsd
  {% endcode %}
{% endcode_with_tabs %}

并使用解析器读取生成的内部 HTML。

于 2016-06-06T08:15:18.993 回答