From 030a5af7b64c0b206b901653d992f62ad60b94f9 Mon Sep 17 00:00:00 2001 From: xaoxuu Date: Mon, 8 Mar 2021 17:54:23 +0800 Subject: [PATCH] tag-plugin: tabs --- scripts/tags/index.js | 8 +++ scripts/tags/lib/tabs.js | 36 ++++++++++ source/css/_common/base.styl | 2 +- source/css/_common/highlight.styl | 2 +- source/css/_common/mobile-only.styl | 2 +- source/css/_defines/func.styl | 2 +- source/css/_defines/theme.styl | 4 +- source/css/_layout/md.styl | 6 +- source/css/_layout/partial/navbar.styl | 2 +- source/css/_layout/partial/related.styl | 2 +- source/css/_layout/sidebar/toc.styl | 8 +-- source/css/_layout/tag-plugins/checkbox.styl | 5 +- source/css/_layout/tag-plugins/copy.styl | 2 +- source/css/_layout/tag-plugins/friends.styl | 2 +- source/css/_layout/tag-plugins/tabs.styl | 76 ++++++++++++++++++++ source/js/main.js | 33 ++++++++- 16 files changed, 173 insertions(+), 19 deletions(-) create mode 100644 scripts/tags/index.js create mode 100644 scripts/tags/lib/tabs.js create mode 100644 source/css/_layout/tag-plugins/tabs.styl diff --git a/scripts/tags/index.js b/scripts/tags/index.js new file mode 100644 index 0000000..55bee61 --- /dev/null +++ b/scripts/tags/index.js @@ -0,0 +1,8 @@ +/* global hexo */ + +'use strict'; + +const postTabs = require('./lib/tabs')(hexo); +hexo.extend.tag.register('tabs', postTabs, true); +hexo.extend.tag.register('subtabs', postTabs, true); +hexo.extend.tag.register('subsubtabs', postTabs, true); diff --git a/scripts/tags/lib/tabs.js b/scripts/tags/lib/tabs.js new file mode 100644 index 0000000..f7b4113 --- /dev/null +++ b/scripts/tags/lib/tabs.js @@ -0,0 +1,36 @@ +/** + * tabs.js | https://theme-next.js.org/docs/tag-plugins/tabs + */ + +'use strict'; + +module.exports = ctx => function(args, content) { + const tabBlock = /\n([\w\W\s\S]*?)/g; + args = ctx.args.map(args, ['active', 'codeblock', 'color'], ['tabName']); + const tabName = args.tabName; + const tabActive = Number(args.active) || 0; + + let match; + let tabId = 0; + let tabNav = ''; + let tabContent = ''; + + if (!tabName) ctx.log.warn('Tabs block must have unique name!'); + + while ((match = tabBlock.exec(content)) !== null) { + let {caption, codeblock} = ctx.args.map(match[1].split(' '), ['codeblock'], ['caption']); + let postContent = ctx.render.renderSync({ text: match[2], engine: 'markdown' }).trim(); + + const abbr = tabName + ' ' + ++tabId; + const href = abbr.toLowerCase().split(' ').join('-'); + + const isActive = (tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1) ? ' active' : ''; + tabNav += `
  • ${caption || abbr}
  • `; + tabContent += `
    ${postContent}
    `; + } + + tabNav = ``; + tabContent = `
    ${tabContent}
    `; + + return `
    ${tabNav + tabContent}
    `; +}; diff --git a/source/css/_common/base.styl b/source/css/_common/base.styl index 77747e6..682b5d7 100644 --- a/source/css/_common/base.styl +++ b/source/css/_common/base.styl @@ -48,7 +48,7 @@ table:not([class]) background: var(--block) td,th padding: 0.5em 1em - border: 1px solid var(--hover-block) + border: 1px solid var(--block-hover) line-height: 1.5 tr word-break: keep-all diff --git a/source/css/_common/highlight.styl b/source/css/_common/highlight.styl index 1eecd29..9af7a17 100644 --- a/source/css/_common/highlight.styl +++ b/source/css/_common/highlight.styl @@ -19,7 +19,7 @@ article.md .highlight padding: 4px 0.5rem position: sticky left: 0 - background: var(--hover-block) + background: var(--block-hover) border-top-left-radius: "calc(%s - 1px)" % $border-block border-top-right-radius: "calc(%s - 1px)" % $border-block border-bottom: 1px solid var(--block-border) diff --git a/source/css/_common/mobile-only.styl b/source/css/_common/mobile-only.styl index e7a1d5b..523e7c8 100644 --- a/source/css/_common/mobile-only.styl +++ b/source/css/_common/mobile-only.styl @@ -14,7 +14,7 @@ padding-right: 2rem padding: 4px overflow: hidden - background: var(--hover-block) + background: var(--block-hover) .sidebar-toggle.mobile cursor: pointer diff --git a/source/css/_defines/func.styl b/source/css/_defines/func.styl index 1363101..164baaa 100644 --- a/source/css/_defines/func.styl +++ b/source/css/_defines/func.styl @@ -90,7 +90,7 @@ hover-block($v, $h, $br = 4px) padding: $v $h trans2 color background &:hover - background: var(--hover-block) + background: var(--block-hover) inside-box($fs = $fs-15) diff --git a/source/css/_defines/theme.styl b/source/css/_defines/theme.styl index 7fceb41..1064553 100644 --- a/source/css/_defines/theme.styl +++ b/source/css/_defines/theme.styl @@ -2,7 +2,7 @@ --site-bg: $c-site-bg-light --block: $c-block-light --block-border: mix($c-block-light, $c-text-light, 95) - --hover-block: mix($c-block-light, $c-text-light, 98) + --block-hover: mix($c-block-light, $c-text-light, 98) --text-p0: $c-title-light --text-p1: $c-text-light --text-p2: mix($c-text-light, $c-site-bg-light, 80) @@ -16,7 +16,7 @@ body[theme='dark'] --site-bg: $c-site-bg-dark --block: $c-block-dark --block-border: mix($c-block-dark, $c-text-dark, 90) - --hover-block: mix($c-block-dark, $c-text-dark, 95) + --block-hover: mix($c-block-dark, $c-text-dark, 95) --text-p0: $c-title-dark --text-p1: $c-text-dark --text-p2: mix($c-text-dark, $c-site-bg-dark, 70) diff --git a/source/css/_layout/md.styl b/source/css/_layout/md.styl index d0691cb..e9b1be6 100644 --- a/source/css/_layout/md.styl +++ b/source/css/_layout/md.styl @@ -38,7 +38,7 @@ article.md &:first-child margin-top: 0 h3 - margin-top: 3rem + margin-top: 1.5rem font-weight: 400 h4,h5,h6 font-weight: 500 @@ -70,6 +70,10 @@ article.md code font-family: $ff-code word-break: break-all font-size: $fs-p + background: var(--block) + padding: 2px + border-radius: 2px + border: 1px solid var(--block-border) // div article.md>div diff --git a/source/css/_layout/partial/navbar.styl b/source/css/_layout/partial/navbar.styl index 45af35d..7e061e2 100644 --- a/source/css/_layout/partial/navbar.styl +++ b/source/css/_layout/partial/navbar.styl @@ -22,7 +22,7 @@ nav.cap white-space: nowrap trans1 background &.active, &:hover - background: var(--hover-block) + background: var(--block-hover) color: var(--text-p1) diff --git a/source/css/_layout/partial/related.styl b/source/css/_layout/partial/related.styl index 8eb1604..754729b 100644 --- a/source/css/_layout/partial/related.styl +++ b/source/css/_layout/partial/related.styl @@ -26,7 +26,7 @@ min-width: 280px width: 40vw max-width: 460px - border: 1px solid var(--hover-block) + border: 1px solid var(--block-hover) .img min-width: 100% min-height: 140px diff --git a/source/css/_layout/sidebar/toc.styl b/source/css/_layout/sidebar/toc.styl index 3498405..84cafda 100644 --- a/source/css/_layout/sidebar/toc.styl +++ b/source/css/_layout/sidebar/toc.styl @@ -47,12 +47,12 @@ line-height: 1.2 border-radius: 4px &:hover - background: var(--hover-block) + background: var(--block-hover) &.active color: var(--theme-highlight) !important #toc .doc-tree - border-left: 2px solid var(--hover-block) + border-left: 2px solid var(--block-hover) a.doc-tree-link color: var(--text-p3) padding: 0.5rem @@ -65,10 +65,10 @@ color: var(--text-p2) font-size: $fs-14 &:hover - background: var(--hover-block) + background: var(--block-hover) #toc .widget-body.wiki .doc-tree.active border-color: var(--text-meta) .doc-tree.active:only-child - border-color: var(--hover-block) + border-color: var(--block-hover) diff --git a/source/css/_layout/tag-plugins/checkbox.styl b/source/css/_layout/tag-plugins/checkbox.styl index fb87382..c48b2f5 100644 --- a/source/css/_layout/tag-plugins/checkbox.styl +++ b/source/css/_layout/tag-plugins/checkbox.styl @@ -1,6 +1,5 @@ .md .checkbox display: flex - align-items: center margin: 0.25em 0 font-size: $fs-15 line-height: 1.2 @@ -21,6 +20,8 @@ margin-right: 8px if hexo-config('tag_plugins.checkbox.interactive') != true pointer-events: none + span + margin-top: 1px /* Checkbox */ input[type=checkbox] &:before, &:after @@ -155,7 +156,7 @@ .tag-plugin.checkbox - --theme: $color-theme + --theme: $c-blue .tag-plugin.checkbox[color='red'] --theme: mix($c-red, $c-card-light, 90) diff --git a/source/css/_layout/tag-plugins/copy.styl b/source/css/_layout/tag-plugins/copy.styl index 1d7e351..06d8bcb 100644 --- a/source/css/_layout/tag-plugins/copy.styl +++ b/source/css/_layout/tag-plugins/copy.styl @@ -21,7 +21,7 @@ margin: 0 border-left: 1px solid var(--block-border) display: inline-block - background: var(--hover-block) + background: var(--block-hover) line-height: 0 height: 100% font-size: 1rem diff --git a/source/css/_layout/tag-plugins/friends.styl b/source/css/_layout/tag-plugins/friends.styl index 3547b86..8a66bdd 100644 --- a/source/css/_layout/tag-plugins/friends.styl +++ b/source/css/_layout/tag-plugins/friends.styl @@ -66,7 +66,7 @@ >img trans2 transform box-shadow &:hover - background: var(--hover-block) + background: var(--block-hover) img transform: scale(1.2) rotate(8deg) box-shadow: $boxshadow-card-float diff --git a/source/css/_layout/tag-plugins/tabs.styl b/source/css/_layout/tag-plugins/tabs.styl new file mode 100644 index 0000000..10626b7 --- /dev/null +++ b/source/css/_layout/tag-plugins/tabs.styl @@ -0,0 +1,76 @@ +$tbr = $border-block + +.tag-plugin.tabs + display: block + position: relative + margin-top: 1rem + margin-bottom: 1rem + border-radius: $tbr + border: 1px solid var(--block-border) + font-size: $fs-14 + +.tag-plugin.tabs + ul.nav-tabs + display: flex + overflow-x: auto + white-space: nowrap + justify-content: flex-start + margin: 0 !important + padding: 8px 8px 0 8px + background: var(--block) + border-radius: $tbr $tbr 0 0 + line-height: 1.5 + li.tab + list-style-type: none + margin-top: 0 + margin-bottom: 0 + &:last-child + padding-right: 1rem + a + display: block + cursor: pointer + border-radius: $tbr $tbr 0 0 + padding: 0.5rem + text-align: center + font-size: $fs-14 + line-height: inherit + font-weight: 700 + color: var(--text-p3) + border: 1px solid transparent + &:hover + color: var(--text-p1) + i + pointer-events: none + &.active a + cursor: default + color: var(--text-p1) + background: var(--card) + border: 1px solid var(--block-border) + border-bottom: 1px solid var(--card) + + .tab-content + border-top: 1px solid var(--block-border) + margin-top: -1px + background: var(--card) + border-radius: 0 0 $tbr $tbr + .tab-pane + padding: 1rem + &:not(.active) + display: none + &.active + display: block + > + p,.tabs,ul,ol,.highlight,.note + &:first-child + margin-top: 0 + &:last-child + margin-bottom: 0 + + +.tag-plugin.tabs .tab-pane[codeblock] + padding: 0 + .highlight + border: none + border-radius: 0 + background: transparent + margin: 0 diff --git a/source/js/main.js b/source/js/main.js index 16cc0ff..1c604c8 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -230,7 +230,36 @@ const init = { $this.innerText = relativeValue } }) - } + }, + /** + * Tabs tag listener (without twitter bootstrap). + */ + registerTabsTag: function() { + // Binding `nav-tabs` & `tab-content` by real time permalink changing. + document.querySelectorAll('.tabs ul.nav-tabs .tab').forEach(element => { + element.addEventListener('click', event => { + event.preventDefault(); + // Prevent selected tab to select again. + if (element.classList.contains('active')) return; + // Add & Remove active class on `nav-tabs` & `tab-content`. + [...element.parentNode.children].forEach(target => { + target.classList.toggle('active', target === element); + }); + // https://stackoverflow.com/questions/20306204/using-queryselector-with-ids-that-are-numbers + const tActive = document.getElementById(element.querySelector('a').getAttribute('href').replace('#', '')); + [...tActive.parentNode.children].forEach(target => { + target.classList.toggle('active', target === tActive); + }); + // Trigger event + tActive.dispatchEvent(new Event('tabs:click', { + bubbles: true + })); + }); + }); + + window.dispatchEvent(new Event('tabs:register')); + }, + } @@ -238,7 +267,7 @@ const init = { init.toc() init.sidebar() init.relativeDate(document.querySelectorAll('#post-meta time')) - +init.registerTabsTag() // scrollreveal if (stellar.plugins.scrollreveal) {