asciidoctor-tabs 1.0.0.alpha.10 → 1.0.0.alpha.12

Sign up to get free protection for your applications and to get access to all the features.
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.