Hexo系列

HexoRSS分类订阅

[三万字教程]基于Hexo的matery主题搭建博客并深度优化完全一站式教程

  • markdown 各种其它语法插件,latex公式支持,mermaid图表,plant uml图表,URL卡片,bilibili卡片,github卡片,豆瓣卡片,插入音乐和视频,插入脑图,插入PDF,嵌入iframe

用户交互沟通

添加博客看板娘

方法如下:

安装插件:

npm install --save hexo-helper-live2d

安装喜欢的模型:

$ npm install packagename
#安装下载动画人物库, 动画人物有很多, 可以网上查询资料, 下面推荐几种.
npm install --save live2d-widget-model-shizuku #课桌女孩
npm install --save live2d-widget-model-hibiki  #御姐
npm install --save live2d-widget-model-wanko   #狗狗
npm install --save live2d-widget-model-haruto  #海军服女孩
npm install --save live2d-widget-model-miku    #萝莉

将packagename换成模型名字,如我使用的模型:

$ npm install live2d-widget-model-shizuku

然后打开博客根目录下的 _config.yml文件,添加如下代码:

使用本地模型方式:

## 添加动画live2d模块  npm install --save hexo-helper-live2d
## 下载动画人物库 npm install live2d-widget-model-z16 -D
live2d:
  enable: true
  scriptFrom: local # 默认
  pluginRootPath: live2dw/ # 插件在站点上的根目录(相对路径)
  pluginJsPath: lib/ # 脚本文件相对与插件根目录路径
  pluginModelPath: assets/ # 模型文件相对与插件根目录路径
  tagMode: false # 标签模式, 是否仅替换 live2d tag标签而非插入到所有页面中
  debug: false # 调试, 是否在控制台输出日志
  model:
    use: live2d-widget-model-miku
  display:
    position: right #动画位置
    width: 150
    height: 190
    # 位置配置,这个在左侧边栏位置很居中
    hOffset: 50  # 调节水平位置
    vOffset: -5  # 调节垂直位置
  mobile:
    show: false # 是否在移动设备上显示
    scale: 0.5 # 移动设备上的缩放
  react:
    opacityDefault: 0.7
    opacityOnHover: 0.8

使用网络模型方式:

# Live2D
## https://github.com/EYHN/hexo-helper-live2d
live2d:
  enable: true
  # enable: false
  pluginRootPath: live2dw/ # Root path of plugin to be on the site (Relative)
  pluginJsPath: lib/ # JavaScript path related to plugin's root (Relative)
  pluginModelPath: assets/ # Relative model path related to plugin's root (Relative)
  scriptFrom: local # Default
  # scriptFrom: jsdelivr # jsdelivr CDN
  # scriptFrom: unpkg # unpkg CDN
  # scriptFrom: https://cdn.jsdelivr.net/npm/live2d-widget@3.x/lib/L2Dwidget.min.js # Your custom url
  tagMode: false # Whether only to replace live2d tag instead of inject to all pages
  log: false # Whether to show logs in console
  model:
    #use: live2d-widget-model-lwet # npm-module package name
    # use: wanko # folder name in (hexo base dir)/live2d_models/
    # use: ./wives/wanko # folder path relative to hexo base dir
    # 模型:https://huaji8.top/post/live2d-plugin-2.0/
    use: https://cdn.jsdelivr.net/npm/live2d-widget-model-wanko@1.0.5/assets/wanko.model.json # Your custom url
  display:
    position: left
    width: 300
    height: 400
    hOffset: 50
    vOffset: 10
  mobile:
    show: false

见右下角

Live2D看板娘

更强大的看板娘

live2d-widget 原作者教程

支持换装,模型切换,对话框,拍照,小游戏,眼神跟随,触摸对话,音频等。

可以自建api,自定义各种模型,各种对话等。

live2d看板娘

live2d-widget效果图

依赖 Font Awesome

请在 <head> 中加入。在Matery中自带,这一步跳过。

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css">

使用 Usage

将这一行代码加入 <head><body>,即可展现出效果:

<script src="https://cdn.jsdelivr.net/gh/17lai/live2d-widget@latest/autoload.js"></script>

后端 API

initWidget 方法接受名为 apiPathcdnPath 的参数,两者设置其中一项即可。其中 apiPath 为后端 API 的 URL,可以自行搭建,并增加模型(需要修改的内容比较多,此处不再赘述)。而 cdnPath 则是通过 jsDelivr 这样的 CDN 服务加载资源,更加稳定。

目录结构 Files

  • waifu-tips.js 包含了按钮和对话框的逻辑;
  • waifu-tips.json 中定义了触发条件(selector,CSS 选择器)和触发时显示的文字(text);
  • waifu.css 是看板娘的样式表。

使用 waifu-tips.json 自定义 selector触发提示文字框,可以用来做菜单,按钮的导航提示,终于是个合格的看板娘了!

  • 对所有菜单,常用按钮做了基本文字提示。鼠标去到处戳一下,看看触发提示!😄
  • 这是一个不小的工程,难度不高,趣味性很强。

看板娘触发文字提示

添加夜间模式切换

  • 下面这个还远未完善,只是基本可用,不少细节地方CSS需要完善
  • 已经由博主上传到官方 develop 分支了

设置基础样式

