桥山之巅,姬水之畔

基于Hexo-Ocean主题博客搭建

2019.09.30

本文主要是Hexo Ocean主题博客搭建过程的记录 博客地址:松林羊

hexo 的基本命令

hexo init [folder] :创建一个存放网站源码的文件夹。 hexo new [layout] <title>:新建一篇文章。layout:默认post,可以是page、draft。title:文章标题,标题包含空格的话,请使用引号括起来。 hexo clean:清除缓存文件db.json和已生成的静态文件public,尤其是更换主题后 hexo g:生成静态html文件 hexo s:启动服务器 hexo d:部署网站 传送门:官方文档

下载主题源码

在hexo init [folder] 的folder目录下执行:

git clone https://github.com/zhwangart/hexo-theme-ocean.git themes/ocean

参照主题文档进行配置

Ocean 中文文档 关于 Ocean 使用中的问题

文章自动添加Read More

将\themes\ocean\layout\_partial\article.ejs文中的<% if (post.excerpt && index){ %>的else部分替换为如下内容:

<% var br = post.content.indexOf('<br>') %>
<% if(br < 0 || !index) { %>
  <%- post.more %>
<% } else { %>
  <%- post.content.substring(0, br) %><br/>
  <% if (theme.excerpt_link) { %>
	<a class="article-more-link" href="<%- url_for(post.path) %>"><%= theme.excerpt_link %></a>
  <% } %>
<% } %>

搜索功能不起作用? or 除开首页不能正常搜索

  1. 本地检索需要安装插件

    	npm install hexo-generator-searchdb --save
    
  2. 另外一个问题:插件搜索函数返回的url 地址有问题 ,作者说是因为 “中文字符被URL encode了 ” 。后来我找到一个解决办法: 将 [folder]/node_modules/hexo-generator-searchdb/templates/xml.ejs 文件中的:

    	<url><%- encodeURIComponent(config.root + post.path) %></url>
    

    修改为

    	<url><%- encodeURI(config.root + post.path) %></url>
    

修改导航栏

修改 themes/ocean/source/css/_partial/navbar.styl 文件

文章添加封面图片

---
title: Post name
date: 2019-07-24 22:01:03
photos: [
        ["/images/相机.jpg"], // themes/ocean/source/images目录下
        ["https://tuchong.pstatp.com/2716763/f/531173888.jpg"]
  ]
---

在首页只会显示第一张,详情页会按顺序显示这两张

为文章添加Gitalk评论

参考:https://zhwangart.github.io/2018/12/06/Gitalk/

在右上角或者左上角实现fork me on github

选样式:GitHub Corners-1GitHub Corners-2 然后粘贴刚才复制的代码到themes/ocean/layout/index.ejs文件中,放在<div id=”landingpage”></div>的第一行,并把href改为你的github地址 对样式做出修改: <div id="landingpage"> 修改为 <div id="landingpage" style="position:relative;"> 复制的<a>标签添加如下样式:style="position:absolute;left:0;top:100;z-index=1000;"

实现点击出现特效

  1. 点击桃心 下载:桃心Js 然后将里面的代码copy一下,新建love.js文件并且将代码复制进去,然后保存。 在themes/ocean/_config.yml最后一行写入:

    	lovejs: true
    

    将love.js文件放到路径/themes/ocean/source/js/src里面,然后打开\themes\ocean\layout\_partial\ after-footer.ejs文件, 在最后一行写入:

    	<% if (theme.lovejs){ %>
    		<%- js('/js/love.js') %>
    	<% } %> 
    
  2. 爆炸效果 下载:fireworks.jsanime.min.js 步骤与上面类似保存js到/themes/ocean/source/js/src,最后在\themes\ocean\layout\_partial\ after-footer.ejs文件内容未写入:

    	<% if (theme.fireworks){ %>
    	   <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 1; pointer-events: none;" ></canvas>
    	   <%- js('/js/anime.min.js') %>
    	   <%- js('/js/fireworks.js') %>
    	<% } %>
    

头像旋转效果

打开\themes\ocean\layout\_partial\sidebar.ejs,给<div class=logo>下的img加上一个id。然后参考:css + js实现图片不停旋转 鼠标悬停停止旋转 然后将里面的js代码copy到一个my.js文件中(注意替换img的id),保存到/themes/ocean/source/js/src目录。 然后在\themes\ocean\layout\_partial\after-footer.ejs中最后一行写入:

<%- js('/js/my.js') %>

网站底部加上访问量

\themes\ocean\layout\_partial\after-footer.ejs 中默认是导入了统计脚本的(busuanzi-2.3.pure.min.js )

修改访问量统计的样式: 将\themes\ocean\layout\_partial\post\busuanzi.ejs 修改为:

<div class="powered-by">
  <% if (is_home()) { %>
    <span id="busuanzi_container_site_pv">访问量:<span id="busuanzi_value_site_pv"></span></span>
  <%} %>
	&emsp;<i class="fa fa-user-md"></i><span id="busuanzi_container_site_uv">访客数:<span id="busuanzi_value_site_uv"></span></span>&emsp;
  <% if (is_post()) { %>
    <i class="fe fe-bookmark"></i>文章访问量:<span id="busuanzi_value_page_pv"></span>
  <%} %>
</div>

添加网站字数,阅读时间统计

在根目录下运行:

npm install hexo-wordcount –save

在\themes\ocean\_config.yml主题配置文件中加入:

post_wordcount:
  item_text: true
  wordcount: true
  min2read: true
  totalcount: true
  separated_meta: true

在\themes\ocean\layout\_partial\footer.ejs文件中,在<ul class="list-inline">标签后加入:

<ul class="list-inline">
	<li>全站共<span class="post-count"><%= totalcount(site) %></span>字</li>
</ul> 

在\themes\ocean\layout\_partial\article.ejs文件中,在<div class="article-meta">标签中加入:

&emsp;<i class="fe fe-bar-chart"></i> <span class="post-count"><%- wordcount(post.content) %></span>字
&emsp;<i class="fe fe-clock"></i> <span class="post-count"><%- min2read(post.content) %></span>分钟

Ocean主题的图标

图标在\themes\ocean\source\css\_feathericon.styl中查找 官网:feathericons

为博客加上萌萌的宠物

hexo-helper-live2d 在网站根目录下执行

npm install -save hexo-helper-live2d
npm install live2d-widget-model-haruto(自己选择的萌宠模型)

在hexo的配置文件中添加:

# 萌宠
 live2d:
  enable: true
  scriptFrom: local
  model:
    use: live2d-widget-model-haruto
    scale: 1
    hHeadPos: 0.5
    vHeadPos: 0.618
  display:
    superSample: 2
    width: 150
    height: 300
    position: left
    hOffset: 0
    vOffset: -20
  mobile:
    show: true
  react:
    opacityDefault: 0.5
    opacityOnHover: 0.2

重启服务:

hexo clean && hexo g && hexo s

添加网站运行时间

<span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
<script>
    var now = new Date(); 
    function createtime() { 
        var grt= new Date("04/26/2019 15:49:00");//此处修改你的建站时间或者网站上线时间 
        now.setTime(now.getTime()+250); 
        days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); 
        hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); 
        if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); 
        mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} 
        seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); 
        snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} 
        document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+" 天 "; 
        document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; 
    } 
	setInterval("createtime()",250);
