Efu让我转载他之前写的Solitude配置教程,那我顺便汇总整理下,方便大家参考。

那年今日卡片

  1. source 文件夹下找到 _data 文件夹(没有先新建),找到 aside.yml 文件(没有先新建)。在 aside.yml 文件中添加如下代码:
    - name: history
      title: 那年今日 
      class: card-history
      id:
      icon: solitude st-clock-fill
      content_class:
      content_id: history-baidu
      content_css: 'height:80px;overflow:hidden'
      content_html: '<div class="history_swiper-container" id="history-container" style="width: 100%;height: 100%;margin-top: 6px">
            <div id="history_container_wrapper" class="swiper-wrapper"></div>
          </div>'
  2. source 文件夹下找到 css 文件夹(没有先新建),找到 custom.css 文件(没有先新建)。在 custom.css 文件中添加如下代码:
/**
那年今日
*/

#aside-content .card-history .swiper-wrapper {
    flex-direction: column
}

#aside-content .card-history .history_slide {
    text-align: left;
    display: flex!important;
    flex-direction: column;
    align-items: flex-start
}

#aside-content .card-history #history-baidu>.blog-slider__pagination {
    display: none
}

#aside-content .card-history .history_slide_time {
    color: var(--ba-secondtext);
    font-size: 14px;
    font-style: italic;
    font-weight: lighter
}

#aside-content .card-history .history_slide_link {
    line-height: 1.5;
    -webkit-line-clamp: 2;
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical
}

#aside-content .card-history .history_slide_link a {
    color: var(--ba-main);
    padding: 0 4px;
    border-radius: 4px
}

#aside-content .card-history .history_slide_link a:hover {
    color: var(--ba-white);
    background: var(--ba-main)
}
/**
那年今日
*/

#aside-content .card-history .swiper-wrapper {
    flex-direction: column
}

#aside-content .card-history .item-headline {
    margin-left: 0;
}

#aside-content .card-history .history_slide {
    text-align: left;
    display: flex !important;
    flex-direction: column;
    align-items: flex-start
}

#aside-content .card-history .history_slide_time {
    color: var(--ba-secondtext);
    font-size: 14px;
    font-style: italic;
    font-weight: lighter
}

#aside-content .card-history .history_slide_link {
    line-height: 1.5;
    -webkit-line-clamp: 2;
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical
}

#aside-content .card-history .history_slide_link a {
    color: var(--ba-main);
    padding: 0 4px;
    border-radius: 4px
}

#aside-content .card-history .history_slide_link a:hover {
    color: var(--ba-white);
    background: var(--ba-main)
}
  1. source 文件夹下找到 js 文件夹(没有先新建),找到 custom.js 文件(没有先新建)。在 custom.js 文件中添加如下代码:
// 那年今日
(function() {
    async function fetchHistoryData() {
        const myDate = new Date();
        const myMonth = myDate.getMonth() + 1;
        const getDate = myDate.getDate();
        const getMonth = myMonth < 10 ? "0" + myMonth : "" + myMonth;
        const getDay = getDate < 10 ? "0" + getDate : "" + getDate;
        const getMonthDate = "S" + getMonth + getDay;
        const history_data_url = `https://fastly.jsdelivr.net/gh/Zfour/Butterfly-card-history@2.08/baiduhistory/json/${getMonth}.json`;

        const response = await fetch(history_data_url);
        const data = await response.json();
        return data[getMonthDate];
    }

    function append(parent, text) {
        const temp = document.createElement('div');
        temp.innerHTML = text;
        const frag = document.createDocumentFragment();
        while (temp.firstChild) {
            frag.appendChild(temp.firstChild);
        }
        parent.appendChild(frag);
    }

    function card_history() {
        if (document.getElementById('history-container')) {
            fetchHistoryData().then(data => {
                const html_item = data.map(item => `
        <div class="swiper-slide history_slide">
            <span class="history_slide_time">A.D.${item.year}</span>
            <span class="history_slide_link">${item.title}</span>
        </div>
        `).join('');
                const history_container_wrapper = document.getElementById('history_container_wrapper');
                append(history_container_wrapper, html_item);
                const swiper_history = new Swiper('.history_swiper-container', {
                    passiveListeners: true,
                    spaceBetween: 30,
                    effect: 'coverflow',
                    coverflowEffect: {
                        rotate: 30,
                        slideShadows: false,
                    },
                    loop: true,
                    direction: 'vertical',
                    autoplay: {
                        disableOnInteraction: true,
                        delay: 5000
                    },
                    mousewheel: false,
                });
                const history_container = document.getElementById('history-container');
                history_container.onmouseenter = function () {
                    swiper_history.autoplay.stop();
                };
                history_container.onmouseleave = function () {
                    swiper_history.autoplay.start();
                }
            });
        }
    }

    card_history();

    document.addEventListener('pjax:complete', card_history);
})();
// 那年今日
document.addEventListener('DOMContentLoaded', function () {
    async function cardHistory() {
        const historyContainer = document.getElementById('history-container');
        if (!historyContainer) return;
        const data = await fetchHistoryData();
        const html = data.map(item => `<div class="swiper-slide history_slide"><span class="history_slide_time">A.D.${item.year}</span><span class="history_slide_link">${item.title}</span></div>`).join('');
        const swiperContainer = document.querySelector('.history_swiper-container');
        document.getElementById('history_container_wrapper').innerHTML = html
        const swiperHistory = new Swiper(swiperContainer, {
            loop: true,
            direction: 'vertical',
            autoplay: {disableOnInteraction: true, delay: 5000},
            mousewheel: false,
        });
        historyContainer.onmouseenter = () => swiperHistory.autoplay.stop();
        historyContainer.onmouseleave = () => swiperHistory.autoplay.start();

        async function fetchHistoryData() {
            const myDate = new Date();
            const formattedDate = 'S' + `${myDate.getMonth() + 1}`.padStart(2, '0') + `${myDate.getDate()}`.padStart(2, '0');
            const historyDataUrl = `https://fastly.jsdelivr.net/gh/Zfour/Butterfly-card-history@2.08/baiduhistory/json/${myDate.getMonth() < 10 ? '0' + (myDate.getMonth() + 1) : myDate.getMonth() + 1}.json`;
            const response = await fetch(historyDataUrl);
            const data = await response.json();
            return data[formattedDate];
        }
    }
    cardHistory()
    document.addEventListener('pjax:complete', cardHistory);
})
  1. 在主题配置文件_config.solitude.ymlextendshead 中添加如下:
    - <link rel="stylesheet" href="/css/custom.css">
  2. 在主题配置文件_config.solitude.ymlextendsbody 中添加如下:
    - <script src="/js/custom.js"></script>

如果你没有使用 即刻短文的话,还需要在 extends 中添加如下:

extends:
   head:
     - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.css" />
   body:
     - <script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/11.0.5/swiper-bundle.min.js"></script>

新年倒计时卡片