参考其他优秀产品的黑夜模式,得出共性:

  • 那就是黑夜模式的背景一般不会是纯黑(#000);而是淡黑色,字体也不是纯白(#fff)而浅白色
  • 图片亮度降低

下面就开始贴代码了

themes>hexo-theme-matery>source>css>matery.css 中加上下面的代码

/* 字体颜色变灰白色 */
body.DarkMode .fas,
body.DarkMode .title,
body.DarkMode .row .text,
body.DarkMode article .article-content .summary,
body.DarkMode .card .card-image .card-title,
body.DarkMode .fa-moon-o:before,
body.DarkMode .fa-lightbulb-o:before,
body.DarkMode article .article-tags .chip,
body.DarkMode .chip-container .tag-title,
body.DarkMode div.jqcloud a,
body.DarkMode .friends-container .tag-title,
body.DarkMode .frind-ship .title h1,
body.DarkMode .card .card-content p,
body.DarkMode .card .card-content .dss,
body.DarkMode .v[data-class='v'] .vcount,
body.DarkMode .v[data-class='v'] .vcount .vnum,
body.DarkMode pre code,
body.DarkMode h1,
body.DarkMode h2,
body.DarkMode h3,
body.DarkMode h4,
body.DarkMode h5,
body.DarkMode h6,
body.DarkMode li,
body.DarkMode p,
body.DarkMode header .side-nav .mobile-head .logo-name,
body.DarkMode header .side-nav .mobile-head .logo-desc,
body.DarkMode header .side-nav .menu-list a,
body.DarkMode .bg-cover .post-title,
body.DarkMode.read .bg-cover .description {
    color: rgba(255, 255, 255, 0.6);
}

/* 背景颜色变灰色 */
body.DarkMode .card,
body.DarkMode .block-with-text:after {
    background-color: #282c34;
}

/* 背景颜色变黑色 */
body.DarkMode,
body.DarkMode .v[data-class='v'] .vcount,
body.DarkMode #rewardModal .modal-content,
body.DarkMode .modal,
body.DarkMode header .side-nav,
body.DarkMode header .side-nav .menu-list .m-nav-show {
    background-color: #12121c;
}

/* 改变透明度 */
body.DarkMode .aplayer {
    background: #2f3742 !important;
}

body.DarkMode img,
body.DarkMode strong {
    filter: brightness(0.7);
}

/*toc目录滤镜*/
body.DarkMode .toc-widget {
    filter: invert(0.8);
}

body.DarkMode .toc-widget .toc-list-item {
    color: #000
}

/* Skill bar text color */
body.DarkMode .skillbar .skill-bar-percent {
    color: #000;
}

切换按钮

完成了背景、字体、图片的样式,就需要黑夜白天切换按钮了

themes>hexo-theme-matery>layout>_widget 中创建一个新的文件 day-night.ejs,在新建的文件中加入下面的代码

<!-- 白天和黑夜主题 -->
<div class="sum-moon-box">
  <a class="btn-floating btn-large waves-effect waves-light" onclick="switchNightMode()" title="切换主题" >
    <i id="sum-moon-icon" class="fas fa-sun" style="width:48px; height:48px; font-size: 28px;"></i>
  </a>
</div>

<script>
  function switchNightMode() {
    $('<div class="Cuteen_DarkSky"><div class="Cuteen_DarkPlanet"></div></div>').appendTo($('body')),
      setTimeout(function () {
        $('body').hasClass('DarkMode') 
        ? ($('body').removeClass('DarkMode'), localStorage.setItem('isDark', '0'), $('#sum-moon-icon').removeClass("fa-sun").addClass('fa-moon')) 
        : ($('body').addClass('DarkMode'), localStorage.setItem('isDark', '1'), $('#sum-moon-icon').addClass("fa-sun").removeClass('fa-moon')),
          
        setTimeout(function () {
          $('.Cuteen_DarkSky').fadeOut(1e3, function () {
            $(this).remove()
          })
        }, 2e3)
      })
  }
</script>

再在 themes>hexo-theme-matery>layout>layout.ejs 文件中引用一下

需要在 body 标签内部插入下面代码

<%- partial('_widget/day-night.ejs') %>

按钮样式

完成上面操作以后,就需要添加按钮样式和切换动画了,同样是在 themes>hexo-theme-matery>source>css>matery.css

/* 黑夜模式动画 */
.Cuteen_DarkSky,
.Cuteen_DarkSky:before {
    content: '';
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 8888;
}

.Cuteen_DarkSky {
    background: linear-gradient(#feb8b0, #fef9db);
}

.Cuteen_DarkSky:before {
    transition: 2s ease all;
    opacity: 0;
    background: linear-gradient(#4c3f6d, #6c62bb, #93b1ed);
}

.DarkMode .Cuteen_DarkSky:before {
    opacity: 1;
}

.Cuteen_DarkPlanet {
    z-index: 9999;
    position: fixed;
    left: -50%;
    top: -50%;
    width: 200%;
    height: 200%;
    -webkit-animation: CuteenPlanetMove 2s cubic-bezier(0.7, 0, 0, 1);
    animation: CuteenPlanetMove 2s cubic-bezier(0.7, 0, 0, 1);
    transform-origin: center bottom;
}

@-webkit-keyframes CuteenPlanetMove {
    0% {
        transform: rotate(0);
    }
    to {
        transform: rotate(360deg);
    }
}

@keyframes CuteenPlanetMove {
    0% {
        transform: rotate(0);
    }
    to {
        transform: rotate(360deg);
    }
}

.Cuteen_DarkPlanet:after {
    position: absolute;
    left: 35%;
    top: 40%;
    width: 9.375rem;
    height: 9.375rem;
    border-radius: 50%;
    content: '';
    background: linear-gradient(#fefefe, #fffbe8);
}

/*黑夜模式按钮*/
.sum-moon-box {
    width: 48px;
    height: 48px;
    text-align: center;
    border-radius: 50%;
    position: fixed;
    right: 15px;
    bottom: 195px;
    margin-bottom: 0;
    z-index: 900;
}

.sum-moon-box .btn-floating {
    width: 48px;
    height: 48px;
}

.sum-moon-box i {
    font-size: 1.8rem;
    line-height: 48px !important;
}

定时提示切换黑夜模式

themes>hexo-theme-matery>source>js>matery.js 中添加下列代码

//黑夜模式提醒开启功能
setTimeout(function () {
    if ((new Date().getHours() >= 19 || new Date().getHours() < 7) && !$('body').hasClass('DarkMode')) {
        let toastHTML = '<span style="color:#97b8b2;border-radius: 10px;>' + '<i class="fa fa-bellaria-hidden="true"></i>晚上使用黑夜模式阅读能够减轻视觉疲劳。</span>'
        M.toast({ html: toastHTML })
    }
}, 2000)

黑夜模式持久化

themes>hexo-theme-matery>layout>layout.ejs 中添加下列代码(最好插入在 <%- partial('_partial/day-night.ejs') %> 下面)

/* 模式判断 */
<script>
    /* 模式判断 */
    if (localStorage.getItem('isDark') === '1') {
        document.body.classList.add('DarkMode');
        $('#sum-moon-icon').addClass("fa-sun").removeClass('fa-moon')
    } else {
        document.body.classList.remove('DarkMode');
        $('#sum-moon-icon').removeleClass("fa-sun").addClass('fa-moon')
    }
</script>

完成以上操作就完成了基本的黑夜模式了。

黑夜白天切换的动态背景

下面这是黑夜白天切换的动态背景,在你新建的 day-night.ejs 文件中加入下列代码

<div class="stars-con">
  <div id="stars"></div>
  <div id="stars2"></div>
  <div id="stars3"></div>  
</div>

themes>hexo-theme-matery>source>css>matery.css 中加上下面的代码

/*黑夜模式背景*/
body.DarkMode {
    background: linear-gradient(#15151b, #1b1b2e, #231832) !important;
}

@keyframes animStar {
    from {
        transform: translateY(0)
    }
    to {
        transform: translateY(-2000px)
    }
}

body.DarkMode .stars-con {
    position: fixed;
    height: 100vh;
    width: 100vw;
    overflow: hidden;
    z-index: -111;
    background: linear-gradient(#15151b, #1b1b2e, #231832);
}

body.DarkMode #stars {
    width: 1px;
    height: 1px;
    background: 0 0;
    box-shadow: 1804px 1265px #fff, 365px 332px #fff, 86px 1888px #fff, 1888px 484px #fff, 199px 1489px #fff, 1459px 1010px #fff, 807px 388px #fff, 855px 558px #fff, 83px 1095px #fff, 1418px 377px #fff, 677px 886px #fff, 862px 1709px #fff, 1058px 1085px #fff, 50px 1772px #fff, 1941px 1544px #fff, 377px 900px #fff, 184px 712px #fff, 1797px 1928px #fff, 507px 1861px #fff, 1849px 19px #fff, 1399px 200px #fff, 972px 497px #fff, 795px 1109px #fff, 746px 970px #fff, 1524px 972px #fff, 1631px 389px #fff, 1026px 1016px #fff, 1295px 862px #fff, 1258px 1876px #fff, 791px 189px #fff, 1519px 45px #fff, 592px 1405px #fff, 620px 130px #fff, 1044px 1171px #fff, 37px 1578px #fff, 1589px 86px #fff, 1024px 528px #fff, 1613px 568px #fff, 912px 1175px #fff, 1177px 133px #fff, 67px 1641px #fff, 1168px 357px #fff, 310px 1873px #fff, 1187px 573px #fff, 308px 1839px #fff, 565px 24px #fff, 1691px 1555px #fff, 1384px 1551px #fff, 179px 861px #fff, 1850px 1966px #fff, 1169px 1979px #fff, 1182px 1522px #fff, 616px 751px #fff, 1083px 908px #fff, 684px 766px #fff, 67px 955px #fff, 1813px 1714px #fff, 1256px 1413px #fff, 332px 803px #fff, 1670px 1921px #fff, 362px 211px #fff, 1513px 423px #fff, 1304px 1145px #fff, 1292px 1168px #fff, 611px 802px #fff, 1297px 575px #fff, 540px 1289px #fff, 1551px 1678px #fff, 1545px 237px #fff, 423px 138px #fff, 1088px 28px #fff, 642px 1637px #fff, 429px 1293px #fff, 1276px 1900px #fff, 1168px 1696px #fff, 847px 837px #fff, 151px 1395px #fff, 1490px 75px #fff, 1588px 131px #fff, 1739px 1358px #fff, 709px 624px #fff, 343px 502px #fff, 1342px 1690px #fff, 175px 1722px #fff, 964px 1299px #fff, 892px 1326px #fff, 519px 1142px #fff, 1014px 193px #fff, 1181px 360px #fff, 325px 139px #fff, 482px 1199px #fff, 613px 8px #fff, 1976px 1125px #fff, 346px 60px #fff, 1565px 818px #fff, 268px 1590px #fff, 213px 1666px #fff, 800px 464px #fff, 974px 1825px #fff, 1066px 23px #fff, 1995px 1499px #fff, 666px 1130px #fff, 1074px 1710px #fff, 1636px 1483px #fff, 1379px 1509px #fff, 1221px 887px #fff, 1857px 964px #fff, 1046px 993px #fff, 1875px 643px #fff, 1504px 1607px #fff, 1065px 641px #fff, 1095px 752px #fff, 566px 1737px #fff, 1972px 1778px #fff, 146px 1517px #fff, 1923px 588px #fff, 557px 881px #fff, 1885px 1950px #fff, 1739px 1598px #fff, 1048px 501px #fff, 1316px 705px #fff, 1900px 1697px #fff, 1187px 917px #fff, 1688px 1025px #fff, 648px 1634px #fff, 1002px 572px #fff, 603px 1995px #fff, 215px 693px #fff, 688px 1374px #fff, 1389px 1166px #fff, 1310px 1140px #fff, 245px 587px #fff, 845px 63px #fff, 296px 1646px #fff, 792px 350px #fff, 756px 1493px #fff, 1553px 1079px #fff, 850px 66px #fff, 963px 1904px #fff, 81px 207px #fff, 1776px 1634px #fff, 1759px 521px #fff, 1761px 1536px #fff, 601px 1485px #fff, 898px 153px #fff, 48px 648px #fff, 1644px 1109px #fff, 1974px 60px #fff, 1278px 653px #fff, 616px 432px #fff, 1179px 1849px #fff, 739px 677px #fff, 808px 1850px #fff, 1104px 827px #fff, 984px 888px #fff, 1027px 44px #fff, 1462px 1105px #fff, 902px 1486px #fff, 769px 441px #fff, 431px 1195px #fff, 4px 764px #fff, 562px 7px #fff, 952px 1744px #fff, 822px 971px #fff, 1016px 1804px #fff, 1429px 1161px #fff, 328px 1568px #fff, 101px 746px #fff, 649px 1484px #fff, 1903px 569px #fff, 733px 871px #fff, 1554px 505px #fff, 1076px 642px #fff, 609px 641px #fff, 996px 149px #fff, 1595px 758px #fff, 14px 1083px #fff, 261px 767px #fff, 1274px 1517px #fff, 1412px 215px #fff, 1651px 879px #fff, 284px 1633px #fff, 1439px 287px #fff, 1717px 270px #fff, 1107px 1063px #fff, 1521px 1831px #fff, 656px 1702px #fff, 25px 230px #fff, 1958px 1615px #fff, 646px 675px #fff, 1201px 343px #fff, 1918px 1064px #fff, 1932px 609px #fff, 1203px 900px #fff, 10px 575px #fff, 1582px 1828px #fff, 1184px 462px #fff, 1px 1619px #fff, 1440px 1071px #fff, 1844px 1913px #fff, 376px 1054px #fff, 1883px 1236px #fff, 571px 493px #fff, 354px 1701px #fff, 747px 60px #fff, 11px 1142px #fff, 1136px 1891px #fff, 1682px 473px #fff, 1537px 1520px #fff, 902px 836px #fff, 1313px 395px #fff, 534px 341px #fff, 230px 1614px #fff, 14px 1387px #fff, 1296px 1765px #fff, 1064px 1270px #fff, 761px 975px #fff, 1855px 335px #fff, 198px 110px #fff, 1660px 598px #fff, 1022px 933px #fff, 518px 356px #fff, 19px 865px #fff, 471px 830px #fff, 758px 358px #fff, 541px 1652px #fff, 320px 926px #fff, 425px 1826px #fff, 659px 353px #fff, 708px 778px #fff, 862px 641px #fff, 475px 1362px #fff, 1326px 1449px #fff, 446px 802px #fff, 391px 1169px #fff, 496px 39px #fff, 1534px 934px #fff, 1822px 1809px #fff, 1454px 237px #fff, 187px 1555px #fff, 1069px 1977px #fff, 1880px 1508px #fff, 279px 418px #fff, 1938px 1980px #fff, 1304px 530px #fff, 1763px 187px #fff, 1945px 1642px #fff, 311px 1490px #fff, 770px 1598px #fff, 263px 330px #fff, 1733px 1771px #fff, 978px 34px #fff, 325px 1776px #fff, 873px 1460px #fff, 365px 33px #fff, 913px 1999px #fff, 667px 1021px #fff, 27px 572px #fff, 950px 1858px #fff, 448px 1205px #fff, 1302px 1138px #fff, 1269px 932px #fff, 480px 132px #fff, 770px 1871px #fff, 952px 654px #fff, 623px 90px #fff, 419px 1683px #fff, 930px 794px #fff, 1327px 1651px #fff, 769px 1536px #fff, 895px 90px #fff, 599px 1268px #fff, 1645px 919px #fff, 1672px 1080px #fff, 1637px 1259px #fff, 243px 1182px #fff, 1509px 457px #fff, 1374px 1469px #fff, 751px 137px #fff, 1097px 1008px #fff, 1979px 1381px #fff, 981px 1825px #fff, 928px 1930px #fff, 632px 422px #fff, 812px 341px #fff, 1077px 1832px #fff, 203px 1452px #fff, 664px 1531px #fff, 1203px 57px #fff, 1654px 1203px #fff, 491px 174px #fff, 1507px 735px #fff, 964px 896px #fff, 52px 1718px #fff, 1435px 26px #fff, 753px 635px #fff, 890px 1847px #fff, 42px 1353px #fff, 717px 72px #fff, 1845px 1212px #fff, 344px 867px #fff, 418px 855px #fff, 899px 1124px #fff, 1798px 1582px #fff, 1774px 760px #fff, 908px 1567px #fff, 1647px 1210px #fff, 299px 82px #fff, 1179px 1317px #fff, 938px 1580px #fff, 82px 921px #fff, 657px 1596px #fff, 892px 1264px #fff, 1161px 819px #fff, 607px 1447px #fff, 605px 679px #fff, 1642px 595px #fff, 1963px 525px #fff, 1656px 1591px #fff, 1467px 1743px #fff, 167px 1420px #fff, 471px 492px #fff, 1077px 932px #fff, 774px 1282px #fff, 799px 701px #fff, 400px 258px #fff, 235px 1937px #fff, 894px 562px #fff, 1277px 907px #fff, 435px 1360px #fff, 507px 1253px #fff, 1022px 833px #fff, 351px 773px #fff, 1126px 1969px #fff, 1382px 1620px #fff, 411px 59px #fff, 187px 906px #fff, 644px 1364px #fff, 1721px 1451px #fff, 1879px 1390px #fff, 1396px 318px #fff, 1002px 891px #fff, 1930px 1454px #fff, 1952px 496px #fff, 1308px 1325px #fff, 343px 475px #fff, 285px 373px #fff, 1329px 1591px #fff, 901px 1875px #fff, 966px 254px #fff, 1624px 1577px #fff, 371px 589px #fff, 1918px 1494px #fff, 841px 589px #fff, 873px 1657px #fff, 970px 1697px #fff, 1354px 975px #fff, 807px 1099px #fff, 384px 1608px #fff, 1600px 1739px #fff, 110px 1310px #fff, 687px 1611px #fff, 324px 394px #fff, 1267px 224px #fff, 1122px 1919px #fff, 1753px 578px #fff, 611px 479px #fff, 1494px 475px #fff, 1595px 368px #fff, 304px 1379px #fff, 1663px 87px #fff, 1789px 1471px #fff, 941px 1861px #fff, 287px 657px #fff, 1882px 217px #fff, 1766px 1960px #fff, 144px 966px #fff, 872px 943px #fff, 1705px 1909px #fff, 1318px 1173px #fff, 1856px 1549px #fff, 1722px 1482px #fff, 196px 594px #fff, 355px 1182px #fff, 1242px 112px #fff, 226px 344px #fff, 674px 895px #fff, 210px 2px #fff, 1224px 488px #fff, 220px 617px #fff, 1857px 1348px #fff, 426px 1026px #fff, 1370px 720px #fff, 109px 440px #fff, 1940px 1575px #fff, 978px 1443px #fff, 308px 614px #fff, 1392px 1351px #fff, 635px 1231px #fff, 1132px 616px #fff, 756px 342px #fff, 1968px 765px #fff, 1020px 1877px #fff, 1998px 1325px #fff, 1296px 1303px #fff, 1817px 223px #fff, 1184px 907px #fff, 546px 845px #fff, 51px 705px #fff, 1421px 735px #fff, 1255px 700px #fff, 249px 1908px #fff, 1701px 351px #fff, 173px 1658px #fff, 1088px 1476px #fff, 1930px 1787px #fff, 689px 1312px #fff, 615px 1006px #fff, 1870px 1229px #fff, 1900px 546px #fff, 1416px 141px #fff, 1983px 945px #fff, 1104px 1351px #fff, 426px 701px #fff, 431px 1597px #fff, 893px 456px #fff, 1976px 1914px #fff, 1538px 673px #fff, 916px 1386px #fff, 304px 138px #fff, 1038px 681px #fff, 1349px 1740px #fff, 1231px 552px #fff, 35px 1435px #fff, 588px 652px #fff, 793px 575px #fff, 542px 926px #fff, 1252px 25px #fff, 831px 332px #fff, 718px 283px #fff, 1327px 1952px #fff, 1019px 704px #fff, 888px 1117px #fff, 1107px 1378px #fff, 532px 505px #fff, 1070px 552px #fff, 346px 645px #fff, 63px 1783px #fff, 775px 879px #fff, 165px 160px #fff, 788px 1225px #fff, 1562px 1520px #fff, 56px 1522px #fff, 439px 498px #fff, 1988px 1521px #fff, 254px 1363px #fff, 1162px 816px #fff, 219px 386px #fff, 1789px 1315px #fff, 1090px 1415px #fff, 1361px 315px #fff, 825px 1306px #fff, 92px 548px #fff, 1501px 1946px #fff, 350px 1735px #fff, 459px 1533px #fff, 1417px 931px #fff, 1849px 174px #fff, 220px 1084px #fff, 1357px 209px #fff, 1974px 358px #fff, 90px 808px #fff, 1247px 765px #fff, 1878px 725px #fff, 1415px 87px #fff, 1253px 943px #fff, 1455px 1919px #fff, 1321px 337px #fff, 1210px 1600px #fff, 1855px 1575px #fff, 325px 936px #fff, 1118px 892px #fff, 703px 294px #fff, 89px 891px #fff, 239px 1548px #fff, 280px 262px #fff, 1401px 555px #fff, 1092px 1638px #fff, 673px 1207px #fff, 1469px 1358px #fff, 1253px 1986px #fff, 1249px 1040px #fff, 253px 484px #fff, 1163px 775px #fff, 426px 162px #fff, 721px 1761px #fff, 369px 510px #fff, 702px 1599px #fff, 1883px 483px #fff, 680px 1604px #fff, 870px 1599px #fff, 976px 1808px #fff, 916px 477px #fff, 1223px 1636px #fff, 506px 993px #fff, 898px 1284px #fff, 1013px 290px #fff, 1189px 78px #fff, 25px 588px #fff, 960px 861px #fff, 28px 526px #fff, 959px 681px #fff, 1426px 1329px #fff, 294px 557px #fff, 1907px 1320px #fff, 1289px 1627px #fff, 124px 451px #fff, 967px 653px #fff, 892px 1460px #fff, 537px 1385px #fff, 197px 1954px #fff, 1543px 302px #fff, 747px 1953px #fff, 995px 1630px #fff, 1423px 1221px #fff, 1075px 983px #fff, 1556px 1739px #fff, 1068px 1425px #fff, 81px 550px #fff, 1668px 523px #fff, 1158px 438px #fff, 401px 1795px #fff, 537px 1072px #fff, 1px 326px #fff, 249px 118px #fff, 832px 1544px #fff, 240px 153px #fff, 651px 1077px #fff, 1656px 542px #fff, 1102px 606px #fff, 1583px 788px #fff, 1205px 1842px #fff, 1657px 1793px #fff, 1848px 1464px #fff, 1285px 1395px #fff, 662px 1227px #fff, 1790px 134px #fff, 577px 263px #fff, 383px 702px #fff, 1728px 1953px #fff, 417px 57px #fff, 1390px 574px #fff, 1024px 287px #fff, 1969px 753px #fff, 1239px 1036px #fff, 1063px 1313px #fff, 1784px 1519px #fff, 1665px 682px #fff, 806px 1437px #fff, 394px 917px #fff, 904px 666px #fff, 801px 1280px #fff, 1392px 1930px #fff, 1611px 1386px #fff, 1809px 1507px #fff, 1720px 1300px #fff, 1721px 1287px #fff, 969px 240px #fff, 3px 1070px #fff, 1198px 538px #fff, 1416px 1001px #fff, 1665px 1265px #fff, 1010px 1275px #fff, 772px 978px #fff, 1980px 980px #fff, 1283px 1573px #fff, 444px 516px #fff, 875px 737px #fff, 258px 716px #fff, 1698px 758px #fff, 644px 238px #fff, 19px 876px #fff, 355px 1327px #fff, 1602px 1846px #fff, 548px 534px #fff, 1498px 1473px #fff, 1389px 1136px #fff, 174px 771px #fff, 955px 1931px #fff, 403px 371px #fff, 1502px 794px #fff, 117px 876px #fff, 536px 778px #fff, 67px 393px #fff, 119px 1918px #fff, 1912px 1663px #fff, 1141px 245px #fff, 1105px 130px #fff, 1218px 1608px #fff, 662px 1502px #fff, 1907px 927px #fff, 521px 109px #fff, 1885px 362px #fff, 1785px 1935px #fff, 781px 427px #fff, 1446px 1991px #fff, 164px 1539px #fff, 1807px 1795px #fff, 1922px 890px #fff, 1245px 933px #fff, 446px 450px #fff, 1743px 79px #fff, 1959px 310px #fff, 1348px 749px #fff, 1954px 128px #fff, 1980px 1030px #fff, 1850px 302px #fff, 1074px 922px #fff, 174px 403px #fff, 1579px 733px #fff, 653px 1958px #fff, 1511px 1943px #fff, 1037px 741px #fff, 602px 1384px #fff, 103px 402px #fff, 1722px 1417px #fff, 1732px 1916px #fff, 1743px 1803px #fff, 381px 721px #fff, 964px 1700px #fff, 1070px 341px #fff, 1376px 1258px #fff, 1884px 570px #fff, 940px 280px #fff, 1484px 1658px #fff, 1806px 1875px #fff, 1054px 917px #fff, 1672px 103px #fff, 783px 574px #fff, 98px 347px #fff, 555px 1136px #fff, 1403px 1237px #fff, 1203px 339px #fff, 572px 35px #fff, 932px 1783px #fff, 1527px 1850px #fff, 1959px 1109px #fff, 892px 623px #fff, 211px 1388px #fff, 1581px 1806px #fff, 868px 1053px #fff, 1243px 1997px #fff, 1004px 522px #fff, 1241px 1707px #fff, 376px 282px #fff, 537px 878px #fff, 1948px 979px #fff, 532px 688px #fff, 273px 958px #fff, 581px 927px #fff, 1060px 887px #fff, 486px 1467px #fff, 1122px 1834px #fff, 1650px 1763px #fff, 532px 302px #fff, 314px 1111px #fff, 1888px 683px #fff, 1856px 1040px #fff, 1780px 1338px #fff, 24px 1564px #fff, 1096px 1808px #fff, 1202px 1968px #fff, 214px 992px #fff, 728px 515px #fff, 247px 278px #fff, 1670px 45px #fff, 442px 1579px #fff, 1143px 30px #fff, 612px 72px #fff, 1177px 1303px #fff, 1898px 1255px #fff, 378px 1667px #fff, 326px 1929px #fff, 1257px 766px #fff, 1363px 1170px #fff, 1090px 1667px #fff, 711px 293px #fff, 249px 1406px #fff, 1589px 565px #fff, 1451px 29px #fff, 1171px 1459px #fff, 1294px 1214px #fff, 342px 942px #fff, 1945px 353px #fff, 741px 1185px #fff, 894px 1453px #fff, 593px 1584px #fff, 518px 630px #fff, 393px 756px #fff, 34px 608px #fff;
    animation: animStar 50s linear infinite;
}

body.DarkMode #stars:after {
    content: " ";
    position: absolute;
    top: 2000px;
    width: 1px;
    height: 1px;
    background: 0 0;
    box-shadow: 1804px 1265px #fff, 365px 332px #fff, 86px 1888px #fff, 1888px 484px #fff, 199px 1489px #fff, 1459px 1010px #fff, 807px 388px #fff, 855px 558px #fff, 83px 1095px #fff, 1418px 377px #fff, 677px 886px #fff, 862px 1709px #fff, 1058px 1085px #fff, 50px 1772px #fff, 1941px 1544px #fff, 377px 900px #fff, 184px 712px #fff, 1797px 1928px #fff, 507px 1861px #fff, 1849px 19px #fff, 1399px 200px #fff, 972px 497px #fff, 795px 1109px #fff, 746px 970px #fff, 1524px 972px #fff, 1631px 389px #fff, 1026px 1016px #fff, 1295px 862px #fff, 1258px 1876px #fff, 791px 189px #fff, 1519px 45px #fff, 592px 1405px #fff, 620px 130px #fff, 1044px 1171px #fff, 37px 1578px #fff, 1589px 86px #fff, 1024px 528px #fff, 1613px 568px #fff, 912px 1175px #fff, 1177px 133px #fff, 67px 1641px #fff, 1168px 357px #fff, 310px 1873px #fff, 1187px 573px #fff, 308px 1839px #fff, 565px 24px #fff, 1691px 1555px #fff, 1384px 1551px #fff, 179px 861px #fff, 1850px 1966px #fff, 1169px 1979px #fff, 1182px 1522px #fff, 616px 751px #fff, 1083px 908px #fff, 684px 766px #fff, 67px 955px #fff, 1813px 1714px #fff, 1256px 1413px #fff, 332px 803px #fff, 1670px 1921px #fff, 362px 211px #fff, 1513px 423px #fff, 1304px 1145px #fff, 1292px 1168px #fff, 611px 802px #fff, 1297px 575px #fff, 540px 1289px #fff, 1551px 1678px #fff, 1545px 237px #fff, 423px 138px #fff, 1088px 28px #fff, 642px 1637px #fff, 429px 1293px #fff, 1276px 1900px #fff, 1168px 1696px #fff, 847px 837px #fff, 151px 1395px #fff, 1490px 75px #fff, 1588px 131px #fff, 1739px 1358px #fff, 709px 624px #fff, 343px 502px #fff, 1342px 1690px #fff, 175px 1722px #fff, 964px 1299px #fff, 892px 1326px #fff, 519px 1142px #fff, 1014px 193px #fff, 1181px 360px #fff, 325px 139px #fff, 482px 1199px #fff, 613px 8px #fff, 1976px 1125px #fff, 346px 60px #fff, 1565px 818px #fff, 268px 1590px #fff, 213px 1666px #fff, 800px 464px #fff, 974px 1825px #fff, 1066px 23px #fff, 1995px 1499px #fff, 666px 1130px #fff, 1074px 1710px #fff, 1636px 1483px #fff, 1379px 1509px #fff, 1221px 887px #fff, 1857px 964px #fff, 1046px 993px #fff, 1875px 643px #fff, 1504px 1607px #fff, 1065px 641px #fff, 1095px 752px #fff, 566px 1737px #fff, 1972px 1778px #fff, 146px 1517px #fff, 1923px 588px #fff, 557px 881px #fff, 1885px 1950px #fff, 1739px 1598px #fff, 1048px 501px #fff, 1316px 705px #fff, 1900px 1697px #fff, 1187px 917px #fff, 1688px 1025px #fff, 648px 1634px #fff, 1002px 572px #fff, 603px 1995px #fff, 215px 693px #fff, 688px 1374px #fff, 1389px 1166px #fff, 1310px 1140px #fff, 245px 587px #fff, 845px 63px #fff, 296px 1646px #fff, 792px 350px #fff, 756px 1493px #fff, 1553px 1079px #fff, 850px 66px #fff, 963px 1904px #fff, 81px 207px #fff, 1776px 1634px #fff, 1759px 521px #fff, 1761px 1536px #fff, 601px 1485px #fff, 898px 153px #fff, 48px 648px #fff, 1644px 1109px #fff, 1974px 60px #fff, 1278px 653px #fff, 616px 432px #fff, 1179px 1849px #fff, 739px 677px #fff, 808px 1850px #fff, 1104px 827px #fff, 984px 888px #fff, 1027px 44px #fff, 1462px 1105px #fff, 902px 1486px #fff, 769px 441px #fff, 431px 1195px #fff, 4px 764px #fff, 562px 7px #fff, 952px 1744px #fff, 822px 971px #fff, 1016px 1804px #fff, 1429px 1161px #fff, 328px 1568px #fff, 101px 746px #fff, 649px 1484px #fff, 1903px 569px #fff, 733px 871px #fff, 1554px 505px #fff, 1076px 642px #fff, 609px 641px #fff, 996px 149px #fff, 1595px 758px #fff, 14px 1083px #fff, 261px 767px #fff, 1274px 1517px #fff, 1412px 215px #fff, 1651px 879px #fff, 284px 1633px #fff, 1439px 287px #fff, 1717px 270px #fff, 1107px 1063px #fff, 1521px 1831px #fff, 656px 1702px #fff, 25px 230px #fff, 1958px 1615px #fff, 646px 675px #fff, 1201px 343px #fff, 1918px 1064px #fff, 1932px 609px #fff, 1203px 900px #fff, 10px 575px #fff, 1582px 1828px #fff, 1184px 462px #fff, 1px 1619px #fff, 1440px 1071px #fff, 1844px 1913px #fff, 376px 1054px #fff, 1883px 1236px #fff, 571px 493px #fff, 354px 1701px #fff, 747px 60px #fff, 11px 1142px #fff, 1136px 1891px #fff, 1682px 473px #fff, 1537px 1520px #fff, 902px 836px #fff, 1313px 395px #fff, 534px 341px #fff, 230px 1614px #fff, 14px 1387px #fff, 1296px 1765px #fff, 1064px 1270px #fff, 761px 975px #fff, 1855px 335px #fff, 198px 110px #fff, 1660px 598px #fff, 1022px 933px #fff, 518px 356px #fff, 19px 865px #fff, 471px 830px #fff, 758px 358px #fff, 541px 1652px #fff, 320px 926px #fff, 425px 1826px #fff, 659px 353px #fff, 708px 778px #fff, 862px 641px #fff, 475px 1362px #fff, 1326px 1449px #fff, 446px 802px #fff, 391px 1169px #fff, 496px 39px #fff, 1534px 934px #fff, 1822px 1809px #fff, 1454px 237px #fff, 187px 1555px #fff, 1069px 1977px #fff, 1880px 1508px #fff, 279px 418px #fff, 1938px 1980px #fff, 1304px 530px #fff, 1763px 187px #fff, 1945px 1642px #fff, 311px 1490px #fff, 770px 1598px #fff, 263px 330px #fff, 1733px 1771px #fff, 978px 34px #fff, 325px 1776px #fff, 873px 1460px #fff, 365px 33px #fff, 913px 1999px #fff, 667px 1021px #fff, 27px 572px #fff, 950px 1858px #fff, 448px 1205px #fff, 1302px 1138px #fff, 1269px 932px #fff, 480px 132px #fff, 770px 1871px #fff, 952px 654px #fff, 623px 90px #fff, 419px 1683px #fff, 930px 794px #fff, 1327px 1651px #fff, 769px 1536px #fff, 895px 90px #fff, 599px 1268px #fff, 1645px 919px #fff, 1672px 1080px #fff, 1637px 1259px #fff, 243px 1182px #fff, 1509px 457px #fff, 1374px 1469px #fff, 751px 137px #fff, 1097px 1008px #fff, 1979px 1381px #fff, 981px 1825px #fff, 928px 1930px #fff, 632px 422px #fff, 812px 341px #fff, 1077px 1832px #fff, 203px 1452px #fff, 664px 1531px #fff, 1203px 57px #fff, 1654px 1203px #fff, 491px 174px #fff, 1507px 735px #fff, 964px 896px #fff, 52px 1718px #fff, 1435px 26px #fff, 753px 635px #fff, 890px 1847px #fff, 42px 1353px #fff, 717px 72px #fff, 1845px 1212px #fff, 344px 867px #fff, 418px 855px #fff, 899px 1124px #fff, 1798px 1582px #fff, 1774px 760px #fff, 908px 1567px #fff, 1647px 1210px #fff, 299px 82px #fff, 1179px 1317px #fff, 938px 1580px #fff, 82px 921px #fff, 657px 1596px #fff, 892px 1264px #fff, 1161px 819px #fff, 607px 1447px #fff, 605px 679px #fff, 1642px 595px #fff, 1963px 525px #fff, 1656px 1591px #fff, 1467px 1743px #fff, 167px 1420px #fff, 471px 492px #fff, 1077px 932px #fff, 774px 1282px #fff, 799px 701px #fff, 400px 258px #fff, 235px 1937px #fff, 894px 562px #fff, 1277px 907px #fff, 435px 1360px #fff, 507px 1253px #fff, 1022px 833px #fff, 351px 773px #fff, 1126px 1969px #fff, 1382px 1620px #fff, 411px 59px #fff, 187px 906px #fff, 644px 1364px #fff, 1721px 1451px #fff, 1879px 1390px #fff, 1396px 318px #fff, 1002px 891px #fff, 1930px 1454px #fff, 1952px 496px #fff, 1308px 1325px #fff, 343px 475px #fff, 285px 373px #fff, 1329px 1591px #fff, 901px 1875px #fff, 966px 254px #fff, 1624px 1577px #fff, 371px 589px #fff, 1918px 1494px #fff, 841px 589px #fff, 873px 1657px #fff, 970px 1697px #fff, 1354px 975px #fff, 807px 1099px #fff, 384px 1608px #fff, 1600px 1739px #fff, 110px 1310px #fff, 687px 1611px #fff, 324px 394px #fff, 1267px 224px #fff, 1122px 1919px #fff, 1753px 578px #fff, 611px 479px #fff, 1494px 475px #fff, 1595px 368px #fff, 304px 1379px #fff, 1663px 87px #fff, 1789px 1471px #fff, 941px 1861px #fff, 287px 657px #fff, 1882px 217px #fff, 1766px 1960px #fff, 144px 966px #fff, 872px 943px #fff, 1705px 1909px #fff, 1318px 1173px #fff, 1856px 1549px #fff, 1722px 1482px #fff, 196px 594px #fff, 355px 1182px #fff, 1242px 112px #fff, 226px 344px #fff, 674px 895px #fff, 210px 2px #fff, 1224px 488px #fff, 220px 617px #fff, 1857px 1348px #fff, 426px 1026px #fff, 1370px 720px #fff, 109px 440px #fff, 1940px 1575px #fff, 978px 1443px #fff, 308px 614px #fff, 1392px 1351px #fff, 635px 1231px #fff, 1132px 616px #fff, 756px 342px #fff, 1968px 765px #fff, 1020px 1877px #fff, 1998px 1325px #fff, 1296px 1303px #fff, 1817px 223px #fff, 1184px 907px #fff, 546px 845px #fff, 51px 705px #fff, 1421px 735px #fff, 1255px 700px #fff, 249px 1908px #fff, 1701px 351px #fff, 173px 1658px #fff, 1088px 1476px #fff, 1930px 1787px #fff, 689px 1312px #fff, 615px 1006px #fff, 1870px 1229px #fff, 1900px 546px #fff, 1416px 141px #fff, 1983px 945px #fff, 1104px 1351px #fff, 426px 701px #fff, 431px 1597px #fff, 893px 456px #fff, 1976px 1914px #fff, 1538px 673px #fff, 916px 1386px #fff, 304px 138px #fff, 1038px 681px #fff, 1349px 1740px #fff, 1231px 552px #fff, 35px 1435px #fff, 588px 652px #fff, 793px 575px #fff, 542px 926px #fff, 1252px 25px #fff, 831px 332px #fff, 718px 283px #fff, 1327px 1952px #fff, 1019px 704px #fff, 888px 1117px #fff, 1107px 1378px #fff, 532px 505px #fff, 1070px 552px #fff, 346px 645px #fff, 63px 1783px #fff, 775px 879px #fff, 165px 160px #fff, 788px 1225px #fff, 1562px 1520px #fff, 56px 1522px #fff, 439px 498px #fff, 1988px 1521px #fff, 254px 1363px #fff, 1162px 816px #fff, 219px 386px #fff, 1789px 1315px #fff, 1090px 1415px #fff, 1361px 315px #fff, 825px 1306px #fff, 92px 548px #fff, 1501px 1946px #fff, 350px 1735px #fff, 459px 1533px #fff, 1417px 931px #fff, 1849px 174px #fff, 220px 1084px #fff, 1357px 209px #fff, 1974px 358px #fff, 90px 808px #fff, 1247px 765px #fff, 1878px 725px #fff, 1415px 87px #fff, 1253px 943px #fff, 1455px 1919px #fff, 1321px 337px #fff, 1210px 1600px #fff, 1855px 1575px #fff, 325px 936px #fff, 1118px 892px #fff, 703px 294px #fff, 89px 891px #fff, 239px 1548px #fff, 280px 262px #fff, 1401px 555px #fff, 1092px 1638px #fff, 673px 1207px #fff, 1469px 1358px #fff, 1253px 1986px #fff, 1249px 1040px #fff, 253px 484px #fff, 1163px 775px #fff, 426px 162px #fff, 721px 1761px #fff, 369px 510px #fff, 702px 1599px #fff, 1883px 483px #fff, 680px 1604px #fff, 870px 1599px #fff, 976px 1808px #fff, 916px 477px #fff, 1223px 1636px #fff, 506px 993px #fff, 898px 1284px #fff, 1013px 290px #fff, 1189px 78px #fff, 25px 588px #fff, 960px 861px #fff, 28px 526px #fff, 959px 681px #fff, 1426px 1329px #fff, 294px 557px #fff, 1907px 1320px #fff, 1289px 1627px #fff, 124px 451px #fff, 967px 653px #fff, 892px 1460px #fff, 537px 1385px #fff, 197px 1954px #fff, 1543px 302px #fff, 747px 1953px #fff, 995px 1630px #fff, 1423px 1221px #fff, 1075px 983px #fff, 1556px 1739px #fff, 1068px 1425px #fff, 81px 550px #fff, 1668px 523px #fff, 1158px 438px #fff, 401px 1795px #fff, 537px 1072px #fff, 1px 326px #fff, 249px 118px #fff, 832px 1544px #fff, 240px 153px #fff, 651px 1077px #fff, 1656px 542px #fff, 1102px 606px #fff, 1583px 788px #fff, 1205px 1842px #fff, 1657px 1793px #fff, 1848px 1464px #fff, 1285px 1395px #fff, 662px 1227px #fff, 1790px 134px #fff, 577px 263px #fff, 383px 702px #fff, 1728px 1953px #fff, 417px 57px #fff, 1390px 574px #fff, 1024px 287px #fff, 1969px 753px #fff, 1239px 1036px #fff, 1063px 1313px #fff, 1784px 1519px #fff, 1665px 682px #fff, 806px 1437px #fff, 394px 917px #fff, 904px 666px #fff, 801px 1280px #fff, 1392px 1930px #fff, 1611px 1386px #fff, 1809px 1507px #fff, 1720px 1300px #fff, 1721px 1287px #fff, 969px 240px #fff, 3px 1070px #fff, 1198px 538px #fff, 1416px 1001px #fff, 1665px 1265px #fff, 1010px 1275px #fff, 772px 978px #fff, 1980px 980px #fff, 1283px 1573px #fff, 444px 516px #fff, 875px 737px #fff, 258px 716px #fff, 1698px 758px #fff, 644px 238px #fff, 19px 876px #fff, 355px 1327px #fff, 1602px 1846px #fff, 548px 534px #fff, 1498px 1473px #fff, 1389px 1136px #fff, 174px 771px #fff, 955px 1931px #fff, 403px 371px #fff, 1502px 794px #fff, 117px 876px #fff, 536px 778px #fff, 67px 393px #fff, 119px 1918px #fff, 1912px 1663px #fff, 1141px 245px #fff, 1105px 130px #fff, 1218px 1608px #fff, 662px 1502px #fff, 1907px 927px #fff, 521px 109px #fff, 1885px 362px #fff, 1785px 1935px #fff, 781px 427px #fff, 1446px 1991px #fff, 164px 1539px #fff, 1807px 1795px #fff, 1922px 890px #fff, 1245px 933px #fff, 446px 450px #fff, 1743px 79px #fff, 1959px 310px #fff, 1348px 749px #fff, 1954px 128px #fff, 1980px 1030px #fff, 1850px 302px #fff, 1074px 922px #fff, 174px 403px #fff, 1579px 733px #fff, 653px 1958px #fff, 1511px 1943px #fff, 1037px 741px #fff, 602px 1384px #fff, 103px 402px #fff, 1722px 1417px #fff, 1732px 1916px #fff, 1743px 1803px #fff, 381px 721px #fff, 964px 1700px #fff, 1070px 341px #fff, 1376px 1258px #fff, 1884px 570px #fff, 940px 280px #fff, 1484px 1658px #fff, 1806px 1875px #fff, 1054px 917px #fff, 1672px 103px #fff, 783px 574px #fff, 98px 347px #fff, 555px 1136px #fff, 1403px 1237px #fff, 1203px 339px #fff, 572px 35px #fff, 932px 1783px #fff, 1527px 1850px #fff, 1959px 1109px #fff, 892px 623px #fff, 211px 1388px #fff, 1581px 1806px #fff, 868px 1053px #fff, 1243px 1997px #fff, 1004px 522px #fff, 1241px 1707px #fff, 376px 282px #fff, 537px 878px #fff, 1948px 979px #fff, 532px 688px #fff, 273px 958px #fff, 581px 927px #fff, 1060px 887px #fff, 486px 1467px #fff, 1122px 1834px #fff, 1650px 1763px #fff, 532px 302px #fff, 314px 1111px #fff, 1888px 683px #fff, 1856px 1040px #fff, 1780px 1338px #fff, 24px 1564px #fff, 1096px 1808px #fff, 1202px 1968px #fff, 214px 992px #fff, 728px 515px #fff, 247px 278px #fff, 1670px 45px #fff, 442px 1579px #fff, 1143px 30px #fff, 612px 72px #fff, 1177px 1303px #fff, 1898px 1255px #fff, 378px 1667px #fff, 326px 1929px #fff, 1257px 766px #fff, 1363px 1170px #fff, 1090px 1667px #fff, 711px 293px #fff, 249px 1406px #fff, 1589px 565px #fff, 1451px 29px #fff, 1171px 1459px #fff, 1294px 1214px #fff, 342px 942px #fff, 1945px 353px #fff, 741px 1185px #fff, 894px 1453px #fff, 593px 1584px #fff, 518px 630px #fff, 393px 756px #fff, 34px 608px #fff;
}

body.DarkMode #stars2 {
    width: 2px;
    height: 2px;
    background: 0 0;
    box-shadow: 114px 658px #fff, 236px 768px #fff, 1130px 1503px #fff, 486px 592px #fff, 1353px 1407px #fff, 1583px 1741px #fff, 450px 1479px #fff, 1845px 327px #fff, 1520px 361px #fff, 580px 1699px #fff, 1277px 1233px #fff, 1697px 943px #fff, 568px 1135px #fff, 1273px 263px #fff, 788px 126px #fff, 1834px 1911px #fff, 1147px 1652px #fff, 651px 567px #fff, 79px 1897px #fff, 1590px 666px #fff, 1362px 566px #fff, 275px 367px #fff, 556px 479px #fff, 1063px 476px #fff, 1337px 1119px #fff, 1780px 1109px #fff, 1323px 1655px #fff, 1740px 1165px #fff, 525px 60px #fff, 1513px 1484px #fff, 708px 280px #fff, 429px 475px #fff, 563px 1360px #fff, 1580px 697px #fff, 1702px 1164px #fff, 1649px 1952px #fff, 1580px 1812px #fff, 70px 1190px #fff, 1100px 98px #fff, 1232px 1896px #fff, 851px 1047px #fff, 851px 30px #fff, 596px 1486px #fff, 666px 526px #fff, 1855px 1342px #fff, 80px 531px #fff, 248px 1804px #fff, 1990px 263px #fff, 1796px 1640px #fff, 1502px 862px #fff, 1780px 488px #fff, 1881px 1191px #fff, 1063px 876px #fff, 1614px 1073px #fff, 1414px 666px #fff, 1865px 289px #fff, 687px 352px #fff, 1329px 1312px #fff, 279px 136px #fff, 475px 756px #fff, 1177px 435px #fff, 1264px 921px #fff, 467px 1496px #fff, 391px 1359px #fff, 666px 1083px #fff, 1526px 1251px #fff, 594px 564px #fff, 991px 525px #fff, 1511px 875px #fff, 1935px 1049px #fff, 1471px 1430px #fff, 959px 604px #fff, 1685px 72px #fff, 1505px 1876px #fff, 509px 1627px #fff, 1065px 978px #fff, 1860px 884px #fff, 1038px 464px #fff, 1051px 106px #fff, 1056px 728px #fff, 1953px 45px #fff, 1483px 638px #fff, 559px 845px #fff, 1184px 922px #fff, 1320px 1117px #fff, 1572px 747px #fff, 1971px 43px #fff, 665px 13px #fff, 1457px 1153px #fff, 848px 154px #fff, 1039px 1837px #fff, 878px 795px #fff, 1286px 1705px #fff, 1946px 1143px #fff, 1114px 1166px #fff, 1747px 874px #fff, 1894px 636px #fff, 1316px 541px #fff, 1953px 1620px #fff, 1446px 1773px #fff, 974px 833px #fff, 1814px 1211px #fff, 102px 335px #fff, 327px 1868px #fff, 348px 548px #fff, 353px 1540px #fff, 1212px 1872px #fff, 1968px 129px #fff, 1531px 644px #fff, 1939px 559px #fff, 1397px 1876px #fff, 1446px 1446px #fff, 1721px 603px #fff, 924px 1171px #fff, 1086px 1954px #fff, 1798px 310px #fff, 21px 1595px #fff, 1462px 1948px #fff, 149px 1752px #fff, 804px 318px #fff, 1262px 636px #fff, 1051px 100px #fff, 392px 560px #fff, 654px 1236px #fff, 1889px 1159px #fff, 498px 394px #fff, 522px 1889px #fff, 1198px 579px #fff, 1437px 1866px #fff, 1049px 1064px #fff, 286px 921px #fff, 993px 1790px #fff, 1557px 1997px #fff, 1525px 532px #fff, 481px 1561px #fff, 790px 683px #fff, 141px 17px #fff, 1202px 28px #fff, 518px 1927px #fff, 90px 1677px #fff, 1258px 370px #fff, 1379px 1536px #fff, 607px 474px #fff, 163px 139px #fff, 1025px 1359px #fff, 815px 845px #fff, 231px 1212px #fff, 192px 806px #fff, 313px 1946px #fff, 1132px 1808px #fff, 624px 767px #fff, 379px 722px #fff, 733px 1847px #fff, 628px 1517px #fff, 1559px 929px #fff, 234px 397px #fff, 1230px 1231px #fff, 849px 726px #fff, 1148px 786px #fff, 546px 1533px #fff, 477px 822px #fff, 1325px 480px #fff, 972px 383px #fff, 334px 958px #fff, 1032px 664px #fff, 1781px 40px #fff, 38px 1335px #fff, 1634px 1691px #fff, 1061px 680px #fff, 1319px 304px #fff, 82px 1776px #fff, 1302px 509px #fff, 1231px 746px #fff, 1264px 1509px #fff, 980px 495px #fff, 1153px 1381px #fff, 1981px 1918px #fff, 70px 113px #fff, 390px 736px #fff, 1882px 1925px #fff, 1380px 1326px #fff, 257px 1681px #fff, 860px 998px #fff, 518px 1136px #fff, 168px 905px #fff, 500px 1882px #fff, 1012px 1572px #fff, 349px 1916px #fff, 905px 1339px #fff, 1940px 1803px #fff, 23px 1159px #fff, 9px 1559px #fff, 1658px 776px #fff, 820px 1361px #fff, 171px 983px #fff, 580px 1902px #fff, 1268px 263px #fff, 1734px 994px #fff, 1872px 29px #fff, 1475px 435px #fff;
    animation: animStar 100s linear infinite;
}

body.DarkMode #stars2:after {
    content: " ";
    position: absolute;
    top: 2000px;
    width: 2px;
    height: 2px;
    background: 0 0;
    box-shadow: 114px 658px #fff, 236px 768px #fff, 1130px 1503px #fff, 486px 592px #fff, 1353px 1407px #fff, 1583px 1741px #fff, 450px 1479px #fff, 1845px 327px #fff, 1520px 361px #fff, 580px 1699px #fff, 1277px 1233px #fff, 1697px 943px #fff, 568px 1135px #fff, 1273px 263px #fff, 788px 126px #fff, 1834px 1911px #fff, 1147px 1652px #fff, 651px 567px #fff, 79px 1897px #fff, 1590px 666px #fff, 1362px 566px #fff, 275px 367px #fff, 556px 479px #fff, 1063px 476px #fff, 1337px 1119px #fff, 1780px 1109px #fff, 1323px 1655px #fff, 1740px 1165px #fff, 525px 60px #fff, 1513px 1484px #fff, 708px 280px #fff, 429px 475px #fff, 563px 1360px #fff, 1580px 697px #fff, 1702px 1164px #fff, 1649px 1952px #fff, 1580px 1812px #fff, 70px 1190px #fff, 1100px 98px #fff, 1232px 1896px #fff, 851px 1047px #fff, 851px 30px #fff, 596px 1486px #fff, 666px 526px #fff, 1855px 1342px #fff, 80px 531px #fff, 248px 1804px #fff, 1990px 263px #fff, 1796px 1640px #fff, 1502px 862px #fff, 1780px 488px #fff, 1881px 1191px #fff, 1063px 876px #fff, 1614px 1073px #fff, 1414px 666px #fff, 1865px 289px #fff, 687px 352px #fff, 1329px 1312px #fff, 279px 136px #fff, 475px 756px #fff, 1177px 435px #fff, 1264px 921px #fff, 467px 1496px #fff, 391px 1359px #fff, 666px 1083px #fff, 1526px 1251px #fff, 594px 564px #fff, 991px 525px #fff, 1511px 875px #fff, 1935px 1049px #fff, 1471px 1430px #fff, 959px 604px #fff, 1685px 72px #fff, 1505px 1876px #fff, 509px 1627px #fff, 1065px 978px #fff, 1860px 884px #fff, 1038px 464px #fff, 1051px 106px #fff, 1056px 728px #fff, 1953px 45px #fff, 1483px 638px #fff, 559px 845px #fff, 1184px 922px #fff, 1320px 1117px #fff, 1572px 747px #fff, 1971px 43px #fff, 665px 13px #fff, 1457px 1153px #fff, 848px 154px #fff, 1039px 1837px #fff, 878px 795px #fff, 1286px 1705px #fff, 1946px 1143px #fff, 1114px 1166px #fff, 1747px 874px #fff, 1894px 636px #fff, 1316px 541px #fff, 1953px 1620px #fff, 1446px 1773px #fff, 974px 833px #fff, 1814px 1211px #fff, 102px 335px #fff, 327px 1868px #fff, 348px 548px #fff, 353px 1540px #fff, 1212px 1872px #fff, 1968px 129px #fff, 1531px 644px #fff, 1939px 559px #fff, 1397px 1876px #fff, 1446px 1446px #fff, 1721px 603px #fff, 924px 1171px #fff, 1086px 1954px #fff, 1798px 310px #fff, 21px 1595px #fff, 1462px 1948px #fff, 149px 1752px #fff, 804px 318px #fff, 1262px 636px #fff, 1051px 100px #fff, 392px 560px #fff, 654px 1236px #fff, 1889px 1159px #fff, 498px 394px #fff, 522px 1889px #fff, 1198px 579px #fff, 1437px 1866px #fff, 1049px 1064px #fff, 286px 921px #fff, 993px 1790px #fff, 1557px 1997px #fff, 1525px 532px #fff, 481px 1561px #fff, 790px 683px #fff, 141px 17px #fff, 1202px 28px #fff, 518px 1927px #fff, 90px 1677px #fff, 1258px 370px #fff, 1379px 1536px #fff, 607px 474px #fff, 163px 139px #fff, 1025px 1359px #fff, 815px 845px #fff, 231px 1212px #fff, 192px 806px #fff, 313px 1946px #fff, 1132px 1808px #fff, 624px 767px #fff, 379px 722px #fff, 733px 1847px #fff, 628px 1517px #fff, 1559px 929px #fff, 234px 397px #fff, 1230px 1231px #fff, 849px 726px #fff, 1148px 786px #fff, 546px 1533px #fff, 477px 822px #fff, 1325px 480px #fff, 972px 383px #fff, 334px 958px #fff, 1032px 664px #fff, 1781px 40px #fff, 38px 1335px #fff, 1634px 1691px #fff, 1061px 680px #fff, 1319px 304px #fff, 82px 1776px #fff, 1302px 509px #fff, 1231px 746px #fff, 1264px 1509px #fff, 980px 495px #fff, 1153px 1381px #fff, 1981px 1918px #fff, 70px 113px #fff, 390px 736px #fff, 1882px 1925px #fff, 1380px 1326px #fff, 257px 1681px #fff, 860px 998px #fff, 518px 1136px #fff, 168px 905px #fff, 500px 1882px #fff, 1012px 1572px #fff, 349px 1916px #fff, 905px 1339px #fff, 1940px 1803px #fff, 23px 1159px #fff, 9px 1559px #fff, 1658px 776px #fff, 820px 1361px #fff, 171px 983px #fff, 580px 1902px #fff, 1268px 263px #fff, 1734px 994px #fff, 1872px 29px #fff, 1475px 435px #fff;
}

body.DarkMode #stars3 {
    width: 3px;
    height: 3px;
    background: 0 0;
    box-shadow: 519px 875px #fff, 1497px 751px #fff, 1256px 88px #fff, 1168px 1791px #fff, 1884px 109px #fff, 1465px 451px #fff, 450px 370px #fff, 1560px 703px #fff, 1788px 1997px #fff, 1047px 963px #fff, 1281px 119px #fff, 439px 96px #fff, 164px 1956px #fff, 1360px 930px #fff, 1387px 347px #fff, 1073px 1970px #fff, 1296px 284px #fff, 25px 1602px #fff, 455px 944px #fff, 1177px 738px #fff, 633px 1142px #fff, 1730px 1079px #fff, 1283px 1606px #fff, 674px 1186px #fff, 513px 166px #fff, 1077px 636px #fff, 1811px 580px #fff, 971px 1789px #fff, 694px 1756px #fff, 703px 1138px #fff, 1290px 942px #fff, 351px 1509px #fff, 1904px 790px #fff, 68px 819px #fff, 1097px 362px #fff, 1035px 331px #fff, 180px 940px #fff, 1776px 1229px #fff, 1487px 781px #fff, 1131px 1765px #fff, 1684px 536px #fff, 939px 367px #fff, 1102px 1481px #fff, 741px 887px #fff, 167px 1132px #fff, 1756px 529px #fff, 608px 758px #fff, 541px 1025px #fff, 1976px 505px #fff, 1349px 1257px #fff, 815px 1388px #fff, 505px 1351px #fff, 33px 1945px #fff, 861px 1695px #fff, 678px 1360px #fff, 1615px 727px #fff, 1138px 726px #fff, 30px 293px #fff, 1624px 1044px #fff, 683px 1242px #fff, 1781px 1758px #fff, 906px 1328px #fff, 1066px 1764px #fff, 1568px 664px #fff, 1027px 1876px #fff, 775px 1099px #fff, 1605px 208px #fff, 730px 837px #fff, 1475px 1482px #fff, 871px 1759px #fff, 1240px 15px #fff, 1987px 705px #fff, 302px 1049px #fff, 475px 1015px #fff, 1843px 1296px #fff, 493px 631px #fff, 1613px 164px #fff, 1863px 156px #fff, 1479px 423px #fff, 202px 1499px #fff, 886px 969px #fff, 904px 930px #fff, 1853px 535px #fff, 726px 914px #fff, 435px 1205px #fff, 1732px 1824px #fff, 1212px 667px #fff, 499px 31px #fff, 552px 594px #fff, 1715px 1814px #fff, 775px 908px #fff, 1949px 921px #fff, 1267px 718px #fff, 1830px 1960px #fff, 338px 1325px #fff, 466px 1120px #fff, 140px 1675px #fff, 1919px 664px #fff, 1136px 771px #fff, 1888px 1302px #fff;
    animation: animStar 150s linear infinite;
}

body.DarkMode #stars3:after {
    content: " ";
    position: absolute;
    top: 2000px;
    width: 3px;
    height: 3px;
    background: 0 0;
    box-shadow: 519px 875px #fff, 1497px 751px #fff, 1256px 88px #fff, 1168px 1791px #fff, 1884px 109px #fff, 1465px 451px #fff, 450px 370px #fff, 1560px 703px #fff, 1788px 1997px #fff, 1047px 963px #fff, 1281px 119px #fff, 439px 96px #fff, 164px 1956px #fff, 1360px 930px #fff, 1387px 347px #fff, 1073px 1970px #fff, 1296px 284px #fff, 25px 1602px #fff, 455px 944px #fff, 1177px 738px #fff, 633px 1142px #fff, 1730px 1079px #fff, 1283px 1606px #fff, 674px 1186px #fff, 513px 166px #fff, 1077px 636px #fff, 1811px 580px #fff, 971px 1789px #fff, 694px 1756px #fff, 703px 1138px #fff, 1290px 942px #fff, 351px 1509px #fff, 1904px 790px #fff, 68px 819px #fff, 1097px 362px #fff, 1035px 331px #fff, 180px 940px #fff, 1776px 1229px #fff, 1487px 781px #fff, 1131px 1765px #fff, 1684px 536px #fff, 939px 367px #fff, 1102px 1481px #fff, 741px 887px #fff, 167px 1132px #fff, 1756px 529px #fff, 608px 758px #fff, 541px 1025px #fff, 1976px 505px #fff, 1349px 1257px #fff, 815px 1388px #fff, 505px 1351px #fff, 33px 1945px #fff, 861px 1695px #fff, 678px 1360px #fff, 1615px 727px #fff, 1138px 726px #fff, 30px 293px #fff, 1624px 1044px #fff, 683px 1242px #fff, 1781px 1758px #fff, 906px 1328px #fff, 1066px 1764px #fff, 1568px 664px #fff, 1027px 1876px #fff, 775px 1099px #fff, 1605px 208px #fff, 730px 837px #fff, 1475px 1482px #fff, 871px 1759px #fff, 1240px 15px #fff, 1987px 705px #fff, 302px 1049px #fff, 475px 1015px #fff, 1843px 1296px #fff, 493px 631px #fff, 1613px 164px #fff, 1863px 156px #fff, 1479px 423px #fff, 202px 1499px #fff, 886px 969px #fff, 904px 930px #fff, 1853px 535px #fff, 726px 914px #fff, 435px 1205px #fff, 1732px 1824px #fff, 1212px 667px #fff, 499px 31px #fff, 552px 594px #fff, 1715px 1814px #fff, 775px 908px #fff, 1949px 921px #fff, 1267px 718px #fff, 1830px 1960px #fff, 338px 1325px #fff, 466px 1120px #fff, 140px 1675px #fff, 1919px 664px #fff, 1136px 771px #fff, 1888px 1302px #fff;
}