</script>

将以上代码保存到\themes\ocean\layout\_partial\post\runtime.ejs

在\themes\ocean\layout\_partial\footer.ejs文件中,第一个<ul class="list-inline"></ul>标签后加入:

<div class="float-right">
      <%- partial('post/runtime') %>
</div>

添加DaoVoice 在线联系

首先在https://account.daocloud.io/signin  注册账号 然后点击下方链接 http://dashboard.daovoice.io/get-started?invite_code=0f81ff2f 之后会得到一个app_id

在主题配置文件写入:

# Online contact 
daovoice: true
daovoice_app_id: 这里填你的刚才获得的 app_id

在\themes\ocean\layout\_partial\footer.ejs中,</head>前写入:

<% if (theme.daovoice){ %>
  <script>
  (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/0f81ff2f.js","daovoice")
  daovoice('init', {
      app_id: "<%- theme.daovoice_app_id %>"
    });
  daovoice('update');
  </script>
<% } %>

取消文章下面的分享连接,添加本文结束

去掉\themes\ocean\layout\_partial\article.ejs中的以下代码:

<a data-url="<%- post.permalink %>" data-id="<%= post._id %>" class="article-share-link"><%- theme.share_text %></a>

同时还可以添加本文结束 感谢阅读等说明: 如在<%- partial('post/tag') %>下面一行添加:

<% if (!index && is_post()) { %>
	<div style="text-align:center;color: #ccc;font-size:14px;">------------- 本文结束&nbsp;<i class="fe fe-smile"></i>&nbsp;感谢您的阅读 -------------</div>
<% } %>

博文压缩

在根目录下执行:

npm install gulp -g
npm install gulp-minify-css gulp-uglify gulp-htmlmin gulp-htmlclean gulp –save

在根目录下新建gulpfile.js,写入一下内容:

var gulp = require('gulp');
//Plugins模块获取
var minifycss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
var htmlmin = require('gulp-htmlmin');
var htmlclean = require('gulp-htmlclean');
//压缩css
gulp.task('minify-css',
function() {
    return gulp.src('./public/**/*.css').pipe(minifycss()).pipe(gulp.dest('./public'));
});
//压缩html
gulp.task('minify-html',
function() {
    return gulp.src('./public/**/*.html').pipe(htmlclean()).pipe(htmlmin({
        removeComments: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
    }))
    .pipe(gulp.dest('./public'))
});
//压缩js 不压缩min.js
gulp.task('minify-js',
function() {
    return gulp.src(['./public/**/*.js', '!./public/**/*.min.js']).pipe(uglify()).pipe(gulp.dest('./public'));
});

//4.0以前的写法 
//gulp.task('default', [
//  'minify-html', 'minify-css', 'minify-js'
//]);

//4.0以后的写法
// 执行 gulp 命令时执行的任务
//gulp.task('default', gulp.parallel('minify-html', 'minify-css', 'minify-js',
//function() {
    // Do something after a, b, and c are finished.
//	console.log('success')
//}));

gulp.task('default',gulp.series(gulp.parallel('minify-html','minify-css','minify-js')));

生成博文时执行

hexo clean && hexo g && gulp && hexo d 

就会根据 gulpfile.js 中的配置,对 public 目录中的静态资源文件进行压缩。

修改文章封面图片的引入方式,同时支持相对地址与http的图片

将\themes\ocean\layout\_partial\post\gallery.ejs 中的<% if (index){ %>的上一行写入:

<% var idx = url_for(photo).indexOf('http') %>

将文中两处的:

<img src="<%- url_for(photo) %>" itemprop="image">

修改为:

<% if(idx < 0) { %>
	<img src="<%- url_for(post.path)+url_for(photo).substring(1) %>" itemprop="image">
<% } else { %>
	<img src="<%- url_for(photo) %>" itemprop="image">
<% } %>

设置封面图片不在内容详情页展示

将\themes\ocean\layout\_partial\article.ejs 中的

<%- partial('post/gallery') %>

修改为:

<% if (index){ %>
	<%- partial('post/gallery') %>
<% } %>

去掉rss订阅

根目录下执行:

npm uninstall hexo-generator-feed –save

将\themes\ocean\_config.yml文件中修改为:rss: false

导航栏图表改为在文字左侧

修改\themes\ocean\source\css\_partial\navbar.styl

&.nav-main
      .nav-item-link
        &::before, i.fe
          display block
          line-height 1
        &::before
          font-family 'feathericon'

修改为:

&.nav-main
      .nav-item-link
        &::before, i.fe
          // display block
          line-height 1
		   margin-right: 10px;
        &::before
          font-family 'feathericon'

添加readme.md不被渲染

在Hexo目录下的source根目录下添加一个, README.md。 修改Hexo目录下的_config.yml。 将skip_render参数的值设置上。skip_render: README.md 保存退出即可。

首页视屏换成图片

将\themes\ocean\layout\_partial\ocean.ejs中

<video playsinline="" autoplay="" loop="" muted="" data-autoplay=""
   poster="<%- theme.ocean.path %>ocean.png" x5-video-player-type="h5">
  <source src="<%- theme.ocean.path %>ocean.mp4" type="video/mp4">
  <source src="<%- theme.ocean.path %>ocean.ogv" type="video/ogg">
  <source src="<%- theme.ocean.path %>ocean.webm" type="video/webm">
  <p>Your user agent does not support the HTML5 Video element.</p>
</video>

修改为:

<img src="<%- theme.ocean.path %>ocean.png">

去掉首页视频或图片

去掉themes/ocean/layout/index.ejs中的

<%- partial('_partial/ocean') %>

is_home()、is_post() 函数判断不正确

将\themes\ocean\layout\layout.ejs中

<%- partial('_partial/footer', null, {cache: !config.relative_link}) %>

修改为

<%- partial('_partial/footer', null, {cache: config.relative_link}) %>

就是将partial中的cache设置为false。参考:is_home()、is_post() 函数判断不正确

视频 or 图片只在pc端显示,不在移动端显示

修改themes\ocean\source\css_partial\layou.styl文件

// Media Query
@media (min-width: 768px)
  .jumbotron
    margin-bottom 6rem
    display block   //此处为新增。设备宽度大于等于768像素时显示视频or图片

在文件末尾新增

@media (max-width: 768px)
  .jumbotron
    display none  // 设备宽度小于等于768像素时不显示视频or图片

此时会发现移动端左上角有点空旷,则进行如下修改 修改themes\ocean\layout_partial\archive.ejs文件

var title = '';
var mobile_title = "松林羊 Blog";  // 此处为新增
...
<h1 class="page-type-title pc"><%- title %></h1> // 新增类名为pc的样式
<h1 class="page-type-title mobile"><%- mobile_title %></h1> // 此处为新增

修改themes\ocean\source\css_partial\archive.styl文件

.page-type-title
  margin 0
  padding 3rem 0
 // 以下内容为新增
  &.pc
    @media screen and (max-width: 768px)
      display none
    @media screen and (min-width: 768px)
      display block
  &.mobile
    @media screen and (max-width: 768px)
      display block
      font-family 'STXingkai'
    @media screen and (min-width: 768px)
      display none

配置fancybox展示文章图集

在themes\ocean\layout\_partial\after-footer.ejs文件末尾加入如下代码

<% if (is_post()){ %>
<script>
// 使用fancybox来显示post图片集(#andus-head-img为头像id)
$('img:not(#andus-head-img)').each(function() {
  $(this).wrap('<a class="fancybox" data-fancybox="gallery" href="' + $(this).prop("src") + '"></a>'); 
})
</script>
<% } %>

更换评论系统,由gitalk跟换为valine, 并增加邮件通知功能

依次参考 Valine--一款极简的评论系统 Valine Valine-Adminthemes/ocean/_config.yml文件中新增以下内容,同时确保gitalk.enablefalse

# Valine 不能与gitalk同时开启
valine:
  enable: true
  app_id:  # 这里填写得到的APP ID
  app_key:  # 这里填写得到的APP KEY
  placeholder: 记得留下你的昵称和邮箱...可以快速收到回复ヾノ≧∀≦)o # [v1.0.7 new]留言框占位提示文字
  notify: true # 评论回复邮件提醒 。 第三方支持:https://github.com/zhaojun1998/Valine-Admin
  verify: false # 验证码 。 开启邮件提醒会默认开启验证码选项
  avatar: monsterid # Gravatar头像。可选项:[identicon monsterid  wavatar retro robohash mp ''] ,见 https://valine.js.org/avatar.html
  recordIP: true # 是否记录评论者ip
  visitor: false  # 阅读量统计 https://valine.js.org/visitor.html

拷贝themes\ocean\layout\_partial\post\gitalk.ejs重命名为valine.ejs 全部内容修改为

<% if (theme.valine.enable) { %>
  <div class="comment_headling"  style="margin-top:5rem;">
	<font size="5"><i class="fe fe-comments"></i> 评论</font>
  </div>
  <div class="comment"></div>
  <%- js('https://cdn1.lncld.net/static/js/3.0.4/av-min.js') %>
  <%- js('js/Valine.min.js') %>
  <script type="text/javascript">
  // https://cdnjs.cloudflare.com/ajax/libs/valine/1.3.10/Valine.min.js
  GUEST_INFO = ["nick", "mail", "link"],
  guest_info = "nick,mail,link".split(",").filter(function(i) {
		return - 1 < GUEST_INFO.indexOf(i)
  });
  guest_info = 0 == guest_info.length ? GUEST_INFO: guest_info,
  new Valine({
	 // AV 对象来自上面引入av-min.js
	 av: AV, 
	 el: '.comment',
	 app_id: '<%- theme.valine.app_id %>', 
	 app_key: '<%- theme.valine.app_key %>', 
	 placeholder: '<%- theme.valine.placeholder %>',
	 meta: guest_info,
	 notify: <%- theme.valine.notify %>,
	 verify: <%- theme.valine.verify %>,
	 avatar: '<%- theme.valine.avatar %>',
	 recordIP: <%- theme.valine.recordIP %>,
	 visitor: <%- theme.valine.visitor %>,
	 lang: 'zh-cn'
  });
  </script>
<% } %>

修改themes\ocean\layout\_partial\article.ejs文件

<% if (is_post()) { %>
	<%- partial('post/gitalk') %>
	<%# 下面为新增内容 %>
	<%- partial('post/valine') %>
<%} %>

关闭评论时的验证码,将Valine.min.js保存到themes\ocean\source\js目录下,将其中

u.attr(Q, "style", "display:block;"), t && t.type) {
	var o = u.find(Q, ".vsure");
	u.on("click", o,
	function(n) {
		e.alert.hide(),
		t.cb && t.cb()
	})
}

修改为

u.attr(Q, "style", "display:none;"), t && t.type) {
	e.alert.hide(),
	t.cb && t.cb()
}

记录(自用)

<%- page.content.substring(0,tips) %> 显示html的样式结果
<%= page.content.substring(0,tips) %>显示html源代码