asciidoctor-tabs 1.0.0.beta.2 → 1.0.0.beta.3

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: 0e0a17ea54a3c9b7c4c8e152b8cb6c80e4aceb4e7aaa9a03b7cf3dfdf5783d0c
4
- data.tar.gz: e9f4f8844fbdf8435bbb1fc99ac600b35820cabe0a22c4b51902cf39c851e203
3
+ metadata.gz: 79ee9882999f6e27787ce575352f3382272a502fa99c3e33090c265110290ab8
4
+ data.tar.gz: 1c8d5d2001a1b8f277ae84fc0c4e0f0d54f65266d97bd948e78835de7d5a91ae
5
5
  SHA512:
6
- metadata.gz: 0e296393e9638c0131b2e4c1a20ec388944de811295d28c30548befda9d786b5131c2039c2b46096a315218bb4a5335532603b0dd9cb557388f5283af7ddc04d
7
- data.tar.gz: e53ca031e1b78d56b80612403323254cd29ecf38c5a757af1996e3c08fb3a02bbe644ad9010c7a034c55062ec4b4752b669c02978ea6a90c9435d5568f280dce
6
+ metadata.gz: 4bf6818b2492f96aee01f2d29658e09a5bac3614e3c6e6565a83a817d0b1c5cf80897da04ca7859f0fe2fa6ce587cd5f10e37b74688a78e3c4d07a94a0b8d350
7
+ data.tar.gz: 12a6df3597b1c1da6fbff9f3bf130d1ec34d0485102bf780a27d8cde79596a22ca44b8f6620ab202ca6ac03d386da94e155d58b49d186e47117a02864ea5998e
data/CHANGELOG.adoc CHANGED
@@ -4,6 +4,23 @@
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-beta.3 (2023-02-01) - @mojavelinux
8
+
9
+ === Added
10
+
11
+ * Allow storage of sync tab selection to be configured using `tabs-sync-storage-key` and `tabs-sync-storage-scope` document attributes
12
+ * Add `is-loaded` class to tabs blocks on next tick after initialization for binding transitions (#50)
13
+ * Allow sync group ID to be specified rather than derived using the `sync-group-id` attribute on the tabs block (#52)
14
+
15
+ === Changed
16
+
17
+ * Rename data-sync-group attribute to data-sync-group-id
18
+ * Don't lowercase sync group ID
19
+
20
+ === Details
21
+
22
+ {url-repo}/releases/tag/v1.0.0-beta.3[git tag] | {url-repo}/compare/v1.0.0-beta.2\...v1.0.0-beta.3[full diff]
23
+
7
24
  == 1.0.0-beta.2 (2023-01-30) - @mojavelinux
8
25
 
9
26
  === Changed
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-beta.2, 2023-01-30
3
+ v1.0.0-beta.3, 2023-02-01
4
4
  :idprefix:
5
5
  :idseparator: -
6
6
  ifndef::env-github[:icons: font]
@@ -19,9 +19,10 @@ See the xref:js/README.adoc[README in the js folder] for details.
19
19
 
20
20
  == Overview
21
21
 
22
- Each set of tabs (a "`tabset`") is constructed from a description list (dlist) enclosed in an example block marked with the tabs style (i.e., `[tab]`).
23
- The tabbed interface that this block produces can help to organize information by code language, operating system, or product variant.
22
+ Each set of tabs (aka a "`tabset`" or tabs block) is constructed from a description list (dlist) enclosed in an example block marked with the tabs style (i.e., `[tab]`).
23
+ That nested combination of blocks gets translated by this extension into a single tabs block that is a specialization of an open block.
24
24
 
25
+ The tabbed interface produced from this block can help organize information by code language, operating system, or product variant.
25
26
  The benefit of organizing information in this way is that it condenses the use of vertical space by only showing what's relevant to the reader (and thus hiding information that's irrelevant or redundant).
26
27
  The result is that readers enjoy a better user experience when reading your documentation.
27
28
 
@@ -125,8 +126,10 @@ Tab B:: Contents of tab B in second tabset.
125
126
  ====
126
127
  ----
127
128
 
128
- Note that only tabs blocks with congruent tablists are synchronized.
129
+ Only tabs blocks with congruent tablists are synchronized by default.
129
130
  Each unique combination of tabs implicitly creates a new sync group.
131
+ You can override the sync group ID using the `sync-group-id` attribute on a tabs block to force it to participate in a sync group.
132
+ By default, the sync group ID is derived from the text of each tab, sorted, then joined on `|` (e.g., `A|B`).
130
133
 
131
134
  Alternately, you can set the `sync` option on each tabs block.
132
135
  If you want to delist a tabs block from sync, set the `nosync` option on that block.
@@ -134,6 +137,7 @@ If you want to delist a tabs block from sync, set the `nosync` option on that bl
134
137
  If you want to persist the sync selection, assign a value to the `data-sync-storage-key` attribute on the `<script>` tag.
135
138
  By default, the sync selection will be assigned to the specified key in local storage.
136
139
  You can set the `data-sync-storage-scope` attribute on the `<script>` tag to `session` to use session storage instead.
140
+ When using the extension on a standalone document, you can configure these options using the `tabs-sync-storage-key` and `tabs-sync-storage-scope` document attributes, respectively.
137
141
 
138
142
  == Usage
139
143
 
data/data/js/tabs.js CHANGED
@@ -23,7 +23,7 @@
23
23
  var panel = tabs.querySelector('.tabpanel[aria-labelledby~="' + id + '"]')
24
24
  if (!panel) return // invalid state
25
25
  tab.tabIndex = -1
26
- syncIds && (((syncId = tab.textContent.toLowerCase().trim()) in syncIds) ? (syncId = undefined) : true) &&
26
+ syncIds && (((syncId = tab.textContent.trim()) in syncIds) ? (syncId = undefined) : true) &&
27
27
  (syncIds[(tab.dataset.syncId = syncId)] = tab)
28
28
  idx || (initial = { tab: tab, panel: panel }) && syncIds ? toggleHidden(panel, true) : toggleSelected(tab, true)
29
29
  tab.setAttribute('aria-controls', panel.id)
@@ -36,18 +36,23 @@
36
36
  tab.addEventListener('click', onClick.bind({ tabs: tabs, tab: tab, panel: panel }))
37
37
  })