这样黑夜模式算是真正完成了

Tag标签外挂使用方法

Tag标签外挂使用方法

{%r%}
紅色
{%endr%}
{%g%}
綠色
{%endg%}
{%y%}
黃色
{%endy%}

屏蔽网页源码(单纯的屏蔽鼠标右键和键盘事件)

在 themes/matery/layout/layout.ejs 添加如下代码

<script type="text/javascript">
        window.onload = function(){
            //屏蔽键盘事件
            document.onkeydown = function (){
                var e = window.event || arguments[0];
                //F12
                if(e.keyCode == 123){
                    return false;
                //Ctrl+Shift+I
                }else if((e.ctrlKey) && (e.shiftKey) && (e.keyCode == 73)){
                    return false;
                //Shift+F10
                }else if((e.shiftKey) && (e.keyCode == 121)){
                    return false;
                //Ctrl+U
                }else if((e.ctrlKey) && (e.keyCode == 85)){
                    return false;
                }
            };
            //屏蔽鼠标右键
            document.oncontextmenu = function (){
                return false;
            }
        }
</script>

添加天气小插件

首先去中国天气官网:,配置自己的插件,选择自定义插件—>自定义样式——>生成代码,然后会生成一段代码,复制粘贴到 themes/matery/layout/layout.ejs 即可。

