diff --git a/_config.yml b/_config.yml
index f5d51a7..441f68d 100755
--- a/_config.yml
+++ b/_config.yml
@@ -1,11 +1,11 @@
############################### Basic Information ###############################
info:
name: Volantis
- version: '2.0.2'
+ version: '2.1-beta'
docs: https://volantis.js.org/
cdn: # To use CDN, write 'use_cdn: true' in 'blog/_config.yml'.
- css: https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2.0.2.4/css/style.css
- js: https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2.0.2.4/js/app.js
+ # css: https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2.0.2.4/css/style.css
+ # js: https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2.0.2.4/js/app.js
############################### Style ###############################
diff --git a/scripts/tabs.js b/scripts/tabs.js
new file mode 100644
index 0000000..4b39576
--- /dev/null
+++ b/scripts/tabs.js
@@ -0,0 +1,59 @@
+/**
+ * tabs.js | https://theme-next.org/docs/tag-plugins/tabs
+ */
+
+/* global hexo */
+
+'use strict';
+
+function postTabs(args, content) {
+ var tabBlock = /\n([\w\W\s\S]*?)/g;
+
+ args = args.join(' ').split(',');
+ var tabName = args[0];
+ var tabActive = Number(args[1]) || 0;
+
+ var matches = [];
+ var match;
+ var tabId = 0;
+ var tabNav = '';
+ var tabContent = '';
+
+ !tabName && hexo.log.warn('Tabs block must have unique name!');
+
+ while ((match = tabBlock.exec(content)) !== null) {
+ matches.push(match[1]);
+ matches.push(match[2]);
+ }
+
+ for (var i = 0; i < matches.length; i += 2) {
+ var tabParameters = matches[i].split('@');
+ var postContent = matches[i + 1];
+ var tabCaption = tabParameters[0] || '';
+ var tabIcon = tabParameters[1] || '';
+ var tabHref = '';
+
+ postContent = hexo.render.renderSync({text: postContent, engine: 'markdown'}).trim();
+
+ tabId += 1;
+ tabHref = (tabName + ' ' + tabId).toLowerCase().split(' ').join('-');
+
+ ((tabCaption.length === 0) && (tabIcon.length === 0)) && (tabCaption = tabName + ' ' + tabId);
+
+ var isOnlyicon = tabIcon.length > 0 && tabCaption.length === 0 ? ' style="text-align: center;"' : '';
+ tabIcon.length > 0 && (tabIcon = ``);
+
+ var isActive = (tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1) ? ' active' : '';
+ tabNav += `
${tabIcon + tabCaption.trim()}`;
+ tabContent += `${postContent}
`;
+ }
+
+ tabNav = ``;
+ tabContent = `${tabContent}
`;
+
+ return `${tabNav + tabContent}
`;
+}
+
+hexo.extend.tag.register('tabs', postTabs, {ends: true});
+hexo.extend.tag.register('subtabs', postTabs, {ends: true});
+hexo.extend.tag.register('subsubtabs', postTabs, {ends: true});
diff --git a/source/css/_layout/tabs.styl b/source/css/_layout/tabs.styl
new file mode 100644
index 0000000..df6d0a4
--- /dev/null
+++ b/source/css/_layout/tabs.styl
@@ -0,0 +1,60 @@
+$table-border-color = $color-block
+$tbr = $borderradius-codeblock
+div.tabs
+ display: block
+ position: relative
+ margin-top: $gap-line
+ margin-bottom: $gap-line
+ border-bottom: 0
+ border-radius: $tbr
+ a
+ color: $color-text
+ &:hover
+ text-decoration: none
+
+
+div.tabs
+ ul.nav-tabs
+ display: flex
+ overflow-x: scroll
+ white-space: nowrap
+ justify-content: flex-start
+ margin: 0
+ padding: 0
+ padding-top: $borderradius-line
+ background: darken($color-block, 2)
+ border-radius: $tbr $tbr 0 0
+ li.tab
+ list-style-type: none
+ border-radius: $tbr $tbr 0 0
+ a
+ display: block
+ padding: $gap * 0.5
+ margin: 0 $gap * 0.5
+ text-align: center
+ font-size: $fontsize-meta
+ font-weight: bold
+ color: $color-meta
+ border-bottom: $borderradius-line solid transparent
+ &:hover
+ color: $color-p
+ border-bottom: $borderradius-line solid $color-meta
+ &.active a
+ cursor: default
+ color: $color-p
+ border-bottom: $borderradius-line solid $color-meta
+
+ .tab-content
+ overflow: hidden
+ .tab-pane
+ background: lighten($color-block, 2)
+ border-top: 0
+ border-radius: $tbr
+ padding: $gap-inline $gap
+ &:not(.active)
+ display: none
+
+ &.active
+ display: block
+ &:nth-of-type(1)
+ border-radius: 0 $tbr $tbr $tbr
diff --git a/source/js/app.js b/source/js/app.js
index d8d171c..511d3ae 100755
--- a/source/js/app.js
+++ b/source/js/app.js
@@ -303,6 +303,20 @@ var customSearch;
}
}
+ function setTabs() {
+ const $tabs = $('.tabs');
+ if ($tabs.length === 0) return;
+ $tabs.on('click', 'a', (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ $tabs.find('.nav-tabs .active').removeClass('active');
+ $tabs.find(e.target.parentElement).addClass('active');
+ $tabs.find('.tab-content .active').removeClass('active');
+ $tabs.find($(e.target).attr("href")).addClass('active');
+ return false;
+ });
+ }
+
$(function () {
setHeader();
setHeaderMenuSelection();
@@ -311,6 +325,7 @@ var customSearch;
setTocToggle();
setScrollAnchor();
setSearchService();
+ setTabs();
// $(".article .video-container").fitVids();
$('.scroll-down').on('click', function () {
scrolltoElement('.l_body');