新年倒计时卡片已在 1.9.0 版本后失效

  1. source 文件夹下找到 _data 文件夹(没有先新建),找到 aside.yml 文件(没有先新建)。在 aside.yml 文件中添加如下代码:
    home:
     noSticky:
        - class_name:
          id_name: newYear
          name:
          icon:
          html: '<div id="newYear-main">
             <p class="title"></p>
             <div class="newYear-time"></div>
             <p class="today" style="text-align: right;"></p>
             </div>'
     Sticky:
  2. 新建 custom.css 文件在 [root]/source/css 目录下(如果没有css文件夹,请新建),添加如下内容:
    /* 新年侧边栏 */
    #newYear {
     color: var(--ba-card-bg);
     padding: 0 !important;
    }
    
    #newYear p,
    #newYear h3 {
     font-weight: normal;
     color: inherit;
     margin: 0;
    }
    
    #newYear .item-headline {
     display: none;
    }
    
    #newYear-main {
     min-height: 160px;
     padding: 1rem;
     position: relative;
     border-radius: 12px;
     background-color: var(--ba-theme);
    }
    
    #newYear-main * {
     position: relative;
     line-height: 1.3;
    }
    
    #newYear-main .newYear-time {
     font-weight: bold;
     text-align: center;
    }
    
    #newYear-main .time,
    #newYear-main .happyNewYear {
     font-size: 2rem;
     text-shadow: 2px 2px 2px red;
     margin: 1rem 0;
     display: block;
    }
    
    #newYear-main .day {
     font-size: 5rem;
    }
    
    #newYear-main .day .unit {
     font-size: 1rem;
    }
  3. source 文件夹下找到 js 文件夹(没有先新建),找到 custom.js 文件(没有先新建)。在 custom.js 文件中添加如下代码:
    let newYearTimer = null;
    var newYear = () => {
    clearTimeout(newYearTimer);
    if (!document.querySelector('#newYear')) return;
    // 新年时间戳 and 星期对象
    let newYear = new Date('2024-02-10 00:00:00').getTime() / 1000,
    week = { 0: '周日', 1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六' }
    
        time();
    
        // 补零函数
        function nol(h) { return h > 9 ? h : '0' + h; };
    
        function time() {
            // 现在 时间对象
            let now = new Date();
    
            // 右下角 今天
            document.querySelector('#newYear .today').innerHTML = now.getFullYear() + '年' + (now.getMonth() + 1) + '月' + now.getDate() + '日 ' + week[now.getDay()]
    
            // 现在与新年相差秒数
            let second = newYear - Math.round(now.getTime() / 1000);
    
            // 小于0则表示已经过年
            if (second < 0) {
                document.querySelector('#newYear .title').innerHTML = '喜迎新年';
                document.querySelector('#newYear .newYear-time').innerHTML = '<span class="happyNewYear">新年快乐!</span>';
            } else {
                // 大于0则还未过年
                document.querySelector('#newYear .title').innerHTML = '距离2024年春节:'
    
                // 大于一天则直接渲染天数
                if (second > 86400) {
                    document.querySelector('#newYear .newYear-time').innerHTML = `<span class="day">${Math.ceil(second / 86400)}<span class="unit">天</span></span>`
                } else {
                    // 小于一天则使用时分秒计时。
                    let h = nol(parseInt(second / 3600));
                    second %= 3600;
                    let m = nol(parseInt(second / 60));
                    second %= 60;
                    let s = nol(second);
                    document.querySelector('#newYear .newYear-time').innerHTML = `<span class="time">${h}:${m}:${s}</span></span>`;
                    // 计时
                    newYearTimer = setTimeout(time, 1000);
                }
            }
        }
    }
    newYear();
    
    document.addEventListener('pjax:complete', newYear);
  4. 在主题配置文件的 extendshead 中添加如下内容:
    - <link rel="stylesheet" href="/css/custom.css">
  5. 在主题配置文件的 extendsbody 中添加如下内容:
    - <script src="/js/custom.js"></script>

友链申请验证

直观地展示出友链申请条件,保证其他人能够看到并在同意后进行申请,有效节省双方的时间。

  • Twikoo
<style>
.tk-comments > .tk-submit {
  opacity: 0;
  height: 0;
  transition: opacity 0.5s, height 0.5s;
  overflow: hidden;
}
</style>**勾选** 你符合的条件:

<div id="friends_checkbox">
<p>
    <label><input type="checkbox" onclick="checkForm()"> 我已添加 <b>btwoa</b> 博客的友情链接</label>
</p>
<p>
    <label><input type="checkbox" onclick="checkForm()"> 我的链接主体为 <b>个人</b>,网站类型为<b>博客</b></label>
</p>
<p>
    <label><input type="checkbox" onclick="checkForm()"> 我的网站现在可以在中国大陆区域正常访问</label>
</p>
<p>
    <label><input type="checkbox" onclick="checkForm()"> 网站内容符合中国大陆法律法规</label>
</p>
</div>

<script>
var twikooSubmit = document.getElementsByClassName("tk-submit")[0];
if(twikooSubmit) {
    twikooSubmit.style.opacity = "0";
}
function checkForm() {
    let comment = document.querySelector('.tk-submit');
    if(comment===null) return;
    let checkboxes = document.querySelectorAll('#friends_checkbox input[type="checkbox"]');
    let content = document.querySelector('.el-textarea__inner');
    let allChecked = Array.from(checkboxes).every(checkbox => checkbox.checked);
    if (allChecked) {
        comment.style.display = 'block';
        content.value = "```yaml \n- name: \n  link: \n  avatar: \n  descr: \n```";
        content.style.height = '205px';
        content.focus();
    } else {
        comment.style.display = 'none';
        content.value = '';
    }
}
window.onload = checkForm;
document.addEventListener('pjax:complete', checkForm);
</script>

无障碍快捷菜单

  1. 主题内置了配置项,启用并配置即可。
    keyboard:
      enable: false # 是否开启键盘控制 / Whether to enable keyboard control
      # 键盘控制配置
      # Keyboard control configuration
      list:
      # name: 按键名称
      # name: Key name
      # key: 按键
      # key: Key
      # func: 方法
      # func: Function
      # sco: sco内置方法
      # sco: sco built-in method
      # url: 跳转链接
      # url: Jump link
      #    - name: 关闭快捷键功能
      #      key: K
      #      func: keyboard
      #    - name: 打开中控台
      #      key: A
      #      sco: showConsole
      #    - name: 播放/暂停音乐
      #      key: M
      #      sco: musicToggle
      #    - name: 打开友情链接
      #      key: L
      #      url: '/links/'
  2. list 可添加的方法包括
    func: 自己定义的方法,主题内自带的非Sco的方法
    sco: Sco内置的方法
    link: 可直接写链接

    只能添加一个方法,如果添加多个方法,只会执行最后一个方法

  3. 我的配置
    keyboard:
     enable: true
     list:
       - name: 关闭快捷键功能
         key: K
         func: keyboard
       - name: 打开中控台
         key: A
         sco: showConsole
       - name: 播放/暂停音乐
         key: M
         sco: musicToggle
       - name: 深色/浅色显示切换
         key: N 
         sco: switchDarkMode
       - name: 站内搜索
         key: S
         func: openSearch
       - name: 随机访问
         key: R
         func: toRandomPost
       - name: 返回首页
         key: H
         url: /
       - name: 友链鱼塘
         key: F
         url: '/moments/'
       - name: 友情链接
         key: L
         url: '/links/'
       - name: 关于本站
         key: P
         url: '/about/' 
  4. 保存后,重新部署即可。
  5. 参考
类型方法说明
funcopenSearch打开站内搜索
functoRandomPost随机访问
scoswitchDarkMode切换深色/浅色模式
scoswitchKeyboard切换快捷键开关
scoshowConsole打开中控台
scomusicToggle播放/暂停音乐
scoswitchCommentBarrage切换弹幕开关
scotoTop回到顶部
link写需要跳转的地址

可拓展func ,自定义方法,方法名不能重复。

压缩代码

  1. 安装插件
npm install gulp compress gulp-clean-css gulp-html-minifier-terser gulp-htmlclean gulp-terser gulp-uglify --save
  1. 新建 gulpfile.js 文件
var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css');
var htmlmin = require('gulp-html-minifier-terser');
var htmlclean = require('gulp-htmlclean');
var terser = require('gulp-terser');
var uglify = require('gulp-uglify');
// 压缩js
gulp.task('compress', () =>
gulp.src(['./public/**/*.js', '!./public/**/*.min.js'])
.pipe(terser())
.pipe(uglify())
.pipe(gulp.dest('./public'))
)
//压缩css
gulp.task('minify-css', () => {
return gulp.src(['./public/**/*.css'])
.pipe(cleanCSS({
compatibility: 'ie11'
}))
.pipe(gulp.dest('./public'));
});
//压缩html
gulp.task('minify-html', () => {
return gulp.src('./public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true, //清除html注释
collapseWhitespace: true, //压缩html
collapseBooleanAttributes: true,
//省略布尔属性的值,例如:<input checked="true"/> ==> <input />
removeEmptyAttributes: true,
//删除所有空格作属性值,例如:<input id="" /> ==> <input />
removeScriptTypeAttributes: true,
//删除<script>的type="text/javascript"
removeStyleLinkTypeAttributes: true,
//删除<style>和<link>的 type="text/css"
minifyJS: true, //压缩页面 JS
minifyCSS: true, //压缩页面 CSS
minifyURLs: true  //压缩页面URL
}))
.pipe(gulp.dest('./public'))
});