新增个人相册

这个功能,已经由博主上传到官方develop分支了

看下面配置使用方法就好,代码不用修改直接使用!

新建相册目录

执行下面的命令:

hexo new page galleries

然后到站点根目录的 source 目录下找名称为 galleries 的目录,打开目录下的 **index.md ** 文档,在原有基础上添加一下配置:

type: "galleries"
layout: "galleries"

紧接着,在主题配置文件的 menu 属性添加关于相册的菜单

相册:
  url: /galleries 
  icon: fas fa-image

如果需要添加到二级菜单,添加格式为:

- name: 相册
  url: /galleries 
  icon: fas fa-image

添加 ejs 文件和 css 文件

首先新建 gallery.css,填写的代码内容如下:

.gallery-wrapper{
  padding-top: 30px;
}
.gallery-wrapper .gallery-box{
  padding: 5px !important;
}

.gallery-wrapper .gallery-item {
  display: block;
  overflow: hidden;
  background-color: #fff;
  padding: 5px;
  padding-bottom: 0;
  position: relative;
  -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22);
  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22);
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22);
}

.gallery-cover-box{
  width: 100%;
  padding-top: 60%;
  text-align: center;
  overflow: hidden;
  position: relative;
  background: center center no-repeat;
  -webkit-background-size: cover;
  background-size: cover;
}