38
38
  if (syncIds && initial) {
39
- var syncGroup = tabs.dataset.syncGroup = Object.keys(syncIds).sort().join('|')
39
+ var syncGroupId
40
+ for (var i = 0, lst = tabs.classList, len = lst.length, className; i !== len; i++) {
41
+ if (!(className = lst.item(i)).startsWith('data-sync-group-id=')) continue
42
+ tabs.dataset.syncGroupId = syncGroupId = lst.remove(className) || className.slice(19).replace(/\u00a0/g, ' ')
43
+ break
44
+ }
45
+ if (syncGroupId === undefined) tabs.dataset.syncGroupId = syncGroupId = Object.keys(syncIds).sort().join('|')
40
46
  var preferredSyncId = 'syncStorageKey' in config &&
41
- window[(config.syncStorageScope || 'local') + 'Storage'].getItem(config.syncStorageKey + '-' + syncGroup)
47
+ window[(config.syncStorageScope || 'local') + 'Storage'].getItem(config.syncStorageKey + '-' + syncGroupId)
42
48
  var tab = preferredSyncId && syncIds[preferredSyncId]
43
49
  tab && Object.assign(initial, { tab: tab, panel: document.getElementById(tab.getAttribute('aria-controls')) })
44
50
  toggleSelected(initial.tab, true) || toggleHidden(initial.panel, false)
45
51
  }
46
52
  })
47
53
  onHashChange()
48
- forEach.call(tabsBlocks, function (tabs) {
49
- tabs.classList.remove('is-loading')
50
- })
54
+ toggleClassOnEach(tabsBlocks, 'is-loading', 'remove')
55
+ window.setTimeout(toggleClassOnEach.bind(null, tabsBlocks, 'is-loaded', 'add'), 0)
51
56
  window.addEventListener('hashchange', onHashChange)
52
57
  }
53
58
 
@@ -61,8 +66,8 @@
61
66
  forEach.call(tabs.querySelectorAll('.tabpanel'), function (el) {
62
67
  toggleHidden(el, el !== panel)
63
68
  })
64
- if (!this.isSync && 'syncStorageKey' in config && 'syncGroup' in tabs.dataset) {
65
- var storageKey = config.syncStorageKey + '-' + tabs.dataset.syncGroup
69
+ if (!this.isSync && 'syncStorageKey' in config && 'syncGroupId' in tabs.dataset) {
70
+ var storageKey = config.syncStorageKey + '-' + tabs.dataset.syncGroupId
66
71
  window[(config.syncStorageScope || 'local') + 'Storage'].setItem(storageKey, tab.dataset.syncId)
67
72
  }
68
73
  if (!e) return
@@ -78,23 +83,28 @@
78
83
  var thisTab = this.tab
79
84
  var initialY = thisTabs.getBoundingClientRect().y
80
85
  forEach.call(document.querySelectorAll('.tabs'), function (tabs) {
81
- if (tabs !== thisTabs && tabs.dataset.syncGroup === thisTabs.dataset.syncGroup) {
82
- forEach.call(tabs.querySelectorAll('.tablist .tab'), function (tab) {
83
- if (tab.dataset.syncId === thisTab.dataset.syncId) activateTab.call({ tabs: tabs, tab: tab, isSync: true })
84
- })
85
- }
86
+ if (tabs === thisTabs || tabs.dataset.syncGroupId !== thisTabs.dataset.syncGroupId) return
87
+ forEach.call(tabs.querySelectorAll('.tablist .tab'), function (tab) {
88
+ if (tab.dataset.syncId === thisTab.dataset.syncId) activateTab.call({ tabs: tabs, tab: tab, isSync: true })
89
+ })
86
90
  })
87
91
  var shiftedBy = thisTabs.getBoundingClientRect().y - initialY
88
92
  if (shiftedBy && (shiftedBy = Math.round(shiftedBy))) window.scrollBy({ top: shiftedBy, behavior: 'instant' })
89
93
  }