// 运行gulp命令时依次执行以下任务
gulp.task('default', gulp.parallel(
'compress', 'minify-css', 'minify-html'
))

鼠标光标

为确保跟随的精度和反馈的准度,会实时跟随鼠标位置,监听鼠标事件,存在大量DOM操作,可能偶现卡顿,对资源占用敏感的不推荐使用

  1. custom.css 文件中添加如下代码
@media (max-width: 1000px) {
    html, body {
        cursor: default;
  }

  .circle {
      display: none;
  }

  .small-circle, .large-circle, body.hovered .small-circle::before, .pulse {
      display: none !important;
  }
}

@media (min-width: 1000px) {
    html, body {
        cursor: none;
  }

    html, body, img, div, a, span, path, svg, button, p, h1, h2, h3, h4, h5, h6, 
    b, strong, i, em, blockquote, ul, ol, li, pre, code, label, textarea, input, 
    select, option, audio, video, canvas, iframe, table, tr, td, th, thead, tbody, 
    tfoot, col, colgroup, form, fieldset, legend, nav, header, footer, article, 
    section, aside, figure, figcaption, details, summary, main {
        cursor: none !important;
    }
}

.circle {
    position: fixed;
    border-radius: 50%;
    pointer-events: none;
    display: none;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

.small-circle {
    width: 12px;
    height: 12px;
    background-color: #fff;
    mix-blend-mode: exclusion;
    z-index: 99999999;
    transition: transform 0.2s ease-out;
    transform-origin: center;
    box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
}

.large-circle {
    width: 32px;
    height: 32px;
    background: radial-gradient(circle, rgba(34, 34, 34, 0.2) 0%, rgba(34, 34, 34, 0.3) 100%);
    transition: transform 0.2s ease-out, left 0.2s ease-out, top 0.2s ease-out;
    z-index: 99999998;
    transform-origin: center;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}

.small-circle::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    width: 1px;
    height: 100%;
    background-color: #000;
    transform: translateX(-50%);
    visibility: hidden;
}

body.hovered .small-circle::before {
    visibility: visible;
}

