前言
在官方最新版本的Matery主题版本中已经优化了代码块的问题,但在旧版本Hexo主题Matery中对hexo-prism-plugin只支持高亮显示,而且存在着许多的BUG。比如新版本的hexo-prism-plugin已经支持了代码块的一键复制和收缩功能,如果不手动对旧版本Matery原有的代码做改动,则代码块显示会存在一些问题。
代码块优化
1. 安装代码块插件
代码语言:javascript复制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主题的配置文件themesmatery_config.yml
,添加如下代码
code:
lang: true # 代码块是否显示名称
copy: true # 代码块是否可复制
shrink: true # 代码块是否可以收缩
break: false # 代码是否折行
4. 代码块CSS优化
打开themessourcecssmatery.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. 文章代码块添加
打开themesmaterylayout_partialpost-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添加
打开目录themesmaterysourcelibs
,新建一个名字为codeBlock
的目录,然后打开该目录。
在themesmaterysourcelibscodeBlock
目录下新建codeBlockFunction.js
文件,并添加如下代码
// 代码块功能依赖
$(function () {
$('pre').wrap('<div class="code-area" style="position: relative"></div>');
});
在themesmaterysourcelibscodeBlock
目录下新建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()
})
});
在themesmaterysourcelibscodeBlock
目录下新建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);
});
});
在themesmaterysourcelibscodeBlock
目录下新建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主题在开启复制版权且添加了版权信息后,会导致复制的所有内容换行失效,以下将解决这个问题。
在themesmaterylayout_partialpost-detail.ejs
文件中,大约在222行左右找到 selection.getRangeAt(0).commonAncestorContainer.nodeName
,将原先if
条件中的的PRE
修改为CODE
即可。
if (selection.getRangeAt(0).commonAncestorContainer.nodeName === 'CODE') {
newdiv.innerHTML = "<pre>" newdiv.innerHTML "</pre>";
}
至此,代码块的优化已经全部完成。