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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07f0dd2b889d4de8d8c69e590e6f491ba46921cd666cfa035a4d96aee505626b
4
- data.tar.gz: bee696a1b3f4e0cafa3ddf758cb43cec40c826f56c142a5fdb648346a13db8c2
3
+ metadata.gz: 601c6ff5abe598efcbd05754237c29ee0d75412553ab59596a1f44f798f8e340
4
+ data.tar.gz: 2dc954003e7c3d180c610d5faf0d5e1c29bb49e73434275a81305de55793a170
5
5
  SHA512:
6
- metadata.gz: 32166ea582c1644e3cc2d4da17158f1d9e21fafa5353d455bb116fb9601e0df1001dc308cfe2d75dec16bd612e92d7755c465c9f031927ce237578a890c9eae6
7
- data.tar.gz: dfca342f289480ae0c56ba93d00b9f36be79f175981b5ac9e827b81e25cd64be245ba527853c0e4562326df3be4ec11cc41617668214702f3aafe5b9d159c3ea
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.10, 2022-12-08
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 (and thus Antora).
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
 
@@ -35,5 +35,5 @@ Gem::Specification.new do |s|
35
35
  s.add_runtime_dependency 'asciidoctor', ['>= 2.0.0', '< 3.0.0']
36
36
 
37
37
  s.add_development_dependency 'rake', '~> 13.0.0'
38
- s.add_development_dependency 'rspec', '~> 3.11.0'
38
+ s.add_development_dependency 'rspec', '~> 3.12.0'
39
39
  end
data/data/css/tabs.css CHANGED
@@ -1,17 +1,17 @@
1
1
  /*! Asciidoctor Tabs | Copyright (c) 2018-present Dan Allen | MIT License */