@keyframes pulse {
    0% {
        transform: scale(0.5);
        opacity: 0.5;
    }
    50% {
        transform: scale(1);
        opacity: 0.8;
    }
    100% {
        transform: scale(0.5);
        opacity: 0.5;
    }
}

.pulse {
    animation: pulse 1.5s infinite;
}
  1. custom.js 文件中添加如下代码
const largeCircle = document.getElementById('largeCircle');
const smallCircle = document.getElementById('smallCircle');

let isMouseDown = false;
let isLargeCircleVisible = false;
let mouseX = 0;
let mouseY = 0;

function setPosition(x, y) {
    const halfLargeCircleWidth = largeCircle.offsetWidth / 2;
    const halfSmallCircleWidth = smallCircle.offsetWidth / 2;

    smallCircle.style.left = `${x - halfSmallCircleWidth}px`;
    smallCircle.style.top = `${y - halfSmallCircleWidth}px`;

    largeCircle.style.left = `${x - halfLargeCircleWidth}px`;
    largeCircle.style.top = `${y - halfLargeCircleWidth}px`;

    largeCircle.style.transform = isMouseDown ? 'scale(0.5)' : 'scale(1)';
    smallCircle.style.transform = isMouseDown ? 'scale(2)' : 'scale(1)';
}

function updateHoverStatus(x, y) {
    const textElements = document.querySelectorAll('p, h1, h2, h3, h4, h5, h6, span, a, div, pre, code, input, textarea');
    let isHoveringText = Array.from(textElements).some(el => {
        const textNodes = Array.from(el.childNodes).filter(node => node.nodeType === Node.TEXT_NODE);
        return textNodes.some(node => {
            const range = document.createRange();
            range.selectNodeContents(node);
            return Array.from(range.getClientRects()).some(rect =>
                x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
            );
        });
    });

    const inputElements = document.querySelectorAll('input, textarea');
    isHoveringText = isHoveringText || Array.from(inputElements).some(el => {
        const rect = el.getBoundingClientRect();
        return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
    });

    document.body.classList.toggle('hovered', isHoveringText);
}

function animate() {
    setPosition(mouseX, mouseY);
    updateHoverStatus(mouseX, mouseY);

    if (!isLargeCircleVisible) {
        isLargeCircleVisible = true;
        largeCircle.style.display = 'block';
        smallCircle.style.display = 'block';
    }

    requestAnimationFrame(animate);
}

function handleMove(event) {
    mouseX = event.clientX;
    mouseY = event.clientY;

    if (!isLargeCircleVisible) {
        requestAnimationFrame(animate);
    }
}

document.addEventListener('mousemove', handleMove);

document.addEventListener('mousedown', (event) => {
    isMouseDown = true;
    mouseX = event.clientX;
    mouseY = event.clientY;
    setPosition(mouseX, mouseY);
    largeCircle.classList.add('pulse');
});

document.addEventListener('mouseup', () => {
    isMouseDown = false;
    setPosition(mouseX, mouseY);
    largeCircle.classList.remove('pulse');
});
  1. layout/includes/inject/body.pug 文件顶部添加如下代码
#smallCircle.circle.small-circle
#largeCircle.circle.large-circle

主题标签

Solitude 主题 Plugin Tags 部分移植来自店长的 hexo-butterfly-tag-plugins-plus,转载请注明出处。
使用方法和配置项基本相同

btn 按钮

{% btn [url],[text],[icon],[color] [style] [layout] [position] [size] %}

[url] : 链接
[text] : 按钮文字
[icon] : [可选] 图标
[color] : [可选] 按钮背景顔色(默认 style 时)
按钮字体和边框顔色(outline 时)
bg-default/bg-blue/bg-pink/bg-red/bg-purple/bg-orange/bg-green
[style] : [可选] 按钮样式 默认实心
outline/留空
[layout] : [可选] 按钮佈局 默认为 line
block/留空
[position] : [可选] 按钮位置 前提是设置了 layout 为 block 默认为左边
center/right/留空
[size] : [可选] 按钮大小
larger/留空
参数含义
url链接
text按钮文字
icon[可选] 图标
color[可选] 按钮背景顔色(默认 style 时)按钮字体和边框顔色(outline 时)default/blue/pink/red/purple/orange/green
layout[可选] 按钮佈局 默认为 line block/留空
position[可选] 按钮位置 前提是设置了 layout 为 block 默认为左边 center/right/留空
size[可选] 按钮大小 larger/留空

一组按钮

This is my website, click the btn

This is my website, click the btn

This is my website, click the btn

This is my website, click the btn

This is my website, click the btn

调整位置或大小

more than one btn in center

居中按钮

> 一组按钮