.gallery-cover-box .gallery-cover-img {
  display: inline-block;
  width: 100%;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%,-50%);
}
.gallery-item .gallery-name{
  font-size: 14px;
  line-height: 24px;
  text-align: center;
  color: #666;
  margin: 0;
}

.waterfall {
  column-count: 3;
  column-gap: 1em;
}
.photo-wrapper{
  padding-top: 20px;
}
.photo-item {
  display: block;
  padding: 10px;
  padding-bottom: 0;
  margin-bottom: 14px;
  font-size: 0;
  -moz-page-break-inside: avoid;
  -webkit-column-break-inside: avoid;
  break-inside: avoid;
  background: white;
  -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22);
  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22);
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.22);
}
.photo-item img {
  width: 100%;
}
.photo-item .photo-name{
  font-size: 14px;
  line-height: 30px;
  text-align: center;
  margin-top: 10px;
  margin-bottom: 10px;
  border-top: 1px solid #dddddd;
}

/*适配移动端布局*/
@media only screen and (max-width: 601px) {
  .waterfall {
    column-count: 2;
    column-gap: 1em;
  }
}

然后保存,将此文件放在主题目录下,路径为 matery/source/css

紧接着,新建 galleries.ejs 文件,添加以下代码:

<link rel="stylesheet" href="/css/gallery.css">

<%- partial('_partial/bg-cover') %>

<main class="content">
    <div class="container">
        <% if (site.data && site.data.galleries) { %>
        <% var galleries = site.data.galleries; %>
        <div class="gallery-wrapper row">
            <% for (var i = 0, len = galleries.length; i < len; i++) { %>
            <% var gallery = galleries[i]; %>
            <div class="col s6 m4 l4 xl3 gallery-box">
                <a href="./<%- gallery.name %>" class="gallery-item" data-aos="zoom-in-up">
                     <div class="gallery-cover-box" style="background-image: url(<%- theme.jsDelivr.url %><%- gallery.cover%>);">
                    </div>
                    <p class="gallery-name">
                        <%- gallery.name %>
                    </p>
                </a>
            </div>
            <% } %>
        </div>
        <% } %>
    </div>
</main>

将此文件放在 matery/layout 目录下,同时再此目录下接着新建 gallery.ejs 文件,添加以下代码:

<link rel="stylesheet" href="/css/gallery.css">
<link type="text/css" href="/libs/fancybox/jquery.fancybox.css" rel="stylesheet">
<link type="text/css" href="/libs/justifiedGallery/justifiedGallery.min.css" rel="stylesheet">

<%- partial('_partial/post-cover') %>
<%
let galleries = [];
if (site.data && site.data.galleries) {
    galleries = site.data.galleries;
}
var pageTitle = page.title;
function getCurrentGallery(galleries, pageTitle) {
    for (let i = 0; i < galleries.length; i++) {
        if (galleries[i]['name'] == pageTitle) {
            return galleries[i];
        }
    }
}
var currentGallery = getCurrentGallery(galleries, pageTitle)

var photos = currentGallery.photos;
var galleryImageStr = theme.jsDelivr.url ? theme.jsDelivr.url : '';

let imageStr = ''

for (var i = 0, len = photos.length; i < len; i++) {
    var photo = photos[i];

    imageStr += "<a href=\"" + galleryImageStr + photo + "\"" +
            "     class=\"photo-item\" rel=\"example_group\"" +
            "     data-fancybox=\"images\">" +
            "      <img src=\"" + galleryImageStr + photo + "\"" +
            "       alt=" + photo + ">\n" +
            "    </a>"

}
%>  

<div class="container">
    <div class="photo-wrapper">
        <% if (page.password ) { %>

            <script src="/js/crypto-js.js"></script>
            <script src="/js/gallery-encrypt.js"></script>
            <div id="hbe-security">
                <div class="hbe-input-container">
                    <input type="password" class="hbe-form-control" id="pass"  placeholder="请输入密码查看内容"/>
                    <a href="javascript:;" class="btn-decrypt" id="btn_decrypt">解密</a>
                </div>
            </div>
            <div  id="mygallery">
                <div class="waterfall" id="encrypt-blog" style="display:none">
                    <%- aes(imageStr, page.password) %>
                </div>
            </div>
        <% } else { %>
            <div class="waterfall" id="encrypt-blog">
                <%- imageStr %>
            </div>
        <% } %>
    </div>
</div>

<script src="/libs/fancybox/fancybox.js"></script>
<script src="/libs/justifiedGallery/justifiedGallery.min.js"></script>
<script>

  $("a[rel=example_group]").fancybox();
  $("#encrypt-blog").justifiedGallery({margins: 5, rowHeight: 150});

</script>

注意:

  1. 需要几个文件,我把文件地址放在下面,用浏览器打开链接,就会显示出代码,然后复制粘贴到文加中去就行。开头的是文件路径,如果没有的话,就新建一个就 OK 了。
  • libs/fancybox/jquery.fancybox.css

    </libs/fancybox/jquery.fancybox.css>

  • libs/justifiedGallery/justifiedGallery.min.css:

    </libs/justifiedGallery/justifiedGallery.min.css>

  • matery/source/js/crypto-js.js:

    </js/crypto-js.js>

  • matery/source/js/gallery-encrypt.js:

    </js/gallery-encrypt.js>

  • libs/fancybox/fancybox.js:

    </libs/fancybox/fancybox.js>

  • libs/justifiedGallery/justifiedGallery.min.js:

    </libs/justifiedGallery/justifiedGallery.min.js>

添加相册 json 配置文件

站点目录 source/_data/ 下新建一个 galleries.json 的文件,json 代码如下:

[
    {
      "name": "2020",
      "cover": "/medias_webp/images/01.webp",
      "description": "我的图床",
      "photos": [
        "/medias_webp/images/01.webp",
        "/medias_webp/images/02.webp",
        "/medias_webp/images/03.webp"
      ]
    },
    {
      "name": "2021",
      "cover": "/medias_webp/featureimages/1.webp",
      "description": "featureimages 图片展示",
      "photos": [
        "/medias_webp/featureimages/1.webp",
        "/medias_webp/featureimages/2.webp",
        "/medias_webp/featureimages/3.webp",
        "/medias_webp/featureimages/4.webp",
      ]
    },
    {
      "name": "2022",
      "cover": "/medias_webp/banner/0.webp",
      "description": "banner 图片展示",
      "photos": [
        "/medias_webp/banner/0.webp",
        "/medias_webp/banner/1.webp",
        "/medias_webp/banner/2.webp",
      ]
    }
]

字段含义:

  • name 是相册标题
  • cover 是封面图片
  • description 是相册介绍
  • photos 是图片列表

配置文件建好了之后还没完,只剩最后一个步骤了,在 galleries 目录下建立对应的相册名称目录和文件,比如我这个相册需要新建名称为 2020 目录,然后下面再分别新建 index.md 文件,2020/index.md文件内容为:

---
title: 2020
date: 2021-10-13 10:51:50
type: "gallery"
layout: "gallery"
---

2021/index.md2022/index.md文件内容和上面一样,只是title修改不同而已

galleries 目录结构

galleries
├── 2020
│   └── index.md
├── 2021
│   └── index.md
├── 2022
│   └── index.md
├── index.md

查看效果

完成以上步骤,执行命令,在本地查看效果:

hexo clean && hexo g && hexo s

我的效果

支持RSS分类订阅

这个功能个人使用很久了,但是原作者插件不支持hexo6, Hexo 6 强制使用的时候,会影响很多基础功能。

这次测试Npm包发布,就拿这个插件练手了!

RSS订阅与文章分类订阅

或者直接访问我的博客查看效果!

重要注意.需要安装 hexo-generator-taghexo-generator-category 插件用来生成 tag/category feeds.

安装

npm install hexo-feed-new --save-dev

配置

feed:
    limit: 20
    order_by: "-date"
    tag_dir: "tag"
    category_dir: "category"
    rss:
        enable: true
        template: "themes/theme/layout/_alternate/rss.ejs"
        output: "rss.xml"
    atom:
        enable: true
        template: "themes/theme/layout/_alternate/atom.ejs"
        output: "atom.xml"
    jsonFeed:
        enable: true
        template: "themes/theme/layout/_alternate/json.ejs"
        output: "feed.json"
KeyRequiredDefault valueDescription
limitfalse0Post count that will be presented in the feed. Use 0 to publish all posts to the feed.
order_byfalse-dateSorting order for the posts.
tag_dirfalsetagDirectory name to publish all tag-related feeds. Set false to avoid generating feeds by tag. For more information see below.
category_dirfalsecategoryDirectory name to publish all category-related feeds. Set false to avoid generating feeds by category. For more information see below.
rss.enablefalsetrueEnable/disable RSS feed generating.
rss.templatefalsePath to custom template for the RSS feed.
rss.outputfalserss.xmlOutput filename for RSS feed.
atom.enablefalsetrueEnable/disable ATOM feed generating.
atom.templatefalsePath to custom template for the ATOM feed.
atom.outputfalseatom.xmlOutput filename for ATOM feed.
jsonFeed.enablefalsetrueEnable/disable JSON feed generating.
jsonFeed.templatefalsePath to custom template for the JSON feed.
jsonFeed.outputfalsefeed.jsonOutput filename for JSON feed.

