Matery之代码块优化


前言

  在官方最新版本的Matery主题版本中已经优化了代码块的问题,但在旧版本Hexo主题Matery中对hexo-prism-plugin只支持高亮显示,而且存在着许多的BUG。比如新版本的hexo-prism-plugin已经支持了代码块的一键复制和收缩功能,如果不手动对旧版本Matery原有的代码做改动,则代码块显示会存在一些问题。

代码块优化

1. 安装代码块插件

npm i -S hexo-prism-plugin

2. Hexo根目录配置

打开Hexo根目录的配置文件_config.yml,修改并添加如下代码

highlight:
  enable: false # 关闭原有的高亮代码

# 添加prism_plugin配置项
prism_plugin:
  mode: 'preprocess'    # realtime/preprocess
  theme: 'tomorrow'
  line_number: true    # default false
  custom_css: 

3. Matery主题根目录

打开Matery主题的配置文件themes\matery\_config.yml,添加如下代码

code:
  lang: true # 代码块是否显示名称
  copy: true # 代码块是否可复制
  shrink: true # 代码块是否可以收缩
  break: false # 代码是否折行

4. 代码块CSS优化

打开themes\source\css\matery.css,大概在100到200行左右,修改代码块CSS样式如下

pre {
    padding: 1.5rem 1.5rem 1.5rem 3.3rem !important;
    margin: 1rem 0 !important;
    background: #272822;
    overflow: auto;
    border-radius: 0.35rem;
    tab-size: 4;
}
.code-area::after {
    content: " ";
    position: absolute;
    border-radius: 50%;
    background: #ff5f56;
    width: 12px;
    height: 12px;
    top: 0;
    left: 12px;
    margin-top: 12px;
    -webkit-box-shadow: 20px 0 #ffbd2e, 40px 0 #27c93f;
    box-shadow: 20px 0 #ffbd2e, 40px 0 #27c93f;
}
code {
    padding: 1px 5px;
    top: 13px !important;
    font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier, monospace;
    font-size: 0.91rem;
    color: #e96900;
    background-color: #f8f8f8;
    border-radius: 2px;
}
.code_copy {
    position: absolute;
    top: 0.7rem;
    right: 25px;
    z-index: 1;
    filter: invert(50%);
    cursor: pointer;
}
.codecopy_notice {
    position: absolute;
    top: 0.7rem;
    right: 6px;
    z-index: 1;
    filter: invert(50%);
    opacity: 0;
}
.code_lang {
    position: absolute;
    top: 1.2rem;
    right: 46px;
    line-height: 0;
    font-weight: bold;
    font-family: normal;
    z-index: 1;
    filter: invert(50%);
    cursor: pointer;
}

.code-expand {
    position: absolute;
    top: 4px;
    right: 0px;
    filter: invert(50%);
    padding: 7px;
    z-index: 999 !important;
    cursor: pointer;
    transition: all .3s;
    transform: rotate(0deg);
}

.code-closed .code-expand {
    transform: rotate(-180deg) !important;
    transition: all .3s;
}

.code-closed pre::before {
    height: 0px;
}

pre code {
    padding: 0;
    color: #e8eaf6;
    background-color: #272822;
}

pre[class*="language-"] {
    padding: 1.2em;
    margin: .5em 0;
}

code[class*="language-"],
pre[class*="language-"] {
    color: #e8eaf6;
    white-space: pre-wrap !important;
}

.line-numbers-rows {
    border-right-width: 0px !important;
}

.line-numbers {
    padding: 1.5rem 1.5rem 1.5rem 3.2rem !important;
    margin: 1rem 0 !important;
    background: #272822;
    overflow: auto;
    border-radius: 0.35rem;
    tab-size: 4;
}

5. 文章代码块添加

打开themes\matery\layout\_partial\post-detail.ejs,添加如下代码

<!-- 代码块功能依赖 -->
<script type="text/javascript" src="<%- url_for('/libs/codeBlock/codeBlockFunction.js') %>"></script>

<!-- 代码语言 -->
<% if (theme.code.lang) { %>
<script type="text/javascript" src="<%- url_for('/libs/codeBlock/codeLang.js') %>"></script>
<% } %>

<!-- 代码块复制 -->
<% if (theme.code.copy) { %>
<script type="text/javascript" src="<%- url_for('/libs/codeBlock/codeCopy.js') %>"></script>
<% } %>