This is my website, click the btn {% btn 'https://google.com/',G %}
This is my website, click the btn {% btn 'https://google.com/',G,st-lightbulb-line %}
This is my website, click the btn {% btn 'https://google.com/',G,outline %}
This is my website, click the btn {% btn 'https://google.com/',G,st-lightbulb-line,outline %}
This is my website, click the btn {% btn 'https://google.com/',G,st-lightbulb-line,larger %}

> 调整位置或大小

{% btn 'https://google.com/',G,st-lightbulb-line,block %}
{% btn 'https://google.com/',G,st-lightbulb-line,block center larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,block right outline larger %}

> more than one btn in center

<span>
{% btn 'https://google.com/',G,st-lightbulb-line,larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,blue larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,pink larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,red larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,purple larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,orange larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,green larger %}
</span>

> 居中按钮

<div class="btn-center">
{% btn 'https://google.com/',G,st-lightbulb-line,outline larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,outline blue larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,outline pink larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,outline red larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,outline purple larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,outline orange larger %}
{% btn 'https://google.com/',G,st-lightbulb-line,outline green larger %}
</div>

image 单张图片

{% image 链接, width=宽度(可选), height=高度(可选), alt=描述(可选), bg=占位颜色(可选) %}
  1. 图片宽度高度:width=300px, height=32px
  2. 图片描述:alt=图片描述
  3. 占位背景色:bg=#f2f2f2

添加描述

侵蚀之困
侵蚀之困

指定宽度

设置占位背景色

> 添加描述