90
94
 
95
+ function toggleClassOnEach (elements, className, method) {
96
+ forEach.call(elements, function (el) {
97
+ el.classList[method](className)
98
+ })
99
+ }
100
+
91
101
  function toggleHidden (el, state) {
92
- el.classList.toggle('is-hidden', (el.hidden = state))
102
+ el.classList[(el.hidden = state) ? 'add' : 'remove']('is-hidden')
93
103
  }
94
104
 
95
105
  function toggleSelected (el, state) {
96
106
  el.setAttribute('aria-selected', '' + state)
97
- el.classList.toggle('is-selected', state)
107
+ el.classList[state ? 'add' : 'remove']('is-selected')
98
108
  el.tabIndex = state ? 0 : -1
99
109
  }
100
110
 
@@ -18,10 +18,10 @@ module Asciidoctor
18
18
  end
19
19
  tabs_number = doc.counter 'tabs-number'
20
20
  tabs_id = attrs['id'] || (generate_id %(tabs #{tabs_number}), doc)
21
- tabs_sync = !(block.option? 'nosync') && ((block.option? 'sync') || (doc.option? 'tabs-sync')) ? ' is-sync' : ''
22
- tabs_role = (tabs_role = attrs['role']) ? %( #{tabs_role}) : ''
23
- tabs = create_open_block parent, nil, { 'id' => tabs_id, 'role' => %(tabs#{tabs_sync}#{tabs_role} is-loading) }
24
- tabs.title = attrs['title']
21
+ tabs_role = 'tabs' + (!(block.option? 'nosync') && ((block.option? 'sync') || (doc.option? 'tabs-sync')) ?
22
+ ((gid = attrs['sync-group-id']) ? %( is-sync data-sync-group-id=#{gid.gsub ' ', ?\u00a0}) : ' is-sync') : '')
23
+ tabs_role += (tabs_user_role = attrs['role']) ? %( #{tabs_user_role} is-loading) : ' is-loading'
24
+ (tabs = create_open_block parent, nil, { 'id' => tabs_id, 'role' => tabs_role }).title = attrs['title']
25
25
  tablist = create_list parent, :ulist, { 'role' => 'tablist' }
26
26
  panes = {}
27
27
  set_id_on_tab = (doc.backend == 'html5') || (list_item_supports_id? doc)
@@ -35,11 +35,19 @@ module Asciidoctor
35
35
  JAVASCRIPT_FILE = ::File.join DATA_DIR, 'js/tabs.js'
36
36
 
37
37
  def process doc
38
+ if doc.attr? 'tabs-sync-storage-key'
39
+ config_attrs = %( data-sync-storage-key="#{doc.attr 'tabs-sync-storage-key'}")
40
+ if doc.attr? 'tabs-sync-storage-scope'
41
+ config_attrs += %( data-sync-storage-scope="#{doc.attr 'tabs-sync-storage-scope'}")
42
+ end
43
+ else
44
+ config_attrs = ''
45
+ end
38
46
  if doc.attr? 'linkcss'
39
47
  src = doc.normalize_web_path 'asciidoctor-tabs.js', (doc.attr 'scriptsdir')
40
- %(<script src="#{src}"></script>)
48
+ %(<script src="#{src}"#{config_attrs}></script>)
41
49
  elsif (script = doc.read_asset JAVASCRIPT_FILE)
42
- %(<script>\n#{script.chomp}\n</script>)
50
+ %(<script#{config_attrs}>\n#{script.chomp}\n</script>)
43
51
  end
44
52
  end
45
53
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module Tabs
5
- VERSION = '1.0.0.beta.2'
5
+ VERSION = '1.0.0.beta.3'
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.beta.2
4
+ version: 1.0.0.beta.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Allen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-30 00:00:00.000000000 Z
11
+ date: 2023-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor