mirror of
https://github.com/foo-dogsquared/website.git
synced 2025-01-30 22:57:59 +00:00
Add asciidoctor-tabs extension
This commit is contained in:
parent
50a03b1f8a
commit
566a7a9c98
1
Gemfile
1
Gemfile
@ -2,6 +2,7 @@ source 'https://rubygems.org'
|
||||
gem 'asciidoctor'
|
||||
gem 'asciidoctor-html5s'
|
||||
gem 'asciidoctor-rouge'
|
||||
gem 'asciidoctor-tabs', github: 'asciidoctor/asciidoctor-tabs'
|
||||
gem 'rouge'
|
||||
gem 'rubocop'
|
||||
gem 'asciidoctor-foodogsquared-extensions', :path => './gems'
|
||||
|
@ -1,3 +1,10 @@
|
||||
GIT
|
||||
remote: https://github.com/asciidoctor/asciidoctor-tabs.git
|
||||
revision: d5ee94b5253f4db75e6646f46511676af0be2cc3
|
||||
specs:
|
||||
asciidoctor-tabs (1.0.0.beta.3)
|
||||
asciidoctor (>= 2.0.0, < 3.0.0)
|
||||
|
||||
PATH
|
||||
remote: gems
|
||||
specs:
|
||||
@ -56,6 +63,7 @@ DEPENDENCIES
|
||||
asciidoctor-foodogsquared-extensions!
|
||||
asciidoctor-html5s
|
||||
asciidoctor-rouge
|
||||
asciidoctor-tabs!
|
||||
rouge
|
||||
rubocop
|
||||
ruby-lsp
|
||||
|
103
assets/css/asciidoctor-tabs.css
Normal file
103
assets/css/asciidoctor-tabs.css
Normal file
@ -0,0 +1,103 @@
|
||||
/*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */
|
||||
.tabs {
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
|
||||
.tablist > ul {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tablist > ul li {
|
||||
align-items: center;
|
||||
background-color: var(--base02);
|
||||
cursor: pointer;
|
||||
font-size: 0.8em;
|
||||
display: flex;
|
||||
padding: 0.5em;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background: var(--base01);
|
||||
}
|
||||
}
|
||||
|
||||
.tablist > ul li:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.tablist.ulist,
|
||||
.tablist.ulist > ul li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tablist.ulist > ul li + li {
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
.tabs.is-loading .tablist li:not(:first-child),
|
||||
.tabs:not(.is-loading) .tablist li:not(.is-selected) {
|
||||
background-color: var(--base00);
|
||||
}
|
||||
|
||||
.tabs.is-loading .tablist li:first-child::after,
|
||||
.tabs:not(.is-loading) .tablist li.is-selected::after {
|
||||
background-color: inherit;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 3px; /* Chrome doesn't always paint the line accurately, so add a little extra */
|
||||
position: absolute;
|
||||
bottom: -1.5px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.tablist > ul p {
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tabpanel {
|
||||
background-color: var(--base00);
|
||||
padding: 1.25em;
|
||||
}
|
||||
|
||||
.tablist > ul li,
|
||||
.tabpanel {
|
||||
border: var(--border-style);
|
||||
}
|
||||
|
||||
.tablist > ul li {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.tabs.is-loading .tabpanel + .tabpanel,
|
||||
.tabs:not(.is-loading) .tabpanel.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tabpanel > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* #content is a signature of the Asciidoctor standalone HTML output */
|
||||
#content .tabpanel > :last-child,
|
||||
#content .tabpanel > :last-child > :last-child,
|
||||
#content .tabpanel > :last-child > :last-child > li:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.tablecontainer {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#content .tablecontainer {
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
|
||||
#content .tablecontainer > table.tableblock {
|
||||
margin-bottom: 0;
|
||||
}
|
118
assets/js/asciidoctor-tabs.js
Normal file
118
assets/js/asciidoctor-tabs.js
Normal file
@ -0,0 +1,118 @@
|
||||
;(function () { /*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */
|
||||
'use strict'
|
||||
|
||||
var config = (document.currentScript || {}).dataset || {}
|
||||
var forEach = Array.prototype.forEach
|
||||
|
||||
init(document.querySelectorAll('.tabs'))
|
||||
|
||||
function init (tabsBlocks) {
|
||||
if (!tabsBlocks.length) return
|
||||
forEach.call(tabsBlocks, function (tabs) {
|
||||
var syncIds = tabs.classList.contains('is-sync') ? {} : undefined
|
||||
var tablist = tabs.querySelector('.tablist ul')
|
||||
tablist.setAttribute('role', 'tablist')
|
||||
var initial
|
||||
forEach.call(tablist.querySelectorAll('li'), function (tab, idx) {
|
||||
tab.setAttribute('role', (tab.className = 'tab')) // NOTE converter may not have set class on li
|
||||
var id, anchor, syncId
|
||||
if (!(id = tab.id)) {
|
||||
if (!(anchor = tab.querySelector('a[id]'))) return // invalid state
|
||||
tab.id = id = anchor.parentNode.removeChild(anchor).id
|
||||
}
|
||||
var panel = tabs.querySelector('.tabpanel[aria-labelledby~="' + id + '"]')
|
||||
if (!panel) return // invalid state
|
||||
tab.tabIndex = -1
|
||||
syncIds && (((syncId = tab.textContent.trim()) in syncIds) ? (syncId = undefined) : true) &&
|
||||
(syncIds[(tab.dataset.syncId = syncId)] = tab)
|
||||
idx || (initial = { tab: tab, panel: panel }) && syncIds ? toggleHidden(panel, true) : toggleSelected(tab, true)
|
||||
tab.setAttribute('aria-controls', panel.id)
|
||||
panel.setAttribute('role', 'tabpanel')
|
||||
forEach.call(panel.querySelectorAll('table.tableblock'), function (table) {
|
||||
var container = Object.assign(document.createElement('div'), { className: 'tablecontainer' })
|
||||
table.parentNode.insertBefore(container, table).appendChild(table)
|
||||
})
|
||||
var onClick = syncId === undefined ? activateTab : activateTabSync
|
||||
tab.addEventListener('click', onClick.bind({ tabs: tabs, tab: tab, panel: panel }))
|
||||
})
|
||||
if (syncIds && initial) {
|
||||
var syncGroupId
|
||||
for (var i = 0, lst = tabs.classList, len = lst.length, className; i !== len; i++) {
|
||||
if (!(className = lst.item(i)).startsWith('data-sync-group-id=')) continue
|
||||
tabs.dataset.syncGroupId = syncGroupId = lst.remove(className) || className.slice(19).replace(/\u00a0/g, ' ')
|
||||
break
|
||||
}
|
||||
if (syncGroupId === undefined) tabs.dataset.syncGroupId = syncGroupId = Object.keys(syncIds).sort().join('|')
|
||||
var preferredSyncId = 'syncStorageKey' in config &&
|
||||
window[(config.syncStorageScope || 'local') + 'Storage'].getItem(config.syncStorageKey + '-' + syncGroupId)
|
||||
var tab = preferredSyncId && syncIds[preferredSyncId]
|
||||
tab && Object.assign(initial, { tab: tab, panel: document.getElementById(tab.getAttribute('aria-controls')) })
|
||||
toggleSelected(initial.tab, true) || toggleHidden(initial.panel, false)
|
||||
}
|
||||
})
|
||||
onHashChange()
|
||||
toggleClassOnEach(tabsBlocks, 'is-loading', 'remove')
|
||||
window.setTimeout(toggleClassOnEach.bind(null, tabsBlocks, 'is-loaded', 'add'), 0)
|
||||
window.addEventListener('hashchange', onHashChange)
|
||||
}
|
||||
|
||||
function activateTab (e) {
|
||||
var tab = this.tab
|
||||
var tabs = this.tabs || (this.tabs = tab.closest('.tabs'))
|
||||
var panel = this.panel || (this.panel = document.getElementById(tab.getAttribute('aria-controls')))
|
||||
forEach.call(tabs.querySelectorAll('.tablist .tab'), function (el) {
|
||||
toggleSelected(el, el === tab)
|
||||
})
|
||||
forEach.call(tabs.querySelectorAll('.tabpanel'), function (el) {
|
||||
toggleHidden(el, el !== panel)
|
||||
})
|
||||
if (!this.isSync && 'syncStorageKey' in config && 'syncGroupId' in tabs.dataset) {
|
||||
var storageKey = config.syncStorageKey + '-' + tabs.dataset.syncGroupId
|
||||
window[(config.syncStorageScope || 'local') + 'Storage'].setItem(storageKey, tab.dataset.syncId)
|
||||
}
|
||||
if (!e) return
|
||||
var loc = window.location
|
||||
var hashIdx = loc.hash ? loc.href.indexOf('#') : -1
|
||||
if (~hashIdx) window.history.replaceState(null, '', loc.href.slice(0, hashIdx))
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
function activateTabSync (e) {
|
||||
activateTab.call(this, e)
|
||||
var thisTabs = this.tabs
|
||||
var thisTab = this.tab
|
||||
var initialY = thisTabs.getBoundingClientRect().y
|
||||
forEach.call(document.querySelectorAll('.tabs'), function (tabs) {
|
||||
if (tabs === thisTabs || tabs.dataset.syncGroupId !== thisTabs.dataset.syncGroupId) return
|
||||
forEach.call(tabs.querySelectorAll('.tablist .tab'), function (tab) {
|
||||
if (tab.dataset.syncId === thisTab.dataset.syncId) activateTab.call({ tabs: tabs, tab: tab, isSync: true })
|
||||
})
|
||||
})
|
||||
var shiftedBy = thisTabs.getBoundingClientRect().y - initialY
|
||||
if (shiftedBy && (shiftedBy = Math.round(shiftedBy))) window.scrollBy({ top: shiftedBy, behavior: 'instant' })
|
||||
}
|
||||
|
||||
function toggleClassOnEach (elements, className, method) {
|
||||
forEach.call(elements, function (el) {
|
||||
el.classList[method](className)
|
||||
})
|
||||
}
|
||||
|
||||
function toggleHidden (el, state) {
|
||||
el.classList[(el.hidden = state) ? 'add' : 'remove']('is-hidden')
|
||||
}
|
||||
|
||||
function toggleSelected (el, state) {
|
||||
el.setAttribute('aria-selected', '' + state)
|
||||
el.classList[state ? 'add' : 'remove']('is-selected')
|
||||
el.tabIndex = state ? 0 : -1
|
||||
}
|
||||
|
||||
function onHashChange () {
|
||||
var id = window.location.hash.slice(1)
|
||||
if (!id) return
|
||||
var tab = document.getElementById(~id.indexOf('%') ? decodeURIComponent(id) : id)
|
||||
if (!(tab && tab.classList.contains('tab'))) return
|
||||
'syncId' in tab.dataset ? activateTabSync.call({ tab: tab }) : activateTab.call({ tab: tab })
|
||||
}
|
||||
})()
|
@ -15,7 +15,8 @@ path = "github.com/foo-dogsquared/hugo-mod-web-feeds"
|
||||
|
||||
[markup.asciidocExt]
|
||||
extensions = [
|
||||
"asciidoctor-foodogsquared-extensions"
|
||||
"asciidoctor-foodogsquared-extensions",
|
||||
"asciidoctor-tabs",
|
||||
]
|
||||
workingFolderCurrent = true
|
||||
|
||||
|
15
gemset.nix
15
gemset.nix
@ -49,6 +49,21 @@
|
||||
targets = [ ];
|
||||
version = "0.4.0";
|
||||
};
|
||||
asciidoctor-tabs = {
|
||||
dependencies = ["asciidoctor"];
|
||||
groups = ["default"];
|
||||
platforms = [];
|
||||
source = {
|
||||
fetchSubmodules = false;
|
||||
rev = "d5ee94b5253f4db75e6646f46511676af0be2cc3";
|
||||
sha256 = "1s2ds0f3v308vw4ic5dm6zh8d7dbi6lxxw6y7ajb8hmm27d0nksi";
|
||||
target = "ruby";
|
||||
type = "git";
|
||||
url = "https://github.com/asciidoctor/asciidoctor-tabs.git";
|
||||
};
|
||||
targets = [];
|
||||
version = "1.0.0.beta.3";
|
||||
};
|
||||
ast = {
|
||||
groups = [ "default" ];
|
||||
platforms = [ ];
|
||||
|
@ -5,6 +5,12 @@
|
||||
{{ end }}
|
||||
<link rel="stylesheet" href="{{ $highlighter.Permalink }}"/>
|
||||
|
||||
{{ $asciidoctorTabs := resources.Get "css/asciidoctor-tabs.css" | resources.ToCSS }}
|
||||
<link rel="stylesheet" href="{{ $asciidoctorTabs.Permalink }}"/>
|
||||
|
||||
{{ $asciidoctorTabsJS := resources.Get "js/asciidoctor-tabs.js" }}
|
||||
<script defer src="{{ $asciidoctorTabsJS.Permalink }}"></script>
|
||||
|
||||
{{- /* medium-zoom */ -}}
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/medium-zoom@1.0.7/dist/medium-zoom.min.js"></script>
|
||||
<script>window.addEventListener('load', () => mediumZoom('article img', { 'background': 'rgba(0, 0, 0, 0.75)' }))</script>
|
||||
|
Loading…
Reference in New Issue
Block a user