asciidoctor-tabs 1.0.0.alpha.10 → 1.0.0.alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +34 -0
- data/README.adoc +3 -2
- data/asciidoctor-tabs.gemspec +1 -1
- data/data/css/tabs.css +39 -31
- data/data/js/tabs.js +46 -26
- data/lib/asciidoctor/tabs/block.rb +22 -27
- data/lib/asciidoctor/tabs/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 601c6ff5abe598efcbd05754237c29ee0d75412553ab59596a1f44f798f8e340
|
4
|
+
data.tar.gz: 2dc954003e7c3d180c610d5faf0d5e1c29bb49e73434275a81305de55793a170
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61ead4d57a662a73f3b754450127ff9ec16dc4ed40ae3a3997e0ce8562cdf3b501cba83bdc6f3c6d32d2dcc08c63900031010c1aeadad1b731f67c838848f8d0
|
7
|
+
data.tar.gz: e2eed95c99e32fbcd9630126ab6b9b73f88181a07f874c4f1aaf8f0b013dde42b873059ac9926b25c7127e800f1c68deddd6a88690a5650631a43a61ade848ca
|
data/CHANGELOG.adoc
CHANGED
@@ -4,6 +4,40 @@
|
|
4
4
|
This document provides a curated view of the changes to Asciidoctor Tabs per release.
|
5
5
|
For a detailed view of what has changed, refer to the {url-repo}/commits/main[commit history] on GitHub.
|
6
6
|
|
7
|
+
== 1.0.0-alpha.12 (2022-12-23) - @mojavelinux
|
8
|
+
|
9
|
+
=== Fixed
|
10
|
+
|
11
|
+
* Wrap div with class `tablecontainer` around tables inside tabpanel to prevent tables from overflowing bounds while honoring width (#41)
|
12
|
+
|
13
|
+
=== Details
|
14
|
+
|
15
|
+
{url-repo}/releases/tag/v1.0.0-alpha.12[git tag] | {url-repo}/compare/v1.0.0-alpha.11\...v1.0.0-alpha.12[full diff]
|
16
|
+
|
17
|
+
== 1.0.0-alpha.11 (2022-12-08) - @mojavelinux
|
18
|
+
|
19
|
+
=== Changed
|
20
|
+
|
21
|
+
* *BREAKING CHANGE:* Align terminology with ARIA / Open UI recommendations for a tabs component; requires change to custom CSS (#38)
|
22
|
+
** `.tabset` becomes `.tabs`
|
23
|
+
** `.tabs` becomes `.tablist`
|
24
|
+
** `.tab-panel` becomes `.tabpanel`
|
25
|
+
** `.is-active` for selected tab becomes `.is-selected`
|
26
|
+
** `.is-active` for visible panel becomes `:not(.is-hidden)`
|
27
|
+
* Assign ARIA attributes in JavaScript (i.e., role, aria-controls, aria-selected, hidden) where recommended (#38)
|
28
|
+
* *BREAKING CHANGE:* Convert tabs block to openblock instead of passthrough block (#15)
|
29
|
+
** `openblock` class added to `.tabs`
|
30
|
+
** `.tablist` becomes child of `.content`
|
31
|
+
** `.tabpanel` elements become siblings of `.tablist`
|
32
|
+
|
33
|
+
=== Fixed
|
34
|
+
|
35
|
+
* Clear margin on .tablist.ulist and child ul
|
36
|
+
|
37
|
+
=== Details
|
38
|
+
|
39
|
+
{url-repo}/releases/tag/v1.0.0-alpha.11[git tag] | {url-repo}/compare/v1.0.0-alpha.10\...v1.0.0-alpha.11[full diff]
|
40
|
+
|
7
41
|
== 1.0.0-alpha.10 (2022-12-08) - @mojavelinux
|
8
42
|
|
9
43
|
=== Fixed
|
data/README.adoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Asciidoctor Tabs
|
2
2
|
Dan Allen <https://github.com/mojavelinux[@mojavelinux]>
|
3
|
-
v1.0.0-alpha.
|
3
|
+
v1.0.0-alpha.12, 2022-12-23
|
4
4
|
:idprefix:
|
5
5
|
:idseparator: -
|
6
6
|
ifndef::env-github[:icons: font]
|
@@ -14,7 +14,8 @@ An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.
|
|
14
14
|
NOTE: This extension is intended to be used with HTML backends (e.g., `html5`).
|
15
15
|
For all other backends (i.e., the filetype is not html), the custom block enclosure is taken away and its contents (a dlist) is converted normally.
|
16
16
|
|
17
|
-
TIP: This extension is also published as an npm package named `@asciidoctor/tabs` for use with Asciidoctor.js
|
17
|
+
TIP: This extension is also published as an npm package named `@asciidoctor/tabs` for use with Asciidoctor.js.
|
18
|
+
See the xref:js/README.adoc[README in the js folder] for details.
|
18
19
|
|
19
20
|
== Overview
|
20
21
|
|
data/asciidoctor-tabs.gemspec
CHANGED
data/data/css/tabs.css
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
/*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */
|
2
|
-
.
|
2
|
+
.tabs {
|
3
3
|
margin-bottom: 1.25em;
|
4
4
|
}
|
5
5
|
|
6
|
-
.
|
6
|
+
.tablist > ul {
|
7
7
|
display: flex;
|
8
8
|
flex-wrap: wrap;
|
9
9
|
list-style: none;
|
10
|
-
margin: 0
|
10
|
+
margin: 0;
|
11
11
|
padding: 0;
|
12
12
|
}
|
13
13
|
|
14
|
-
.
|
14
|
+
.tablist > ul li {
|
15
15
|
align-items: center;
|
16
16
|
background-color: #fff;
|
17
17
|
cursor: pointer;
|
@@ -22,26 +22,22 @@
|
|
22
22
|
position: relative;
|
23
23
|
}
|
24
24
|
|
25
|
-
.
|
26
|
-
|
27
|
-
}
|
28
|
-
|
29
|
-
.tabs > ul p {
|
30
|
-
line-height: inherit;
|
25
|
+
.tablist.ulist,
|
26
|
+
.tablist.ulist > ul li {
|
31
27
|
margin: 0;
|
32
28
|
}
|
33
29
|
|
34
|
-
.
|
30
|
+
.tablist.ulist > ul li + li {
|
35
31
|
margin-left: 0.25em;
|
36
32
|
}
|
37
33
|
|
38
|
-
.
|
39
|
-
.
|
34
|
+
.tabs.is-loading .tablist li:not(:first-child),
|
35
|
+
.tabs:not(.is-loading) .tablist li:not(.is-selected) {
|
40
36
|
background-color: #f5f5f5;
|
41
37
|
}
|
42
38
|
|
43
|
-
.
|
44
|
-
.
|
39
|
+
.tabs.is-loading .tablist li:first-child::after,
|
40
|
+
.tabs:not(.is-loading) .tablist li.is-selected::after {
|
45
41
|
background-color: inherit;
|
46
42
|
content: "";
|
47
43
|
display: block;
|
@@ -52,37 +48,49 @@
|
|
52
48
|
right: 0;
|
53
49
|
}
|
54
50
|
|
55
|
-
.
|
56
|
-
|
57
|
-
|
51
|
+
.tablist > ul p {
|
52
|
+
line-height: inherit;
|
53
|
+
margin: 0;
|
58
54
|
}
|
59
55
|
|
60
|
-
.
|
61
|
-
|
62
|
-
|
63
|
-
overflow-x: auto;
|
56
|
+
.tabpanel {
|
57
|
+
background-color: #fff;
|
58
|
+
padding: 1.25em;
|
64
59
|
}
|
65
60
|
|
66
|
-
.
|
67
|
-
.
|
61
|
+
.tablist > ul li,
|
62
|
+
.tabpanel {
|
68
63
|
border: 1px solid #dcdcdc;
|
69
64
|
}
|
70
65
|
|
71
|
-
.
|
66
|
+
.tablist > ul li {
|
72
67
|
border-bottom: 0;
|
73
68
|
}
|
74
69
|
|
75
|
-
.
|
76
|
-
.
|
70
|
+
.tabs.is-loading .tabpanel:not(:first-child),
|
71
|
+
.tabs:not(.is-loading) .tabpanel.is-hidden {
|
77
72
|
display: none;
|
78
73
|
}
|
79
74
|
|
80
|
-
.
|
75
|
+
.tabpanel > :first-child {
|
81
76
|
margin-top: 0;
|
82
77
|
}
|
83
78
|
|
84
|
-
#content
|
85
|
-
#content .
|
86
|
-
#content .
|
79
|
+
/* #content is a signature of the Asciidoctor standalone HTML output */
|
80
|
+
#content .tabpanel > :last-child,
|
81
|
+
#content .tabpanel > :last-child > :last-child,
|
82
|
+
#content .tabpanel > :last-child > :last-child > li:last-child > :last-child {
|
83
|
+
margin-bottom: 0;
|
84
|
+
}
|
85
|
+
|
86
|
+
.tablecontainer {
|
87
|
+
overflow-x: auto;
|
88
|
+
}
|
89
|
+
|
90
|
+
#content .tablecontainer {
|
91
|
+
margin-bottom: 1.25em;
|
92
|
+
}
|
93
|
+
|
94
|
+
#content .tablecontainer > table.tableblock {
|
87
95
|
margin-bottom: 0;
|
88
96
|
}
|
data/data/js/tabs.js
CHANGED
@@ -3,26 +3,33 @@
|
|
3
3
|
|
4
4
|
var forEach = Array.prototype.forEach
|
5
5
|
|
6
|
-
init(document.querySelectorAll('.
|
6
|
+
init(document.querySelectorAll('.tabs'))
|
7
7
|
|
8
|
-
function init (
|
9
|
-
if (!
|
10
|
-
forEach.call(
|
11
|
-
var
|
12
|
-
var
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
8
|
+
function init (tabsBlocks) {
|
9
|
+
if (!tabsBlocks.length) return
|
10
|
+
forEach.call(tabsBlocks, function (tabs) {
|
11
|
+
var syncIds = tabs.classList.contains('is-sync') ? {} : undefined
|
12
|
+
var tablist = tabs.querySelector('.tablist ul')
|
13
|
+
tablist.setAttribute('role', 'tablist')
|
14
|
+
forEach.call(tablist.querySelectorAll('li'), function (tab, idx) {
|
15
|
+
tab.setAttribute('role', (tab.className = 'tab')) // NOTE converter may not have set class on li
|
16
|
+
var id, anchor
|
17
|
+
if (!(id = tab.id)) {
|
18
|
+
if (!(anchor = tab.querySelector('a[id]'))) return // invalid state
|
18
19
|
tab.id = id = anchor.parentNode.removeChild(anchor).id
|
19
20
|
}
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
var panel = tabs.querySelector('.tabpanel[aria-labelledby~="' + id + '"]')
|
22
|
+
if (!panel) return // invalid state
|
23
|
+
tab.tabIndex = -1
|
24
|
+
tab.setAttribute('aria-controls', panel.id)
|
25
|
+
panel.setAttribute('role', 'tabpanel')
|
26
|
+
idx ? toggleHidden(panel, true) : toggleSelected(tab, true)
|
27
|
+
forEach.call(panel.querySelectorAll('table.tableblock'), function (table) {
|
28
|
+
var container = Object.assign(document.createElement('div'), { className: 'tablecontainer' })
|
29
|
+
table.parentNode.insertBefore(container, table).appendChild(table)
|
30
|
+
})
|
24
31
|
var onClick = activateTab
|
25
|
-
var instance = {
|
32
|
+
var instance = { tabs: tabs, tab: tab, panel: panel }
|
26
33
|
var syncId
|
27
34
|
if (syncIds && !((syncId = tab.textContent.trim()) in syncIds)) {
|
28
35
|
syncIds[(tab.dataset.syncId = syncId)] = true
|
@@ -32,18 +39,21 @@
|
|
32
39
|
})
|
33
40
|
})
|
34
41
|
onHashChange()
|
35
|
-
forEach.call(
|
36
|
-
|
42
|
+
forEach.call(tabsBlocks, function (tabs) {
|
43
|
+
tabs.classList.remove('is-loading')
|
37
44
|
})
|
38
45
|
window.addEventListener('hashchange', onHashChange)
|
39
46
|
}
|
40
47
|
|
41
48
|
function activateTab (e) {
|
42
49
|
var tab = this.tab
|
43
|
-
var
|
44
|
-
var
|
45
|
-
forEach.call(
|
46
|
-
el
|
50
|
+
var tabs = this.tabs || (this.tabs = tab.closest('.tabs'))
|
51
|
+
var panel = this.panel || (this.panel = document.getElementById(tab.getAttribute('aria-controls')))
|
52
|
+
forEach.call(tabs.querySelectorAll('.tablist .tab'), function (el) {
|
53
|
+
toggleSelected(el, el === tab)
|
54
|
+
})
|
55
|
+
forEach.call(tabs.querySelectorAll('.tabpanel'), function (el) {
|
56
|
+
toggleHidden(el, el !== panel)
|
47
57
|
})
|
48
58
|
if (!e) return
|
49
59
|
var loc = window.location
|
@@ -54,16 +64,26 @@
|
|
54
64
|
|
55
65
|
function activateTabSync (e) {
|
56
66
|
activateTab.call(this, e)
|
57
|
-
var
|
67
|
+
var tabs = this.tabs
|
58
68
|
var thisTab = this.tab
|
59
|
-
var initialY =
|
60
|
-
forEach.call(document.querySelectorAll('.tabs
|
69
|
+
var initialY = tabs.getBoundingClientRect().y
|
70
|
+
forEach.call(document.querySelectorAll('.tabs .tablist .tab'), function (tab) {
|
61
71
|
if (tab !== thisTab && tab.dataset.syncId === thisTab.dataset.syncId) activateTab.call({ tab: tab })
|
62
72
|
})
|
63
|
-
var shiftedBy =
|
73
|
+
var shiftedBy = tabs.getBoundingClientRect().y - initialY
|
64
74
|
if (shiftedBy && (shiftedBy = Math.round(shiftedBy))) window.scrollBy({ top: shiftedBy, behavior: 'instant' })
|
65
75
|
}
|
66
76
|
|
77
|
+
function toggleHidden (el, state) {
|
78
|
+
el.classList.toggle('is-hidden', (el.hidden = state))
|
79
|
+
}
|
80
|
+
|
81
|
+
function toggleSelected (el, state) {
|
82
|
+
el.setAttribute('aria-selected', state)
|
83
|
+
el.classList.toggle('is-selected', state)
|
84
|
+
el.tabIndex = state ? 0 : -1
|
85
|
+
}
|
86
|
+
|
67
87
|
function onHashChange () {
|
68
88
|
var id = window.location.hash.slice(1)
|
69
89
|
if (!id) return
|
@@ -9,38 +9,34 @@ module Asciidoctor
|
|
9
9
|
def process parent, reader, attrs
|
10
10
|
block = create_block parent, attrs['cloaked-context'], nil, attrs, content_model: :compound
|
11
11
|
children = (parse_content block, reader).blocks
|
12
|
-
return block unless children.size == 1 && (
|
12
|
+
return block unless children.size == 1 && (seed_tabs = children[0]).context == :dlist && seed_tabs.items?
|
13
13
|
unless (doc = parent.document).attr? 'filetype', 'html'
|
14
|
-
(id = attrs['id']) && (doc.register :refs, [(
|
15
|
-
(reftext = attrs['reftext']) && (
|
16
|
-
parent <<
|
14
|
+
(id = attrs['id']) && (doc.register :refs, [(seed_tabs.id = id), seed_tabs]) unless seed_tabs.id
|
15
|
+
(reftext = attrs['reftext']) && (seed_tabs.set_attr 'reftext', reftext) unless seed_tabs.reftext?
|
16
|
+
parent << seed_tabs
|
17
17
|
return
|
18
18
|
end
|
19
|
-
|
20
|
-
tabs_id = attrs['id'] || (generate_id %(
|
19
|
+
tabs_number = doc.counter 'tabs-number'
|
20
|
+
tabs_id = attrs['id'] || (generate_id %(tabs #{tabs_number}), doc)
|
21
21
|
sync = !(block.option? 'nosync') && ((block.option? 'sync') || (doc.option? 'tabs-sync')) ? ' is-sync' : nil
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
tabs = create_list parent, :ulist
|
27
|
-
tabs.add_role 'tabs'
|
22
|
+
tabs = create_open_block parent, nil, { 'id' => tabs_id, 'role' => %(tabs#{sync || ''} is-loading) }
|
23
|
+
tabs.title = attrs['title']
|
24
|
+
tablist = create_list parent, :ulist, { 'role' => 'tablist' }
|
28
25
|
panes = {}
|
29
26
|
set_id_on_tab = (doc.backend == 'html5') || (list_item_supports_id? doc)
|
30
|
-
|
27
|
+
seed_tabs.items.each do |labels, content|
|
31
28
|
tab_ids = labels.map do |tab|
|
32
|
-
|
29
|
+
tablist << tab
|
33
30
|
tab_id = generate_id tab.text, doc, tabs_id
|
34
|
-
|
35
|
-
set_id_on_tab ? (tab.id = tab_id) : (tab.text = %([[#{tab_id}]]#{
|
36
|
-
tab.
|
37
|
-
(doc.register :refs, [tab_id, tab]).set_attr 'reftext',
|
31
|
+
tab_text_source = tab.instance_variable_get :@text
|
32
|
+
set_id_on_tab ? (tab.id = tab_id) : (tab.text = %([[#{tab_id}]]#{tab_text_source}))
|
33
|
+
tab.role = 'tab'
|
34
|
+
(doc.register :refs, [tab_id, tab]).set_attr 'reftext', tab_text_source
|
38
35
|
tab_id
|
39
36
|
end
|
40
37
|
if content
|
41
38
|
tab_blocks = content.text? ?
|
42
|
-
[(create_paragraph parent, (content.instance_variable_get :@text), nil, subs: :normal)]
|
43
|
-
: []
|
39
|
+
[(create_paragraph parent, (content.instance_variable_get :@text), nil, subs: :normal)] : []
|
44
40
|
if content.blocks?
|
45
41
|
if (block0 = (blocks = content.blocks)[0]).context == :open && blocks.size == 1 && block0.blocks?
|
46
42
|
blocks = block0.blocks
|
@@ -50,15 +46,14 @@ module Asciidoctor
|
|
50
46
|
end
|
51
47
|
panes[tab_ids] = tab_blocks || []
|
52
48
|
end
|
53
|
-
|
54
|
-
parent << (create_html_fragment parent, '<div class="content">')
|
49
|
+
tabs << tablist
|
55
50
|
panes.each do |tab_ids, blocks|
|
56
|
-
|
57
|
-
|
58
|
-
|
51
|
+
attrs = %( id="#{tab_ids[0]}--panel" class="tabpanel" aria-labelledby="#{tab_ids.join ' '}")
|
52
|
+
tabs << (create_html_fragment parent, %(<div#{attrs}>))
|
53
|
+
blocks.each {|it| tabs << it }
|
54
|
+
tabs << (create_html_fragment parent, '</div>')
|
59
55
|
end
|
60
|
-
|
61
|
-
create_html_fragment parent, '</div>', 'id' => tabs_id
|
56
|
+
tabs
|
62
57
|
end
|
63
58
|
|
64
59
|
private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-tabs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.alpha.
|
4
|
+
version: 1.0.0.alpha.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Allen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -50,14 +50,14 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 3.
|
53
|
+
version: 3.12.0
|
54
54
|
type: :development
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
57
|
requirements:
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 3.
|
60
|
+
version: 3.12.0
|
61
61
|
description: An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.
|
62
62
|
The tabset is constructed from a dlist enclosed in an example block marked with
|
63
63
|
the tabs style.
|