添加feed

<html>
  <head>

    <!-- ... -->

    <link rel="alternate" type="application/rss+xml" title="<%= config.title %>" href="<%= full_url_for(`/rss.xml}`) %>" />
    <link rel="alternate" type="application/atom+xml" title="<%= config.title %>" href="<%= full_url_for(`/atom.xml`) %>" />
    <link rel="alternate" type="application/json" title="<%= config.title %>" href="<%= full_url_for(`/feed.json`) %>" />
  </head>
  <body>

    <!-- ... -->

  </body>
</html>

豆瓣书单电影页面

1.首先在博客站点目录执行下面的命令安装豆瓣插件:

npm install hexo-douban --save

2.紧接着在博客站点目录的配置文件_config.yml下,添加如下配置:

douban:
  user: 123456789  #这个需要修改为你个人的id
  builtin: true
  book:
      title: '我的书单'
      quote: '你必须要看的书籍'
  movie:
      title: '我的影单'
      quote: '那些年我们一起看过的电影'
timeout: 10000
  • user::你的豆瓣ID。打开豆瓣,登入账户,然后在右上角点击 ”个人主页“,这时候地址栏的URL大概是这样:https://www.douban.com/people/xxxxxx/ ,其中的”xxxxxx”就是你的个人ID了。
  • builtin:是否将生成页面的功能嵌入 hexo shexo g 中,默认是 false ,另一可选项为 true
  • title: 该页面的标题。
  • quote: 写在页面开头的一段话,支持html语法。
  • timeout: 爬取数据的超时时间,默认是 10000ms,如果在使用时发现报了超时的错(ETIMEOUT)可以把这个数据设置的大一点。 如果只想显示某一个页面(比如movie),那就把其他的配置项注释掉即可。

3.然后再主题配置文件_config.yml中添加关于此页面的菜单:(下面是我的配置)

媒体:
    icon: fas fa-list
    children:
      - name: 电影
        url: /movies
        icon: fas fa-film
      - name: 书单
        url: /books
        icon: fas fa-book

4.适配Matery主题:在 /themes/hexo-theme-matery/layout 文件夹下面创建一个名为 douban.ejs 的文件,并将下面的内容复制进去:

<%- partial('_partial/post-cover') %>
<style>
    .hexo-douban-picture img {
        width: 100%;
    }
</style>
<main class="content">
    <div id="contact" class="container chip-container">
        <div class="card">
            <div class="card-content" style="padding: 30px">
                <h1 style="margin: 10px 0 10px 0px;"><%= page.title %></h1>
                <%- page.content %>
            </div>
        </div>
        <div class="card">
            <div class="card-content" style="text-align: center">
              <h3 style="margin: 5px 0 5px 5px;">如果你有好的内容推荐,欢迎在下面留言!</h3>
            </div>
         </div>
        <div class="card">
            <% if (theme.gitalk && theme.gitalk.enable) { %>
            <%- partial('_partial/gitalk') %>
            <% } %>

            <% if (theme.gitment.enable) { %>
            <%- partial('_partial/gitment') %>
            <% } %>

            <% if (theme.disqus.enable) { %>
            <%- partial('_partial/disqus') %>
            <% } %>

            <% if (theme.livere && theme.livere.enable) { %>
            <%- partial('_partialvere') %>
            <% } %>

            <% if (theme.valine && theme.valine.enable) { %>
            <%- partial('_partialaline') %>
            <% } %>
        </div>
    </div>
</main>

5.然后在博客站点目录下的node_modules文件夹下找到hexo-douban/lib,文件夹下有三个js文件,分别为:books-generator.js 、games-generator.js 、movies-generator.js,用文本编辑器打开这三个文件,并将其文件内容末尾的代码修改为一下内容:

/* 原文件内容为 layout: [`page`, `post`] ,将其修改为下面的内容*/
layout: [`page`, `douban`]

6.最后就是使用并生成相应的页面,执行命令如下:

hexo douban

需要注意的是,通常大家都喜欢用 hexo d 来作为 hexo deploy 命令的简化,但是当安装了 hexo douban 之后,就不能用 hexo d 了,因为 hexo doubanhexo deploy 的前缀都是 hexo d ,你以后执行的 hexo d 将不再是 Hexo 页面的生成,而是豆瓣页面的生成。

以下是可选的命令参数:

-h, --help # 帮助页面
-b, --books # 只生成书单页面
-g, --games # 只生成游戏页面
-m, --movies # 只生成电影页面

当站点配置文件的builtin的值为true时,生成页面的功能会嵌入到hexo g和hexo s中,在进行部署生成操作,会自动生成相应的页面

新增折叠功能

这里利用hexo-sliding-spoiler插件间接实现折叠功能,在matery主题中零修改源代码实现折叠功能。

另一种修改代码实现折叠效果,参考Hexo next博客添加折叠块功能添加折叠代码块

安装插件

npm install hexo-sliding-spoiler --save

配置插件

根目录配置文件_config.yml中添加

plugin:
- hexo-sliding-spoiler

到这里已经实现折叠功能了。

进一步完善美化

修改node_modules_hexo-sliding-spoiler@1.2.1@hexo-sliding-spoiler\assets\spoiler.css

.spoiler {
    margin: 20px 0;
    padding: 15px;
    border: 1px solid #E5E5E5;
    background: #E5E5E5;
    position: relative;
    clear: both;
    border-radius: 3px;
    transition:all .6s
}

.spoiler .spoiler-title {
    margin: 0 -15px;
    padding: 5px 15px;
    color: #353535;
    font-weight: bold;
    font-size: 18px;
    display: block;
    cursor: pointer;
}

.spoiler.collapsed .spoiler-title:before {
    content: "▶ ";
}

.spoiler.expanded .spoiler-title:before {
    content: "▼ ";
}

使用方法

{% spoiler title %}
content
{% endspoiler %}

实例

{% spoiler 点击显/隐内容 %}

内容测试

{% endspoiler %}

{% spoiler 点击显/隐内容 %}

内容测试

{% endspoiler %}

代码块全屏显示

最新发现引用的博客文章消失了,如实找到原来的git修改记录,提取出代码块全屏显示的方法给大家

原理简单,通过 JS 添加删除属性,使用 CSS 控制显示和动画效果

.code-area.code-block-fullscreen pre {
  overflow: auto;
  max-height: unset;
  overflow: auto;
  width: 100%;
  height: 100%;
  min-width: 100%;
}


/* code-block-fullscreen */
.code-block-fullscreen {
  position:fixed;
  top:-0.4em;
  left:0;
  width:100%;
  height:100%;
  min-width:100%;
  z-index: 999999;
  margin:0;
  animation: elastic 1s;
}
.code-block-fullscreen code {
  --widthA:100%;
  --widthB:calc(var(--widthA) - 30px);
  height:var(--widthB);
  min-height:99%;
  overflow-y:hidden;
  overflow-x:auto;
  height:auto;
}
.code-block-fullscreen-html-scroll {
  overflow: hidden;
}
.code-area.code-block-fullscreen i.code-expand,
.code-area.code-block-fullscreen .scroll-down-bar {
  display: none;
}
.code-show-expand {
  position: absolute;
  top: 4px;
  right: 53px;
  z-index: 1;
  filter: invert(50%);
  cursor: pointer;
  padding: 7px;
}
if (enableShowexpand) {
  var $code_show_expand = $('<i class="fas fa-expand code-show-expand"  title="全屏显示" aria-hidden="true"></i>');
  $pre.before($code_show_expand);
  $('.code-area .code-show-expand').on('click', function (e) {
    if (e.target !== this) return
    if ($(this).parent().hasClass('code-closed')) {
      $(this).siblings('pre').find('code').show();
      $(this).parent().removeClass('code-closed');
    }
    $(this).parent().toggleClass('code-block-fullscreen')
    $('html').toggleClass('code-block-fullscreen-html-scroll')
  });
}

让Hexo博客支持通知功能

更新文章后,自动发消息给订阅用户的浏览器!

国外非常火的低成本客户召回方式,增加用户粘性。

Tips: 如果访问不了订阅服务器,就不可用这个通知功能了!

安装插件

插件的 GitHub 仓库 hexo-web-push-notification

在你的博客站点目录执行下面的命令:

npm i hexo-web-push-notification --save

如果你安装了 cnpm 或者 yarn 等可执行下面的命令,安装依赖包的速度更快:

cnpm i hexo-web-push-notification --save #安装cnpm的执行这个命令
yarn add hexo-web-push-notification #安装yarn的执行这个命令

紧接着再你的博客站点目录下的配置文件,而不是主题配置文件,添加以下配置:

webPushNotification:
  webpushrKey: "your webpushr rest api key"
  webpushrAuthToken: "your webpushr authorize token"
  trackingCode: "AEGlpbdgvBCWXqXI6PtsUzobY7TLV9gwJU8bzMktrwfrSERg_xnLVbjpCw8x2GmFmi1ZcLTz0ni6OnX5MAwoM88"

其中 webpushrKey,webpushrAuthTokentrackingCode 的值在官网注册得到。

官网注册

点击右边的图标即可进入👉 : 传送门

注册完之后,然后会让你重新登录,登录之后,然后填写相关的信息即可。

  1. 填写图中所显示的相关网站信息,填写完之后,点击下一步

Web push notications 仅支持 HTTPS 的网站,不支持 HTTP 的网站

根据网站类型,并根据网站指引进行操作,以 Hexo 为例

info, 其中将第二步中所指的代码复制粘贴到你的 footer.ejs 或者 layout.ejs,对于 hexo 用户,建议将其加入 index.ejs 即可。因为主题的不同,所以代码添加的位置不同,简单的说,就是放在网站的 </body> 标签之前,根据你的主题而言,自己添加。

接着将以下代码插入到网页中就可以了。确保每一个你想要询问用户接受通知的页面都要包含以下代码。

其中,上图步骤二中的代码有 trackingCode 的值,如下图中所标明的一长串字母。

验证安装

安装成功

部署之后可能会遇到无法正常发送通知的情况.

进入目录node_modules/hexo-web-push-notification/index.js文件中第22行'summary': util.stripHTML(newPost.excerpt),这里取值取的是excerpt,改成summary即可。

修改前

var JSONFeed = {
        'title': newPost.title,
        'id': newPost.path,
        'date_published': newPost.date.format('L'),
        'summary': util.stripHTML(newPost.excerpt),
        'url': newPost.permalink,
        'tags': newPost.tags.data.map(function (v) { return v.name }),
        'categories': newPost.categories.data.map(function (v) { return v.name })
    }
var JSONFeed = {
        'title': newPost.title,
        'id': newPost.path,
        'date_published': newPost.date.format('L'),
        'summary': util.stripHTML(newPost.summary),
        'url': newPost.permalink,
        'tags': newPost.tags.data.map(function (v) { return v.name }),
        'categories': newPost.categories.data.map(function (v) { return v.name })
    }

客服聊天窗口

1、在官网注册账号

官网地址:点我去crisp官网注册

2、注册完成后设置

登录刚才注册的账户——设置——网站设置——添加网站。

添加完成之后就多了一行网站信息。点网站整合,就有不同的站的整合方式。

比如:html方式

就是复制JS代码片段到你的到head标签里。

<script type="text/javascript">window.$crisp=[];window.CRISP_WEBSITE_ID="xxxxxxx-097e-402f-bb6b-xxxxxxx";(function(){d=document;s=d.createElement("script");s.src="https://client.crisp.chat/l.js";s.async=1;d.getElementsByTagName("head")[0].appendChild(s);})();</script>

3、其他的设置也
登录刚才注册的账户——设置——网站设置。
网站信息行——设置,自己根据需要设置即可,比如显示位置,颜色,自己的头像等。

整个使用非常简单的。

使用Valine-Admin管理评论和评论提醒

使用

首先其他的不错说了,在阅读本篇文章之前你最好已经整合了Valine留言。

由于我已经整合过了所以前面几个步骤的图片来源自@Valine-Admin

首先登陆账号,找到云引擎在点击设置。

推荐使用这个 HCLonely/Valine-Admin

复制仓库地址:DesertsP/Valine-Admin

img

把git仓库地址房子代码库输入框中。

切换到部署标签页,分支使用 master,点击部署。

img

接下来输入分支为master

img

部署完成之后就是设置环境变量

环境变量

点击设置,找到自定义环境变量点击新增变量

img

  • SITE_NAME : 网站名称。
  • SITE_URL : 网站地址, 最后不要加 /
  • SMTP_USER : SMTP 服务用户名,一般为邮箱地址。
  • SMTP_PASS : SMTP 密码,一般为授权码,而不是邮箱的登陆密码,请自行查询对应邮件服务商的获取方式
  • SMTP_SERVICE : 邮件服务提供商,支持 QQ163126Gmail"Yahoo"...... ,全部支持请参考 : Nodemailer Supported services。 — 如这里没有你使用的邮件提供商,请查看自定义邮件服务器
  • SENDER_NAME : 寄件人名称。
  • TO_EMAIL:这个是填收邮件提醒的邮箱地址,若没有这个字段,则将邮件发到SMTP_USER
  • TEMPLATE_NAME:设置提醒邮件的主题,目前内置了两款主题,分别为 defaultrainbow。默认为 default

设置好以上变量之后 点击实例

img

然后重启项目,注意任何变动都要重启项目

然后看一下效果

img

还不错

自定义后台

首先需要设置管理员信息。访问管理员注册页面https://云引擎域名/sign-up,注册管理员登录信息,如:https://deserts-io.avosapps.us/sign-up

点击设置然后点击Web主机域名找到自己的后台地址

img

然后在Usee表中增加账号, 只需要填写 emailpasswordusername 其中邮箱必须设置为你的上面环境变量的邮箱

设置完之后登录就能在你的后台管理评论

更多设置

邮件通知模板

HCLonely/Valine-Admin 时使用这个

邮件通知演示

评论通知模板