{% image https://assets.btwoa.com/measure.avif, alt=侵蚀之困 %}

> 指定宽度

{% image https://assets.btwoa.com/measure.avif, width=500px %}

> 设置占位背景色

{% image https://assets.btwoa.com/measure.avif, width=400px, bg=#000000 %}

inlineimage 行内图片

{% inlineimage 图片链接, height=高度(可选) %}
  1. 高度:height=20px

这是 一段话。

这又是 一段话。

这是 {% inlineimage https://assets.btwoa.com/measure.avif %} 一段话。

这又是 {% inlineimage https://assets.btwoa.com/measure.avif, height=100px %} 一段话。

label 标签

{% label text color %}
参数释义
text文字
color【可选】背景颜色,默认为 default,default/blue/pink/red/purple/orange/green

臣亮言: 创业未半,而 。今天下三分, ,此诚 也!然侍衞之臣,不懈于内; ,忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气;不宜妄自菲薄,引喻失义,以塞忠谏之路也。
宫中、府中,俱为一体;陟罚臧否,不宜异同。若有 ,及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。

臣亮言:{% label 先帝 %}创业未半,而{% label 中道崩殂 blue %}。今天下三分,{% label 益州疲敝 pink %},此诚{% label 危急存亡之秋 red %}也!然侍衞之臣,不懈于内;{% label 忠志之士 purple %},忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气;不宜妄自菲薄,引喻失义,以塞忠谏之路也。
宫中、府中,俱为一体;陟罚臧否,不宜异同。若有{% label 作奸 orange %}、{% label 犯科 green %},及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。

audio 直链音频

{% audio 音频链接 %}
{% audio 音频链接 %}

video 直链视频

{% video 视频链接 %}
  1. 对其方向:left, center, right
  2. 列数:逗号后面直接写列数,支持 1 ~ 4 列。

默认

50% 宽度

25 %

> 默认

{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}

> 50% 宽度

{% videos, 2 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% endvideos %}

> 25 %

{% videos, 4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% video https://assets.btwoa.com/video/bueviocwmp.mp4 %}
{% endvideos %}

p 段落文本

{% p 样式参数(参数以空格划分), 文本内容 %}
  1. 字体: logo, code
  2. 颜色: red,yellow,green,cyan,blue,gray
  3. 大小: small, h4, h3, h2, h1, large, huge, ultra
  4. 对齐方向: left, center, right

red left

yellow center

green right

center h1

center ultra


{% p red left, red left %}

{% p yellow center, yellow center %}

{% p green right, green right %}

{% p center h1, center h1 %}

{% p center ultra, center ultra %}

Note (Bootstrap Callout)

{% note [class] %}
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam, libero.
{% endnote %}
参数含义
class显示值

显示值:(中间空格)

  • 配色
    • default / primary / success / info / warning / danger
  • 样式
    • simple / modern / flat / disabled
  • 图标
    • noicon

默认样式

Demo 1 - default

Simple 样式

Demo 1 - default

Demo 2 - primary

Demo 3 - success

Demo 4 - info

Demo 5 - warning

Demo 6 - danger

Modern 样式

Demo 1 - default

Demo 2 - primary

Demo 3 - success

Demo 4 - info

Demo 5 - warning

Demo 6 - danger

Flat 样式

Demo 1 - default

Demo 2 - primary

Demo 3 - success

Demo 4 - info

Demo 5 - warning

Demo 6 - danger

Disabled 样式

Demo 1 - default

Demo 2 - primary

Demo 3 - success

Demo 4 - info

Demo 5 - warning

Demo 6 - danger

默认样式:
{% note default %}
Demo 1 - default
{% endnote %}

1. Simple 样式
   {% note default simple %}
   Demo 1 - default
   {% endnote %}

{% note primary simple %}
Demo 2 - primary
{% endnote %}

{% note success simple %}
Demo 3 - success
{% endnote %}

{% note info simple %}
Demo 4 - info
{% endnote %}

{% note warning simple %}
Demo 5 - warning
{% endnote %}

{% note danger simple %}
Demo 6 - danger
{% endnote %}

2. Modern 样式
   {% note default modern %}
   Demo 1 - default
   {% endnote %}

{% note primary modern %}
Demo 2 - primary
{% endnote %}

{% note success modern %}
Demo 3 - success
{% endnote %}

{% note info modern %}
Demo 4 - info
{% endnote %}

{% note warning modern %}
Demo 5 - warning
{% endnote %}

{% note danger modern %}
Demo 6 - danger
{% endnote %}

3. Flat 样式
   {% note default flat %}
   Demo 1 - default
   {% endnote %}

{% note primary flat %}
Demo 2 - primary
{% endnote %}

{% note success flat %}
Demo 3 - success
{% endnote %}

{% note info flat %}
Demo 4 - info
{% endnote %}

{% note warning flat %}
Demo 5 - warning
{% endnote %}

{% note danger flat %}
Demo 6 - danger
{% endnote %}

3. Disabled 样式
   {% note default disabled %}
   Demo 1 - default
   {% endnote %}

{% note primary disabled %}
Demo 2 - primary
{% endnote %}

{% note success disabled %}
Demo 3 - success
{% endnote %}

{% note info disabled %}
Demo 4 - info
{% endnote %}

{% note warning disabled %}
Demo 5 - warning
{% endnote %}

{% note danger disabled %}
Demo 6 - danger
{% endnote %}

tabs 分栏

分栏支持内置codesign图标,如果开启了 customicon 则可以使用自定义的图标,否则只能使用默内置codesign图标

{% tabs Unique name, [index] %}

<!-- tab [Tab caption] [@icon] -->

Any content (support inline tags too).

<!-- endtab -->

{% endtabs %}
  1. Unique name:不带逗号的选项卡块标记的唯一名称。
    1. 将在 #id 中用作每个选项卡及其索引号的前缀。
    2. 如果名称中有空格,则对于生成 #id 所有空格都将替换为破折号。
    3. 仅帖子/页面的当前网址必须是唯一的!
  2. [index]:活动选项卡的索引号。
    1. 如果未指定,将选择第一个选项卡 (1)。
    2. 如果 index 为 -1,则不选择任何选项卡。这将是剧透。
    3. 可选参数。
  3. [Tab caption]:当前选项卡的标题。
    1. 如果未指定标题,则带有选项卡索引后缀的唯一名称将用作选项卡的标题。
    2. 如果未指定标题,但指定了图标,则标题将为空。
    3. 可选参数。
  4. [@icon]:图标名称(全名,例如“solitude st-logo”)
    1. 可以指定有或没有空格;例如,“Tab caption @icon”类似于“Tab caption@icon”。
    2. 可选参数。

Demo 1 - 预设选择第一个【默认】

This is Tab 1.

This is Tab 2.

This is Tab 3.

Demo 2 - 没有预设值

This is Tab 1.

This is Tab 2.

This is Tab 3.

Demo 3 - 自定义Tab名 + icon + Tab名和icon

This is Tab 1.

This is Tab 2.

This is Tab 3.

Demo 1 - 预设选择第一个【默认】


{% subtabs Demo1 %}
<!-- tab test1 -->
This is Tab 1.
<!-- endtab-->
<!-- tab test2 -->
This is Tab 2.
<!-- endtab-->
<!-- tab test3 -->
This is Tab 3.
<!-- endtab-->
{% endsubtabs %}

Demo 2 - 没有预设值

{% subtabs Demo2 %}
<!-- tab -->
This is Tab 1.
<!-- endtab-->
<!-- tab -->
This is Tab 2.
<!-- endtab-->
<!-- tab -->
This is Tab 3.
<!-- endtab-->
{% endsubtabs %}

Demo 3 - 自定义Tab名 + icon + Tab名和icon

{% subtabs Demo3 %}
<!-- tab test1  -->
This is Tab 1.
<!-- endtab-->
<!-- tab @st-mac -->
This is Tab 2.
<!-- endtab-->
<!-- tab Apple @st-mac -->
This is Tab 3.
<!-- endtab-->
{% endsubtabs %}

Timelne 时间轴

{% timeline title %}

{% timenode title %}

xxxx

{% endtimenode %}

{% timenode title %}

xxxx

{% endtimenode %}

{% endtimeline %}
参数含义
title节点名称
xxxx内容区

1976.4

史蒂夫·乔布斯、斯蒂夫·沃兹尼亚克和罗纳德·韦恩创立了苹果公司

1996

苹果收购NeXT公司,乔布斯于隔年重返苹果公司

2007.1

苹果电脑公司正式推出其首款智能手机iPhone,并宣布更名为苹果公司

2020.6

库克宣布Mac将采用自研的ARM芯片

{% timeline %}

{% timenode 1976.4 %}

史蒂夫·乔布斯、斯蒂夫·沃兹尼亚克和罗纳德·韦恩创立了苹果公司

{% endtimenode %}

{% timenode 1996 %}
 
苹果收购NeXT公司,乔布斯于隔年重返苹果公司

{% endtimenode %}

{% timenode 2007.1 %}
 
苹果电脑公司正式推出其首款智能手机iPhone,并宣布更名为苹果公司

{% endtimenode %}

{% timenode 2020.6 %}
 
库克宣布Mac将采用自研的ARM芯片

{% endtimenode %}

{% endtimeline %}
{% link [title],[subtitle],[link] %}
参数含义
title标题
subtitle简介
link跳转链接
{% link Google,谷歌搜索,https://google.com/ %}

{% link AUR,archlinux user repository,https://aur.archlinux.org/ %}

fold 折叠块

{% fold title open %}

{% endfold %}
参数含义
title标题(可选)
oepn是否打开(可选)不填默认不打开

Demo 1 - title

Demo1

Demo 2 - title + open

Demo2

Demo 1 - title

{% fold Demo1 %}

{% endfold %}

Demo 2 - title + open

{% fold Demo2 open %}

{% endfold %}

bvideo bilibili视频标签

{% bvideo [id] [time] %}
参数含义
urlbvid(例如视频链接后的:BV1k2421K7sQ)
{% bvideo BV1k2421K7sQ %}

checkbox 复选列表

{% checkbox 样式参数(可选), 文本内容 %}
  1. 样式: plus, minus, times
  2. 颜色: red,yellow,green,cyan,blue,gray
  3. 选中状态: checked

纯文本测试

支持简单的 markdown 语法

支持自定义颜色

绿色 + 默认选中

黄色 + 默认选中

青色 + 默认选中

蓝色 + 默认选中

增加

减少

{% checkbox 纯文本测试 %}
{% checkbox checked, 支持简单的 [markdown](https://guides.github.com/features/mastering-markdown/) 语法 %}
{% checkbox red, 支持自定义颜色 %}
{% checkbox green checked, 绿色 + 默认选中 %}
{% checkbox yellow checked, 黄色 + 默认选中 %}
{% checkbox cyan checked, 青色 + 默认选中 %}
{% checkbox blue checked, 蓝色 + 默认选中 %}
{% checkbox plus green checked, 增加 %}
{% checkbox minus yellow checked, 减少 %}
{% checkbox times red checked, 叉 %}

Katex

更换markdown-it渲染器

npm un hexo-renderer-marked --save
npm un hexo-renderer-kramed --save
npm i hexo-renderer-markdown-it --save
npm install katex @renbaoshuo/markdown-it-katex

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

# markdown-it
markdown:
    preset: 'default'
    render:
        html: true
        xhtmlOut: false
        langPrefix: 'language-'
        breaks: true
        linkify: true
        typographer: true
        quotes: '“”‘’'
    enable_rules:
    disable_rules:
    plugins:
        - '@renbaoshuo/markdown-it-katex'
    anchors:
        level: 2
        collisionSuffix: ''
        permalink: true
        permalinkClass: 'headerlink'
        permalinkSide: 'left'
        permalinkSymbol: ''
        case: 0
        separator: '-'
    images:
        lazyload: true
        prepend_root: false
        post_asset: false
    inline: false   

若在博文中使用Katex,只需在文章头部Front Matter添加katex: true

---
katex: true
---
$$
f(t)=\int_{-\infty}^\infty f(t) e^{-iwt}dt
$$

f(t)=f(t)eiwtdtf(t)=\int_{-\infty}^\infty f(t) e^{-iwt}dt

Typeit

{% typeit 'div' %}
options
{% endtypeit %}
参数含义
div标签名
{% typeit 'div' %}
waitUntilVisible: true,
strings: "Hello World",
{% endtypeit %}