2
- .tabset {
2
+ .tabs {
3
3
  margin-bottom: 1.25em;
4
4
  }
5
5
 
6
- .tabs > ul {
6
+ .tablist > ul {
7
7
  display: flex;
8
8
  flex-wrap: wrap;
9
9
  list-style: none;
10
- margin: 0 -0.25em 0 0;
10
+ margin: 0;
11
11
  padding: 0;
12
12
  }
13
13
 
14
- .tabs > ul li {
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
- .tabs.ulist > ul li {
26
- margin: 0;
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
- .tabs.ulist > ul li + li {
30
+ .tablist.ulist > ul li + li {
35
31
  margin-left: 0.25em;
36
32
  }
37
33
 
38
- .tabset.is-loading .tabs li:not(:first-child),
39
- .tabset:not(.is-loading) .tabs li:not(.is-active) {
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
- .tabset.is-loading .tabs li:first-child::after,
44
- .tabset:not(.is-loading) .tabs li.is-active::after {
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
- .tab-pane {
56
- background-color: #fff;
57
- padding: 1.25em;
51
+ .tablist > ul p {
52
+ line-height: inherit;
53
+ margin: 0;
58
54
  }
59
55
 
60
- .tab-pane > table.tableblock {
61
- border-width: 0;
62
- display: block;
63
- overflow-x: auto;
56
+ .tabpanel {
57
+ background-color: #fff;
58
+ padding: 1.25em;
64
59
  }
65
60
 
66
- .tabs > ul li,
67
- .tab-pane {
61
+ .tablist > ul li,
62
+ .tabpanel {
68
63
  border: 1px solid #dcdcdc;
69
64
  }
70
65
 
71
- .tabs > ul li {
66
+ .tablist > ul li {
72
67
  border-bottom: 0;
73
68
  }
74
69
 
75
- .tabset.is-loading .tab-pane:not(:first-child),
76
- .tabset:not(.is-loading) .tab-pane:not(.is-active) {
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
- .tab-pane > :first-child {
75
+ .tabpanel > :first-child {
81
76
  margin-top: 0;
82
77
  }
83
78
 
84
- #content .tab-pane > :last-child,
85
- #content .tab-pane > :last-child > :last-child,
86
- #content .tab-pane > :last-child > :last-child > li:last-child > :last-child {
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('.tabset'))
6
+ init(document.querySelectorAll('.tabs'))
7
7
 
8
- function init (tabsets) {
9
- if (!tabsets.length) return
10
- forEach.call(tabsets, function (tabset) {
11
- var tabs = tabset.querySelectorAll('.tabs li')
12
- var syncIds = tabset.classList.contains('is-sync') ? {} : undefined
13
- forEach.call(tabs, function (tab, idx) {
14
- var id = tab.id
15
- if (!id) {
16
- var anchor = tab.querySelector('a[id]')
17
- if (!anchor) return // invalid state
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
- tab.className = idx ? 'tab' : 'tab is-active'
21
- var pane = tabset.querySelector('.tab-pane[aria-labelledby~="' + id + '"]')
22
- if (!pane) return // invalid state
23
- if (!idx) pane.classList.add('is-active')
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 = { tabset: tabset, tab: tab, pane: pane }
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(tabsets, function (tabset) {
36
- tabset.classList.remove('is-loading')
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 tabset = this.tabset || (this.tabset = tab.closest('.tabset'))
44
- var pane = this.pane || tabset.querySelector('.tab-pane[aria-labelledby~="' + tab.id + '"]')
45
- forEach.call(tabset.querySelectorAll('.tabs li, .tab-pane'), function (el) {
46
- el === tab || el === pane ? el.classList.add('is-active') : el.classList.remove('is-active')
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 tabset = this.tabset
67
+ var tabs = this.tabs
58
68
  var thisTab = this.tab
59
- var initialY = tabset.getBoundingClientRect().y
60
- forEach.call(document.querySelectorAll('.tabs li'), function (tab) {
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 = tabset.getBoundingClientRect().y - initialY
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 && (source_tabs = children[0]).context == :dlist && source_tabs.items?
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, [(source_tabs.id = id), source_tabs]) unless source_tabs.id
15
- (reftext = attrs['reftext']) && (source_tabs.set_attr 'reftext', reftext) unless source_tabs.reftext?
16
- parent << source_tabs
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
- tabset_number = doc.counter 'tabset-number'
20
- tabs_id = attrs['id'] || (generate_id %(tabset #{tabset_number}), doc)
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
- parent << (create_html_fragment parent, %(<div id="#{tabs_id}" class="tabset#{sync || ''} is-loading">))
23
- if (title = attrs['title'])
24
- parent << (create_html_fragment parent, %(<div class="title">#{parent.apply_subs title}</div>))
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
- source_tabs.items.each do |labels, content|
27
+ seed_tabs.items.each do |labels, content|
31
28
  tab_ids = labels.map do |tab|
32
- tabs << tab
29
+ tablist << tab
33
30
  tab_id = generate_id tab.text, doc, tabs_id
34
- tab_source_text = tab.instance_variable_get :@text
35
- set_id_on_tab ? (tab.id = tab_id) : (tab.text = %([[#{tab_id}]]#{tab_source_text}))
36
- tab.add_role 'tab'
37
- (doc.register :refs, [tab_id, tab]).set_attr 'reftext', tab_source_text
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
- parent << tabs
54
- parent << (create_html_fragment parent, '<div class="content">')
49
+ tabs << tablist
55
50
  panes.each do |tab_ids, blocks|
56
- parent << (create_html_fragment parent, %(<div class="tab-pane" aria-labelledby="#{tab_ids.join ' '}">))
57
- blocks.each {|it| parent << it }
58
- parent << (create_html_fragment parent, '</div>')
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
- parent << (create_html_fragment parent, '</div>')
61
- create_html_fragment parent, '</div>', 'id' => tabs_id
56
+ tabs
62
57
  end
63
58
 
64
59
  private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module Tabs
5
- VERSION = '1.0.0.alpha.10'
5
+ VERSION = '1.0.0.alpha.12'
6
6
  end
7
7
  end
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.10
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-08 00:00:00.000000000 Z
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.11.0
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.11.0
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.