<div
                            style="
                                border-radius: 10px 10px 10px 10px;
                                font-size: 13px;
                                color: #555555;
                                width: 666px;
                                font-family: 'Century Gothic', 'Trebuchet MS', 'Hiragino Sans GB', 微软雅黑, 'Microsoft Yahei', Tahoma, Helvetica,
                                    Arial, 'SimSun', sans-serif;
                                margin: 50px auto;
                                border: 1px solid #eee;
                                max-width: 100%;
                                background: #ffffff repeating-linear-gradient(-45deg, #fff, #fff 1.125rem, transparent 1.125rem, transparent 2.25rem);
                                box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
                            "
                        >
                            <div
                                style="
                                    width: 100%;
                                    background: #49bdad;
                                    color: #ffffff;
                                    border-radius: 10px 10px 0 0;
                                    background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));
                                    background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));
                                    height: 66px;
                                "
                            >
                                <p
                                    style="
                                        font-size: 15px;
                                        word-break: break-all;
                                        padding: 23px 32px;
                                        margin: 0;
                                        background-color: hsla(0, 0%, 100%, 0.4);
                                        border-radius: 10px 10px 0 0;
                                    "
                                >
                                    您在<a style="text-decoration: none; color: #ffffff" href="<%=siteUrl%>"> <%=siteName%> </a>上的留言有新回复啦!
                                </p>
                            </div>
                            <div style="margin: 40px auto; width: 90%">
                                <p><%=pname%> 同学,您曾在文章上发表评论:</p>
                                <div
                                    style="
                                        background: #fafafa
                                            repeating-linear-gradient(-45deg, #fff, #fff 1.125rem, transparent 1.125rem, transparent 2.25rem);
                                        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
                                        margin: 20px 0px;
                                        padding: 15px;
                                        border-radius: 5px;
                                        font-size: 14px;
                                        color: #555555;
                                    "
                                >
                                    <%-ptext%>
                                </div>
                                <p><%=name%> 给您的回复如下:</p>
                                <div
                                    style="
                                        background: #fafafa
                                            repeating-linear-gradient(-45deg, #fff, #fff 1.125rem, transparent 1.125rem, transparent 2.25rem);
                                        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
                                        margin: 20px 0px;
                                        padding: 15px;
                                        border-radius: 5px;
                                        font-size: 14px;
                                        color: #555555;
                                    "
                                >
                                    <%-text%>
                                </div>
                                <p>
                                    您可以点击 <a style="text-decoration: none; color: #12addb" href="<%=url%>">查看回复的完整內容 </a>,欢迎再次光临
                                    <a style="text-decoration: none; color: #12addb" href="<%=siteUrl%>"> <%=siteName%> </a>。
                                </p>
                                <style type="text/css">
                                    a:link {
                                        text-decoration: none;
                                    }
                                    a:visited {
                                        text-decoration: none;
                                    }
                                    a:hover {
                                        text-decoration: none;
                                    }
                                    a:active {
                                        text-decoration: none;
                                    }
                                </style>
                            </div>
                        </div>

博主回复通知模板

<div
                            style="
                                border-radius: 10px 10px 10px 10px;
                                font-size: 13px;
                                color: #555555;
                                width: 666px;
                                font-family: 'Century Gothic', 'Trebuchet MS', 'Hiragino Sans GB', 微软雅黑, 'Microsoft Yahei', Tahoma, Helvetica,
                                    Arial, 'SimSun', sans-serif;
                                margin: 50px auto;
                                border: 1px solid #eee;
                                max-width: 100%;
                                background: #ffffff repeating-linear-gradient(-45deg, #fff, #fff 1.125rem, transparent 1.125rem, transparent 2.25rem);
                                box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
                            "
                        >
                            <div
                                style="
                                    width: 100%;
                                    background: #49bdad;
                                    color: #ffffff;
                                    border-radius: 10px 10px 0 0;
                                    background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));
                                    background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));
                                    height: 66px;
                                "
                            >
                                <p
                                    style="
                                        font-size: 15px;
                                        word-break: break-all;
                                        padding: 23px 32px;
                                        margin: 0;
                                        background-color: hsla(0, 0%, 100%, 0.4);
                                        border-radius: 10px 10px 0 0;
                                    "
                                >
                                    您的<a style="text-decoration: none; color: #ffffff" href="<%=siteUrl%>"> <%=siteName%> </a>上有新的评论啦!
                                </p>
                            </div>
                            <div style="margin: 40px auto; width: 90%">
                                <p><%=name%> 发表评论:</p>
                                <div
                                    style="
                                        background: #fafafa
                                            repeating-linear-gradient(-45deg, #fff, #fff 1.125rem, transparent 1.125rem, transparent 2.25rem);
                                        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
                                        margin: 20px 0px;
                                        padding: 15px;
                                        border-radius: 5px;
                                        font-size: 14px;
                                        color: #555555;
                                    "
                                >
                                    <%-text%>
                                </div>
                                <p><a style="text-decoration: none; color: #12addb" href="<%=url%>" target="_blank">[查看评论]</a></p>
                                <style type="text/css">
                                    a:link {
                                        text-decoration: none;
                                    }
                                    a:visited {
                                        text-decoration: none;
                                    }
                                    a:hover {
                                        text-decoration: none;
                                    }
                                    a:active {
                                        text-decoration: none;
                                    }
                                </style>
                            </div>
                        </div>

使用 DesertsP/Valine-Admin 时使用下面配置

邮件通知模板在云引擎环境变量中设定,可自定义通知邮件标题及内容模板。

环境变量示例说明
MAIL_SUBJECT${PARENT_NICK},您在${SITE_NAME}上的评论收到了回复[可选]@通知邮件主题(标题)模板
MAIL_TEMPLATE见下文[可选]@通知邮件内容模板
MAIL_SUBJECT_ADMIN${SITE_NAME}上有新评论了[可选]博主邮件通知主题模板
MAIL_TEMPLATE_ADMIN见下文[可选]博主邮件通知内容模板

邮件通知包含两种,分别是被@通知和博主通知,这两种模板都可以完全自定义。默认使用经典的蓝色风格模板(样式来源未知)。

默认被@通知邮件内容模板如下:

<div style="border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;"><h2 style="border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;">您在<a style="text-decoration:none;color: #12ADDB;" href="${SITE_URL}" target="_blank">            ${SITE_NAME}</a>上的评论有了新的回复</h2> ${PARENT_NICK} 同学,您曾发表评论:<div style="padding:0 12px 0 12px;margin-top:18px"><div style="background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;">            ${PARENT_COMMENT}</div><p><strong>${NICK}</strong>回复说:</p><div style="background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;"> ${COMMENT}</div><p>您可以点击<a style="text-decoration:none; color:#12addb" href="${POST_URL}" target="_blank">查看回复的完整內容</a>,欢迎再次光临<a style="text-decoration:none; color:#12addb" href="${SITE_URL}" target="_blank">${SITE_NAME}</a>。<br></p></div></div>

效果如下图:

mail-blue-template

mail-blue-template

@通知模板中的可用变量如下(注,这是邮件模板变量,是指嵌入到HTML邮件模板中的变量,请勿与云引擎环境变量混淆):

模板变量说明
SITE_NAME博客名称
SITE_URL博客首页地址
POST_URL文章地址(完整路径)
PARENT_NICK收件人昵称(被@者,父级评论人)
PARENT_COMMENT父级评论内容
NICK新评论者昵称
COMMENT新评论内容

默认博主通知邮件内容模板如下:

<div style="border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;"><h2 style="border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;">您在<a style="text-decoration:none;color: #12ADDB;" href="${SITE_URL}" target="_blank">${SITE_NAME}</a>上的文章有了新的评论</h2><p><strong>${NICK}</strong>回复说:</p><div style="background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;"> ${COMMENT}</div><p>您可以点击<a style="text-decoration:none; color:#12addb" href="${POST_URL}" target="_blank">查看回复的完整內容</a><br></p></div></div>

博主通知邮件模板中的可用变量与@通知中的基本一致,PARENT_NICKPARENT_COMMENT 变量不再可用。

这里还提供一个彩虹风格的@通知邮件模板代码:

<div style="border-radius: 10px 10px 10px 10px;font-size:13px;    color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}"> ${SITE_NAME}</a>上的留言有新回复啦!</p></div><div style="margin:40px auto;width:90%"><p>${PARENT_NICK} 同学,您曾在文章上发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${PARENT_COMMENT}</div><p>${NICK} 给您的回复如下:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p>您可以点击<a style="text-decoration:none; color:#12addb" href="${POST_URL}#comments">查看回复的完整內容</a>,欢迎再次光临<a style="text-decoration:none; color:#12addb"                href="${SITE_URL}"> ${SITE_NAME}</a>。</p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div></div>

效果如图:

彩虹模板

彩虹模板

垃圾评论检测

Akismet (Automattic Kismet)是应用广泛的一个垃圾留言过滤系统,其作者是大名鼎鼎的WordPress 创始人 Matt Mullenweg,Akismet也是WordPress默认安装的插件,其使用非常广泛,设计目标便是帮助博客网站来过滤留言Spam。有了Akismet之后,基本上不用担心垃圾留言的烦恼了。 启用Akismet后,当博客再收到留言会自动将其提交到Akismet并与Akismet上的黑名单进行比对,如果名列该黑名单中,则该条留言会被标记为垃圾评论且不会发布。

如果还没有Akismet Key,你可以去 AKISMET FOR DEVELOPERS 免费申请一个AKISMET_KEY设为MANUAL_REVIEW时,开启人工审核模式; 如果你不需要反垃圾评论,Akismet Key 环境变量可以忽略。

为了实现较为精准的垃圾评论识别,采集的判据除了评论内容、邮件地址和网站地址外,还包括评论者的IP地址、浏览器信息等,但仅在云引擎后台使用这些数据,确保隐私和安全。

如果使用了本站最新的ValineValine Admin,并设置了Akismet Key,可以有效地拦截垃圾评论。被标为垃圾的评论可以在管理页面取消标注。

环境变量示例说明
AKISMET_KEYxxxxxxxxxxxx[可选]Akismet Key 用于垃圾评论检测

手动配置邮件服务器

  • 自定义邮件服务器地址和端口信息,删除SMTP_SERVICE环境变量,新增以下变量:
变量示例说明
SMTP_HOSTsmtp.qq.com[可选]SMTP_SERVICE留空时,自定义SMTP服务器地址
SMTP_PORT465[可选]SMTP_SERVICE留空时,自定义SMTP端口
SMTP_SECUREtrue[可选]使用TLS

Troubleshooting

  • 部署失败,请在评论中附图,或去Github发起Issue

  • 邮件发送失败,确保环境变量都没问题后,重启云引擎

    重启云引擎

    重启云引擎

  • 博主通知模板中不要出现PARENT*相关参数(请勿混用模板)

  • 点击邮件中的链接跳转至相应评论,这一细节实现需要在Web前端添加一点额外的代码:

<script>
    if(window.location.hash){
        var checkExist = setInterval(function() {
           if ($(window.location.hash).length) {
              $('html, body').animate({scrollTop: $(window.location.hash).offset().top-90}, 1000);
              clearInterval(checkExist);
           }
        }, 100);
    }
</script>

@邮件通知效果:

您在[ ${SITE_NAME}](/posts/40300608/${SITE_URL})上的留言有新回复啦!

${PARENT_NICK} 同学,您曾在文章上发表评论:

${PARENT_COMMENT}

${NICK} 给您的回复如下:

${COMMENT}

您可以点击查看回复的完整內容${POST_URL}#comments,欢迎再次光临 ${SITE_NAME}${SITE_URL}。

@邮件通知模板代码:

<div style="border-radius: 10px 10px 10px 10px;font-size:13px; color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}"> ${SITE_NAME}</a>上的留言有新回复啦!</p></div><div style="margin:40px auto;width:90%"><p>${PARENT_NICK} 同学,您曾在文章上发表评论:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${PARENT_COMMENT}</div><p>${NICK} 给您的回复如下:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p>您可以点击<a style="text-decoration:none; color:#12addb" href="${POST_URL}#comments">查看回复的完整內容</a>,欢迎再次光临<a style="text-decoration:none; color:#12addb" href="${SITE_URL}"> ${SITE_NAME}</a>。</p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 0 0 10px 10px;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg,rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"></div></div>

博主通知效果:

您在[${SITE_NAME}${SITE_URL}上的文章有了新的评论!
**${NICK}** 同学,发表评论说:
${COMMENT}
您可以点击查看回复的完整內容${POST_URL}#comments)。
<div style="border-radius: 10px 10px 10px 10px;font-size:13px; color: #555555;width: 666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background: #ffffff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);"><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 10px 10px 0 0;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"><p style="font-size:15px;word-break:break-all;padding: 23px 32px;margin:0;background-color: hsla(0,0%,100%,.4);border-radius: 10px 10px 0 0;">您在<a style="text-decoration:none;color: #ffffff;" href="${SITE_URL}"> ${SITE_NAME}</a>上的文章有了新的评论!</p></div><div style="margin:40px auto;width:90%"><p><strong>${NICK}</strong> 同学,发表评论说:</p><div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:14px;color:#555555;">${COMMENT}</div><p>您可以点击<a style="text-decoration:none; color:#12addb" href="${POST_URL}#comments">查看回复的完整內容</a>。</p><style type="text/css">a:link{text-decoration:none}a:visited{text-decoration:none}a:hover{text-decoration:none}a:active{text-decoration:none}</style></div><div style="width:100%;background:#49BDAD;color:#ffffff;border-radius: 0 0 10px 10px ;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));background-image: -webkit-linear-gradient(0deg,rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;"></div></div>

解决休眠

免费版的 LeanCloud 容器,是有强制性休眠策略的,不能 24 小时运行:

  • 每天必须休眠 6 个小时
  • 30 分钟内没有外部请求,则休眠。
  • 休眠后如果有新的外部请求实例则马上启动(但激活时此次发送邮件会失败)。

也就是如果服务器休眠了的话用户第一次评论是提醒不了的。

参考了Valine-Admin官网找到了解决办法。

首先在环境变量增加服务器地址,就是你的后台服务器地址

img

下面是你的服务器地址,可以自定义

同样登录后台

找到定时任务

img

然后点击创建任务,上面是我创建好的

img

选择self_wake函数,然后运行时间使用cron表达式

0 0/30 7-23 ? 表示每天6点到11点 每30分钟叫醒服务器一次

这样就完美的解决了服务器休眠的问题

那如果用户不在时间范围内发留言了怎么办?我们也可以创建一个捡漏的定时任务

img

创建捡漏定时任务

然后运行函数选择resend_mails,同样使用cron表达式

0 0 8 ?

表示每八个小时进行捡漏一次,这样如果有留言遗漏的话就能即使的提醒。

WakeLeanCloud

这个项目主要是用来解决LeanCloud通过定时任务唤醒机器时被流控的问题。

如何使用

  1. Fork此项目
  2. 添加一个名为GITHUB_TOKEN的Token,并为赋予repoadmin:repo_hookworkflow的权限
  3. 添加名为SITE的Secrets,内容为自己管理后台地址。多个请用英文逗号分隔

详细教程请参考优雅解决LeanCloud流控问题

让hexo支持pwa

pwa中文叫渐进式网页应用,pwa网站可以直接添加网址站到桌面,就相当于在系统中直接安装了一个app,打开的效果也和app差不多,加载速度也很快,部分功能可以直接离线使用。Google的Workbox标准,目前来看需要Chrome支持

  • hexo-pwa 很久没更新,看到资料都是支持4.x版本hexo。
  • hexo-offline 亲自验证,支持最新5.x的hexo。

安装hexo-offline

npm install hexo-offline --save

关于这个插件的详细使用方法可以看下面这里

https://github.com/JLHwung/hexo-offline

配置hexo-offline

之后我们在站点根目录_config.yml如下配置

# offline config passed to sw-precache.
service_worker:
  maximumFileSizeToCacheInBytes: 5242880
  staticFileGlobs:
  - /**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff,woff2}
  - /lib/**/*.js
  - /lib/**/*.css
  - /images/*
  - /js/src/**/*.js
  stripPrefix: public
  verbose: true
  runtimeCaching:
    - urlPattern: /*
      handler: cacheFirst
      options:
        origin: cdn.bootcss.com

注意哦不是主题的_config.yml文件

之后生成manifest.json文件,可以在这个网站在线生成。

填入相关的参数,如下

Tips: 一定需要一个512x512的icon!

之后点击generate.zip 把配置都下载过来

把manifest.json和images文件夹直接复制到hexo下source文件夹中,最后我们编辑主题,在head里添加

<link rel="manifest" href="/manifest.json">

如果使用的是hexo next主题,在

themes/next/layout/_partials/head/head.swig

如果使用的是hexo matery主题,在

themes/matery/layout/_partial/head.ejs

这个文件中添加上面这句话即可,最后直接重新生成站点,部署即可

验证和使用

需要https访问,看到这个齿轮

F12 sources

然后在浏览器地址栏可以看到应用标志

Tips: offline 需要https才能正常使用

地址栏

点击打开,会看到如下结果,试一下?

离线博客

valine 的使用与升级到1.4

一、valine启用

1、主要流程

valine和miniValine使用基本类似。

(1)去 Leancloud注册。

注意事项:

节点选择:华东节点、华北节点、国际版。

如果你的域名没有备案,建议选择国际版。 因为华东或华北节点在安装评论系统之后访问要求域名备案。

(2)在“设置“,”应用 Keys”,找到你的appidappkey,配置到主题中valine配置的地方,启用valine

(3)在“设置“,”安全中心”,”Web 安全域名”,添加自己的域名。

(4)在“设置“,”安全中心”,”服务开关”,数据存储要打开。

(5)在“存储“,”用量统计”,”HTTP状态码”,启用,方便后续报错查错误码。

(6)重新编译部署hexo clean & hexo g & hexo d

2、遇到问题

搞这个东西采坑不少,有些坑都是自己不小心造成的。我在网上查了,交流群里也咨询请教了,没有人能解决这个问题,毕竟这个坑是自己造成的。

常见Code 403问题:

Code 403: 访问被api域名白名单拒绝,请检查你的安全域名设置.

网上多数的说法是在web安全域名中添加自己的域名。可是如果添加之后还是这个问题呢?

其实一般不会有这个问题,我有这个问题是我改了权限造成了。

官方给的解释:

应用在控制台中的相关服务选项未打开,如 Class 关闭了权限,或是 User 缺失了 session 信息等情况下,云端会统一地返回 403 错误码及不同的错误信息,代表当前请求因权限不够而被拒。例如:

信息 - Forbidden to read/write by class permissions
含义 - 操作被禁止,因为 Class 表没有打开「读」或者「写」的权限。进入 控制台 > 存储,点击相应的 Class,从右侧选择 其他 下拉菜单,进入 权限管理 来调整。

信息 - The user cannot be altered by a client without the session.
含义 - 用户没有登录,无法修改用户信息。

解决:

(1)首次使用,添加一条评论,一般添加之后就会好了。

(2)后续使用,403,请检查comment表的add_fields/create/find权限开放。

(3)如果还是不行将_use表的add_fields/create/find权限开放。

(4)如果还是不行,到“存储“,”用量统计”,”HTTP状态码”处,检查你的错误码,然后去LeanCloud的错误找应用的错误码,排查原因吧。

二、valine升级

1、引入1.4版的js文件

(1)修改主题配置文件

js:
  valine: https://unpkg.com/valine/dist/Valine.min.js #/libs/valine/Valine.min.js 

(2)将文件放你自己的仓库

下载我的 Valine.min.js 文件,直接替换你主题目录 /source/libs/valine/ 下的 Valine.min.js 文件。

注意,如果你担心替换有问题,可以先备份一下你自己的 Valine.min.js 文件。

2、增加valine的配置:

1.4的版本有些属性调整了,主题下的_config.ymlvaline属性如下:

valine:
  enable: true
  appId: iTxfqh5e9IaRfiiVOTbIWoKa-XXXXXX
  appKey: C5s5xGFErD1EtXXXXXXXX
  verify: true  # 是否启用防垃圾验证
  notify: true  # 是否开启邮件提醒(https://valine.js.org/notify.html)
  visitor: true
  avatar: monsterid  # 头像样式(https://valine.js.org/avatar.html) 
  pageSize: 10
  placeholder: 'ヾノ≧∀≦)o来啊,快活啊!' # Comment Box placeholder
  background: /medias/comment_bg.png #背景图
  count: true
  enableQQ: 970175021
  recordIP: true
  requiredFields: 
    - nick
    - mail
  guest_info: 
    - nick
    - mail
    - link
  master: 
    - 123abc508165c8eba9a77f872xxxx046  # md5加密后的博主邮箱
  metaPlaceholder:  # 输入框的背景文字
    nick: 昵称/QQ号(必填)
    mail: 邮箱(必填)
    link: 网址(https://)
  lang: zh-CN
  tagMeta: # The String Array of Words to show Flag.[Just Only xCss Style mode]
    - 博主
    - 小伙伴
    - 访客
  friends: # The MD5 String Array of friends Email to show friends Flag.[Just Only xCss Style mode]
    - c08508165c8eba9a77f8c2853xxxx09e
    - 901345d4c91ddfd8db0f175bbcfff0c8
    - 1512958e18378c98b498d5effe3e76ff

复制代码注意缩进对齐,不对齐可能会报错,请自行检查对齐。

3、修改valine.ejs

Matery 主题使用的ejs模板预编译,如果你使用了pug或者swig等其他的模板语言,请修改成对应语言语法即可。

原始的valine.ejs

new Valine({
        el: '#vcomments',
        appId: '<%- theme.valine.appId %>',
        appKey: '<%- theme.valine.appKey %>',
        notify: '<%- theme.valine.notify %>' === 'true',
        verify: '<%- theme.valine.verify %>' === 'true',
        visitor: '<%- theme.valine.visitor %>' === 'true',
        avatar: '<%- theme.valine.avatar %>',
        pageSize: '<%- theme.valine.pageSize %>',
        lang: '<% if (config.language == "zh-CN") {  %>zh-cn<% } else { %>en<% } %>',
        placeholder: '<%= theme.valine.placeholder %>'
    });

升级后的valine.ejs

let metaPlaceholder = <%-  JSON.stringify(theme.valine.metaPlaceholder) %> ;
//这里要换行
new Valine({
        el: '#vcomments',
        appId: '<%- theme.valine.appId %>',
        appKey: '<%- theme.valine.appKey %>',
        notify: '<%- theme.valine.notify %>' === 'true',
        verify: '<%- theme.valine.verify %>' === 'true',
        visitor: '<%- theme.valine.visitor %>' === 'true',
        avatar: '<%- theme.valine.avatar %>',
        pageSize: '<%- theme.valine.pageSize %>',
        lang: '<%- theme.valine.lang %>',
        placeholder: '<%= theme.valine.placeholder %>',
        meta: <%- '["' + theme.valine.guest_info.join('", "') + '"]' %>,
        recordIP: '<%- theme.valine.recordIP %>' === 'true',
        enableQQ: '<%- theme.valine.avatar %>',
        requiredFields: <%- '["' + theme.valine.master.join('", "') + '"]' %>,
        master: <%- '["' + theme.valine.master.join('", "') + '"]' %>,
        friends: <%- '["' + theme.valine.friends.join('", "') + '"]' %>,
        tagMeta: <%- '["' + theme.valine.tagMeta.join('", "') + '"]' %>,
        metaPlaceholder: metaPlaceholder,

    });

如果需要验证昵称和邮箱可以加上以下代码:

document.body.addEventListener('click', function(e) {
    if (e.target.classList.contains('vsubmit')) {
        const email = document.querySelector('input[type=email]');
        const nick = document.querySelector('input[name=nick]');
        const reg = /^[A-Za-z0-9_-\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
        if (!email.value || !nick.value || !reg.test(email.value)) {
            const str = `<div class="valert txt-center"><div class="vtext">请填写正确的昵称和邮箱!</div></div>`;
            const vmark = document.querySelector('.vmark');
            vmark.innerHTML = str;
            vmark.style.display = 'block';

            e.stopPropagation();

            setTimeout(function() {
                vmark.style.display = 'none';
                vmark.innerHTML = '';
            }, 2500);
        }
    }
    }, true);

说明:代码非原创,JS正则验证本身也不难。

好了可以部署之后自己测试一下。

顺便说一下,填写昵称邮箱和网址的地方如果折行了就按我的样式改一下就好:

valine.ejs 是上面对着改一下就好了:

.v[data-class="v"] .vwrap .vheader .vinput {
  width: 32%;
  border-bottom: 1px dashed #dedede;
}

新建文章自动打开本地Markdown编辑器

写新文章时,需要控制台执行hexo new “文章名字”生成一篇新文章,但需要手动打开,挺麻烦,我们可以设置在生成之后自动打开

在站点根目录下新建scripts目录,然后在新建auto_open.js,在文件填入一下内容

var spawn = require('child_process').exec;

// Hexo 2.x 用户复制这段
//hexo.on('new', function(path){
  //spawn('start  "markdown编辑器绝对路径.exe" ' + path);
//});

// Hexo 3 用户复制这段
hexo.on('new', function(data){
  spawn('start  "D:\Program Files\Typora\Typora.exe" ' + data.path);
});

其中”D:\Program Files\Typora\Typora.exe”是我本地编辑器的路径,只需要改为你本地编辑器的路径即可,然后在执行hexo cl && hexo g -d,部署到GitHub即可,以后在新建文章就会自动打开编辑器.

新建文章自动打开本地Vim编辑器

Linux , MacOS 等类UNIX系统用户,vim $hexo/scripts/openNewFile.js

var spawn = require('child_process').spawn;
// Hexo 3
hexo.on('new', function(data){
spawn('vim', [data.path], { stdio: 'inherit'  });
});

使用 VS Code 的任务(Tasks)便捷操作 Hexo

本文章要实现目标是通过配置任务,可以使用 Ctrl+Shift+B(“运行生成任务”的快捷键)自动完成 Hexo 的清理、生成、开启本地预览,并且可以使用 VS Code 的“终端”菜单下的“运行命令”完成上述的单个命令。

配置 Tasks

工作区的特定任务是从 Workspace.vscode 文件夹中的 tasks.json 文件配置。

新建 tasks.json

在 Hexo 工作区的 .vscode 文件夹下新建 tasks.json 文件。

配置单个 Hexo 命令

hexo generate 命令为例,在 tasks.json 粘贴下面的代码。


{
  "version": "2.0.0",
  "tasks": [
    {
      // 任务类型。
      "type": "shell",
      // 任务的用户界面中使用的标签;相当于变量名。
      "label": "local generate",
      // 实际执行的命令。
      "command": "hexo generate",
      // 定义如何在用户界面中处理任务输出,自行定义。
      "presentation": {
        // 命令面板。dedicated -> 如果任务已在命令面板中则重用此面板,否则新建面板。
        "panel": "dedicated",
        // 任务执行前是否清理命令面板。
        "clear": true
      },
      // 问题匹配器,为空则不匹配任何问题。
      "problemMatcher": []
    }
  ]
}

代码中的参数根据注释和名称自行理解,想要查看更多的参数信息或关于 Tasks 的信息可以访问官方文档

备注:上述任务中的 presentationproblemMatcher 是非必要的,但是实际使用时可以减少 VS Code 可能出现的询问次数。

配置多个 Hexo 命令

我们还需要按照上述增加其他命令,添加后的代码如下:


{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "生成",
      "command": "hexo generate",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    // ----------
    // 新增代码
    {
      "type": "shell",
      "label": "清理",
      "command": "hexo clean",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "预览",
      "command": "hexo server",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    }
    // ----------
  ]
}

备注tasks 内的任务书写无顺序之分。

配置多个命令的顺序执行

代码如下:


{
  "version": "2.0.0",

  "tasks": [
    // ----------
    // 新增代码。
    {
      "label": "清理、生成并预览",
      // 执行顺序。sequence -> 顺序依次执行。
      "dependsOrder": "sequence",
      // 执行本任务前要执行的任务。在此处依次写入其他任务的标签(label)。
      "dependsOn": ["清理", "生成", "预览"],
      "problemMatcher": [],
      // 组。
      "group": {
        // 任务类型。
        "kind": "build",
        // 是否为默认任务。
        "isDefault": true
      }
    },
    // ----------
    {
      "type": "shell",
      "label": "清理",
      "command": "hexo clean",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "生成",
      "command": "hexo generate",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "预览",
      "command": "hexo server",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    }
  ]
}

其中本例内 group 的设置是为了将任务 local clear & server 设置为 VS Code “运行生成任务…”功能的默认任务,这样我们才能通过快捷键 Ctrl+Shift+B 执行此任务。

备注:新增的这个任务是一个自身不执行任何命令的任务。

执行 Tasks

完成上面的设置后,我们在编辑了 Hexo 的文章或其他内容后使用 Ctrl+Shift+B 快捷键就可以自动完成 Hexo 的清理、生成、开启本地预览。

如果想要执行上面配置的 3 个任务中的某一个,可以点击菜单栏“终端”下的“运行任务”来执行其中的任务。

运行任务

如果最近任务里没有自己定义的任务,可以点击最下方的“显示所有任务…”来查看所有定义的任务。

疑问与解答

  1. 为什么要创建 4 个任务,而不是将最后任务的依赖设为前两个,这样就只会有 3 个任务(比如如下代码),这难道不是更简洁吗?

    
    {
      "version": "2.0.0",
      "tasks": [
        {
          "type": "shell",
          "label": "清理",
          "command": "hexo clean",
          "presentation": {
            "panel": "dedicated",
            "clear": true
          },
          "problemMatcher": []
        },
        {
          "type": "shell",
          "label": "生成",
          "command": "hexo generate",
          "presentation": {
            "panel": "dedicated",
            "clear": true
          },
          "problemMatcher": []
        },
    
        // 最后一个任务执行前先执行其他两个
        {
          "type": "shell",
          "label": "预览",
          "command": "hexo server",
          "presentation": {
            "panel": "dedicated",
            "clear": true
          },
          "problemMatcher": [],
          "dependsOrder": "sequence",
          "dependsOn": ["清理", "生成"],
          "group": {
            "kind": "build",
            "isDefault": true
          }
        }
      ]
    }

    解答:这样设置会导致无法使用单一的命令 hexo server,因为调用 local server 这个任务总会调用其他两个。当然如果你不需要有单独执行命令 hexo server 的任务,那你这样写也可以。

  2. 只能通过 shell 类型的任务来完成本次的目标吗?
    :当然不是,你也可以使用 npm 等类型的任务来完成目标。

附录

你也可以参考上面的任务,自己添加 Hexo 的任务,比如一键部署等。

使用案例

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "清理、生成并预览",
      "dependsOrder": "sequence",
      "dependsOn": ["清理", "生成", "预览"],
      "problemMatcher": [],
      "group": {
        "kind": "build",
        "isDefault": true
      }
    },
    {
      "type": "shell",
      "label": "清理",
      "command": "hexo clean",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "生成",
      "command": "hexo generate",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "预览",
      "command": "hexo server",
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "新建文章",
      "command": "hexo",
      "args": ["new", "post", "${input:postName}"],
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    },
    {
      "type": "shell",
      "label": "新建草稿",
      "command": "hexo",
      "args": ["new", "draft", "${input:postName}"],
      "presentation": {
        "panel": "dedicated",
        "clear": true
      },
      "problemMatcher": []
    }
  ],
  "inputs": [
    {
      "type": "promptString",
      "id": "postName",
      "description": "文章名称"
    }
  ]
}

TODO List

准备做,但时间不确定的需求

自建 不蒜子 API

https://busuanzi.icodeq.com/

https://github.com/zkeq/Busuanzi_backend_self

访问速度优化

进行中

Search JS 优化

hexo-generator-searchdb

目标实例

CSS整理

进行中

插件内置修改

性能优化,外部插件内置修改

进行中

字体优化

字体体积比较大,是拖慢网页加载速度的重要因素。减少它的体积是重要的加速手段

Done!

  1. font forge
  2. hexo-fontawesome
  3. Customize-Font-Awesome
  4. 在线精简
    1. Fontello: http://fontello.com/
    2. IcoMoon: https://icomoon.io/app/#/select (How To)
    3. Fontastic: http://fontastic.me/

本教程还有其它五大部分,更多内容请见Hexo系列教程

系列教程

全部文章RSS订阅

Hexo系列

HexoRSS分类订阅

[三万字教程]基于Hexo的matery主题搭建博客并深度优化完全一站式教程

  • markdown 各种其它语法插件,latex公式支持,mermaid图表,plant uml图表,URL卡片,bilibili卡片,github卡片,豆瓣卡片,插入音乐和视频,插入脑图,插入PDF,嵌入iframe

笔记系列

Note分类RSS订阅

Gitbook使用系列

Gitbook分类RSS订阅

Gitlab 使用系列

Gitlab RSS 分类订阅


文章作者: 夜法之书
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 夜法之书 !
评论
 上一篇

阅读全文

基于Hexo的matery主题搭建博客常见问题篇6
基于Hexo的matery主题搭建博客常见问题篇6 基于Hexo的matery主题搭建博客常见问题篇6
在建立,使用hexo构建博客的时候遇到的各种各样问题,在这里记录,留念,方便后来者少踩几个坑,O(∩_∩)O
2022-03-27
下一篇 

阅读全文

基于Hexo的matery主题搭建博客增强部署篇4
基于Hexo的matery主题搭建博客增强部署篇4 基于Hexo的matery主题搭建博客增强部署篇4
如果你想自动化部署怎么办?同时部署到多个空间怎么办?如何多种方法同时使用,多线路负载均衡访问了?本篇文章帮助你一一实现!
2022-03-27
  目录