<!-- 代码块收缩 -->
<% if (theme.code.shrink) { %>
<script type="text/javascript" src="<%- url_for('/libs/codeBlock/codeShrink.js') %>"></script>
<% } %>

<!-- 代码块折行 -->
<% if (!theme.code.break) { %>
<style type="text/css">
code[class*="language-"], pre[class*="language-"] { white-space: pre !important; }
</style>
<% } %>

6. 代码块JS添加

打开目录themes\matery\source\libs,新建一个名字为codeBlock的目录,然后打开该目录。

themes\matery\source\libs\codeBlock目录下新建codeBlockFunction.js文件,并添加如下代码

// 代码块功能依赖
$(function () {
    $('pre').wrap('<div class="code-area" style="position: relative"></div>');
});

themes\matery\source\libs\codeBlock目录下新建codeCopy.js文件,并添加如下代码

// 代码块一键复制
$(function () {
    var $copyIcon = $('<i class="fa fa-files-o code_copy" title="复制代码" aria-hidden="true"></i>')
    var $notice = $('<div class="codecopy_notice"></div>')
    $('.code-area').prepend($copyIcon)
    $('.code-area').prepend($notice)
    // “复制成功”字出现
    function copy(text, ctx) {
        if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
            try {
                document.execCommand('copy') // Security exception may be thrown by some browsers.
                $(ctx).prev('.codecopy_notice')
                    .text("复制成功")
                    .animate({
                        opacity: 1,
                        top: 30
                    }, 450, function () {
                        setTimeout(function () {
                            $(ctx).prev('.codecopy_notice').animate({
                                opacity: 0,
                                top: 0
                            }, 650)
                        }, 400)
                    })
            } catch (ex) {
                $(ctx).prev('.codecopy_notice')
                    .text("复制失败")
                    .animate({
                        opacity: 1,
                        top: 30
                    }, 650, function () {
                        setTimeout(function () {
                            $(ctx).prev('.codecopy_notice').animate({
                                opacity: 0,
                                top: 0
                            }, 650)
                        }, 400)
                    })
                return false
            }
        } else {
            $(ctx).prev('.codecopy_notice').text("浏览器不支持复制")
        }
    }
    // 复制
    $('.code-area .fa-files-o').on('click', function () {
        var selection = window.getSelection()
        var range = document.createRange()
        range.selectNodeContents($(this).siblings('pre').find('code')[0])
        selection.removeAllRanges()
        selection.addRange(range)
        var text = selection.toString()
        copy(text, this)
        selection.removeAllRanges()
    })
});

themes\matery\source\libs\codeBlock目录下新建codeLang.js文件,并添加如下代码

// 代码块语言识别
$(function () {
  var $highlight_lang = $('<div class="code_lang" title="代码语言"></div>');

  $('pre').before($highlight_lang);
  $('pre').each(function () {
    var code_language = $(this).attr('class');

    if (!code_language) {
      return true;
    };
    var lang_name = code_language.replace("line-numbers", "").trim().replace("language-", "").trim();

    // 首字母大写
    // lang_name = lang_name.slice(0, 1).toUpperCase() + lang_name.slice(1);
    
    $(this).siblings(".code_lang").text(lang_name);
  });
});

themes\matery\source\libs\codeBlock目录下新建codeShrink.js文件,并添加如下代码

// 代码块收缩
$(function () {
  var $code_expand = $('<i class="fa fa-angle-down code-expand" aria-hidden="true"></i>');

  $('.code-area').prepend($code_expand);
  $('.code-expand').on('click', function () {
    if ($(this).parent().hasClass('code-closed')) {
      $(this).siblings('pre').find('code').show();
      $(this).parent().removeClass('code-closed');
    } else {
      $(this).siblings('pre').find('code').hide();
      $(this).parent().addClass('code-closed');
    }
  });
});

7. 解决代码块复制内容不换行问题

Matery主题在开启复制版权且添加了版权信息后,会导致复制的所有内容换行失效,以下将解决这个问题。

themes\matery\layout\_partial\post-detail.ejs文件中,大约在222行左右找到 selection.getRangeAt(0).commonAncestorContainer.nodeName,将原先if条件中的的PRE修改为CODE即可。

if (selection.getRangeAt(0).commonAncestorContainer.nodeName === 'CODE') {
    newdiv.innerHTML = "<pre>" + newdiv.innerHTML + "</pre>";
}

至此,代码块的优化已经全部完成。


文章作者: Luckysec
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Luckysec !
评论
  目录