asciidoctor-tabs 1.0.0.alpha.4 → 1.0.0.alpha.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +38 -0
- data/README.adoc +62 -15
- data/data/js/tabs.js +27 -3
- data/lib/asciidoctor/tabs/block.rb +23 -18
- data/lib/asciidoctor/tabs/docinfo.rb +16 -8
- data/lib/asciidoctor/tabs/extensions.rb +1 -1
- data/lib/asciidoctor/tabs/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd23b52dcb671b18e2fc149ff7c4c0f131acc7b36c5a83df0003c22cc341d8cd
|
4
|
+
data.tar.gz: 502e57c0df6a007731a21dce2f382f54ea3e940c6548e914e91aab25d233a995
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41ddf35603690caa50d3685eb398ebbfd65ecc13630827731ec11493667a2bcd4db8616e530ae11cb8f05fa450d258b9e734ad4ee10fbe1bcaaf1c256ee681e7
|
7
|
+
data.tar.gz: ac3f2b5a3d44a8209436955dd5ebb74eff9e2bfbc0f107e572488859de78cb133817db3c5362c09198aee71b9381dfa56646e036ebd885b5cf05231b23231a7b
|
data/CHANGELOG.adoc
CHANGED
@@ -4,6 +4,44 @@
|
|
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.6 (2022-11-16) - @mojavelinux
|
8
|
+
|
9
|
+
=== Added
|
10
|
+
|
11
|
+
* Honor title on tabs block; apply normal subs to it (#26)
|
12
|
+
* Clear location hash (URL fragment) when a tab is clicked (#24)
|
13
|
+
* Register ref for each tab so its ID can be used as target of xref (#24)
|
14
|
+
* Activate tab when selected from an internal xref (#24)
|
15
|
+
|
16
|
+
=== Fixed
|
17
|
+
|
18
|
+
* Decode fragment from URL so it can be matched against tab ID (#27)
|
19
|
+
|
20
|
+
=== Details
|
21
|
+
|
22
|
+
{url-repo}/releases/tag/v1.0.0-alpha.6[git tag] | {url-repo}/compare/v1.0.0-alpha.5\...v1.0.0-alpha.6[full diff]
|
23
|
+
|
24
|
+
== 1.0.0-alpha.5 (2022-10-23) - @mojavelinux
|
25
|
+
|
26
|
+
=== Added
|
27
|
+
|
28
|
+
* Link to stylesheet (style) and script (behavior) if `linkcss` attribute is set on document (#7)
|
29
|
+
* Honor safe mode settings (don't read files if safe mode is secure) (#7)
|
30
|
+
|
31
|
+
=== Changed
|
32
|
+
|
33
|
+
* Rename Docinfo::Styles class to Docinfo::Style (#22)
|
34
|
+
* Add smoke test for npm package (#19)
|
35
|
+
|
36
|
+
=== Fixed
|
37
|
+
|
38
|
+
* Prevent dlist ref from being registered again to avoid warning when filetype is not html (#21)
|
39
|
+
* Restore missing default style and behavior in JavaScript version by mapping data dir to dist folder in npm package (#18)
|
40
|
+
|
41
|
+
=== Details
|
42
|
+
|
43
|
+
{url-repo}/releases/tag/v1.0.0-alpha.5[git tag] | {url-repo}/compare/v1.0.0-alpha.4\...v1.0.0-alpha.5[full diff]
|
44
|
+
|
7
45
|
== 1.0.0-alpha.4 (2022-10-08) - @mojavelinux
|
8
46
|
|
9
47
|
=== Added
|
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.6, 2022-11-16
|
4
4
|
:idprefix:
|
5
5
|
:idseparator: -
|
6
6
|
ifndef::env-github[:icons: font]
|
@@ -10,13 +10,20 @@ ifdef::env-github[]
|
|
10
10
|
endif::[]
|
11
11
|
|
12
12
|
An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.
|
13
|
-
Each set of tabs (a "tabset") is constructed from a dlist enclosed in an example block marked with the tabs style.
|
14
13
|
|
15
|
-
NOTE: This extension is intended to be used with HTML backends (e.g., `
|
16
|
-
For other backends (i.e., filetype is not html), the
|
14
|
+
NOTE: This extension is intended to be used with HTML backends (e.g., `html5`).
|
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.
|
17
16
|
|
18
17
|
TIP: This extension is also published as an npm package named `@asciidoctor/tabs` for use with Asciidoctor.js (and thus Antora).
|
19
18
|
|
19
|
+
== Overview
|
20
|
+
|
21
|
+
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]`).
|
22
|
+
The tabbed interface that this block produces can help to organize information by code language, operating system, or product variant.
|
23
|
+
|
24
|
+
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).
|
25
|
+
The result is that readers enjoy a better user experience when reading your documentation.
|
26
|
+
|
20
27
|
== Install
|
21
28
|
|
22
29
|
=== Using gem command
|
@@ -35,10 +42,10 @@ source 'https://rubygems.org'
|
|
35
42
|
gem 'asciidoctor-tabs'
|
36
43
|
|
37
44
|
# or use the code directlly from GitHub
|
38
|
-
# gem 'asciidoctor-tabs', github: 'asciidoctor/asciidoctor-
|
45
|
+
# gem 'asciidoctor-tabs', github: 'asciidoctor/asciidoctor-tabs'
|
39
46
|
----
|
40
47
|
|
41
|
-
Then configure Bundler to install gems locally
|
48
|
+
Then optionally configure Bundler to install gems locally:
|
42
49
|
|
43
50
|
$ bundle config --local path .bundle/gems
|
44
51
|
|
@@ -48,12 +55,7 @@ Then use Bundler to install the gem:
|
|
48
55
|
|
49
56
|
== Syntax
|
50
57
|
|
51
|
-
A tabset is defined using a dlist enclosed in an example block marked with the tabs style.
|
52
|
-
Each item in the dlist becomes a separate tab.
|
53
|
-
The term in the dlist item is used as the tab's label.
|
54
|
-
The description in the dlist item is used for the contents of the tab.
|
55
|
-
The contents can be defined as primary text, attached blocks, or blocks enclosed in an attached open block.
|
56
|
-
If the blocks are enclosed in an attached open block, the open block enclosure itself will be discarded.
|
58
|
+
A tabset is defined using a description list (dlist) enclosed in an example block marked with the tabs style.
|
57
59
|
|
58
60
|
.document-with-tabs.adoc
|
59
61
|
[,asciidoc]
|
@@ -76,6 +78,28 @@ Contains more than one block.
|
|
76
78
|
====
|
77
79
|
----
|
78
80
|
|
81
|
+
The tabbed content is modeled as a dlist.
|
82
|
+
Each item in the dlist becomes a separate tab.
|
83
|
+
The term is used as the tab's label and the description is used as the tab's contents.
|
84
|
+
The contents can be defined as primary text, attached blocks, or both.
|
85
|
+
If the attached blocks are themselves enclosed in a single open block, the open block enclosure itself is discarded upon conversion.
|
86
|
+
|
87
|
+
You may decide to extend the block delimiter length instead of using the typical 4 characters to avoid conflicts with any example blocks inside the tab block (or just as a manner of style).
|
88
|
+
|
89
|
+
[,asciidoc]
|
90
|
+
----
|
91
|
+
[tabs]
|
92
|
+
======
|
93
|
+
Tab A::
|
94
|
+
+
|
95
|
+
====
|
96
|
+
Example block in Tab A.
|
97
|
+
====
|
98
|
+
|
99
|
+
Tab B:: Just text.
|
100
|
+
======
|
101
|
+
----
|
102
|
+
|
79
103
|
== Usage
|
80
104
|
|
81
105
|
=== CLI
|
@@ -83,11 +107,12 @@ Contains more than one block.
|
|
83
107
|
$ asciidoctor -r asciidoctor-tabs document-with-tabs.adoc
|
84
108
|
|
85
109
|
You can specify an alternate stylesheet for tabs using the `tabs-stylesheet` document attribute.
|
86
|
-
The value of this attribute is handled in the same way as the built-in `stylesheet` document attribute.
|
87
|
-
A relative path is resolved starting from the value of the `stylesdir` document attribute, which defaults to the directory of the document.
|
88
110
|
|
89
111
|
$ asciidoctor -r asciidoctor-tabs -a tabs-stylesheet=my-tabs.css document-with-tabs.adoc
|
90
112
|
|
113
|
+
The value of the `tabs-stylesheet` attribute is handled in the same way as the built-in `stylesheet` document attribute.
|
114
|
+
A relative path is resolved starting from the value of the `stylesdir` document attribute, which defaults to the directory of the document.
|
115
|
+
|
91
116
|
=== API
|
92
117
|
|
93
118
|
There are two ways to use the extension with the Asciidoctor API.
|
@@ -116,13 +141,35 @@ Asciidoctor::Tabs::Extensions.register registry
|
|
116
141
|
Asciidoctor.convert_file 'document-with-tabs.adoc', extension_registry: registry, safe: :safe
|
117
142
|
----
|
118
143
|
|
119
|
-
If you're not using other scoped extensions, you can pass in the extensions group without creating a registry instance:
|
144
|
+
If you're not using other scoped extensions, you can pass in the extensions group without first creating a registry instance:
|
120
145
|
|
121
146
|
[,js]
|
122
147
|
----
|
123
148
|
Asciidoctor.convert_file 'document-with-tabs.adoc', extensions: Asciidoctor::Tabs::Extensions.group, safe: :safe
|
124
149
|
----
|
125
150
|
|
151
|
+
== How it Works
|
152
|
+
|
153
|
+
This extension works by transforming the dlist inside the example block into a tabbed interface.
|
154
|
+
The example block enclosure is discarded.
|
155
|
+
The tabbed interface is supported by a stylesheet (style) and script (behavior) that are added to the HTML document by this extension.
|
156
|
+
(These assets can be found in the [.path]_data_ folder of the gem).
|
157
|
+
|
158
|
+
NOTE: The stylesheet and script are only added when producing a standalone document.
|
159
|
+
The stylesheet is added to the end of the `<head>` tag and the script added to the end of the `<body>` tag.
|
160
|
+
If the `linkcss` attribute is set by the API, the CLI, the document, or the safe mode, the HTML links to these assets.
|
161
|
+
Otherwise, the contents of these assets are embedded into the HTML.
|
162
|
+
|
163
|
+
The tabbed interface consists of two output elements.
|
164
|
+
The first element contains an unordered list of all the tab labels in document order.
|
165
|
+
The second element contains all the tab panes.
|
166
|
+
The labels and panes are correlated through the use of a unique ID.
|
167
|
+
Each tab is assigned an `id` attribute and each pane is assigned an `aria-labelledby` attribute that references the corresponding ID.
|
168
|
+
The added stylesheet sets up the appearance of the tabbed interface and the added script supports the interaction (i.e., tab selection).
|
169
|
+
|
170
|
+
A tab can be selected when the page loads using a URL fragment (e.g., `#id-of-tab-here`).
|
171
|
+
Otherwise, the first tab is selected when the page loads.
|
172
|
+
|
126
173
|
== Authors
|
127
174
|
|
128
175
|
Asciidoctor Tabs was written by Dan Allen of OpenDevise Inc. and contributed to the Asciidoctor project.
|
data/data/js/tabs.js
CHANGED
@@ -2,8 +2,11 @@
|
|
2
2
|
;(function () {
|
3
3
|
'use strict'
|
4
4
|
|
5
|
-
var
|
6
|
-
|
5
|
+
var tabsets = find('.tabset')
|
6
|
+
if (!tabsets.length) return
|
7
|
+
var fragment = decodeFragment(window.location.hash)
|
8
|
+
|
9
|
+
tabsets.forEach(function (tabset) {
|
7
10
|
var active
|
8
11
|
var tabs = tabset.querySelector('.tabs')
|
9
12
|
if (tabs) {
|
@@ -14,7 +17,7 @@
|
|
14
17
|
var pane = tabset.querySelector('.tab-pane[aria-labelledby~="' + id + '"]')
|
15
18
|
if (!pane) return
|
16
19
|
if (!idx) first = { tab: tab, pane: pane }
|
17
|
-
if (!active &&
|
20
|
+
if (!active && fragment === id && (active = true)) {
|
18
21
|
tab.classList.add('is-active')
|
19
22
|
if (pane) pane.classList.add('is-active')
|
20
23
|
} else if (!idx) {
|
@@ -31,15 +34,36 @@
|
|
31
34
|
tabset.classList.remove('is-loading')
|
32
35
|
})
|
33
36
|
|
37
|
+
tabsets = undefined
|
38
|
+
window.addEventListener('hashchange', onHashChange)
|
39
|
+
|
34
40
|
function activateTab (e) {
|
35
41
|
var tab = this.tab
|
36
42
|
var pane = this.pane
|
37
43
|
find('.tabs li, .tab-pane', this.tabset).forEach(function (it) {
|
38
44
|
it === tab || it === pane ? it.classList.add('is-active') : it.classList.remove('is-active')
|
39
45
|
})
|
46
|
+
if (!e) return
|
47
|
+
var hashIdx = window.location.hash ? window.location.href.indexOf('#') : -1
|
48
|
+
if (~hashIdx) window.history.replaceState(null, '', window.location.href.slice(0, hashIdx))
|
40
49
|
e.preventDefault()
|
41
50
|
}
|
42
51
|
|
52
|
+
function decodeFragment (hash) {
|
53
|
+
return hash && (~hash.indexOf('%') ? decodeURIComponent(hash.slice(1)) : hash.slice(1))
|
54
|
+
}
|
55
|
+
|
56
|
+
function onHashChange () {
|
57
|
+
var id = decodeFragment(window.location.hash)
|
58
|
+
if (!id) return
|
59
|
+
var tab = document.getElementById(id)
|
60
|
+
if (!(tab && document.querySelector('.tabset .tabs [id="' + id + '"]'))) return
|
61
|
+
if (tab.tagName === 'A') tab = tab.parentNode
|
62
|
+
var tabset = tab.closest('.tabset')
|
63
|
+
var pane = tabset.querySelector('.tab-pane[aria-labelledby~="' + id + '"]')
|
64
|
+
activateTab.call({ tabset: tabset, tab: tab, pane: pane })
|
65
|
+
}
|
66
|
+
|
43
67
|
function find (selector, from) {
|
44
68
|
return Array.prototype.slice.call((from || document).querySelectorAll(selector))
|
45
69
|
}
|
@@ -11,36 +11,39 @@ module Asciidoctor
|
|
11
11
|
children = (parse_content block, reader).blocks
|
12
12
|
return block unless children.size == 1 && (source_tabs = children[0]).context == :dlist && source_tabs.items?
|
13
13
|
unless (doc = parent.document).attr? 'filetype', 'html'
|
14
|
-
|
15
|
-
(reftext = attrs['reftext']) && (source_tabs.set_attr 'reftext', reftext) unless source_tabs.
|
16
|
-
|
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
|
17
|
+
return
|
17
18
|
end
|
18
19
|
tabset_number = doc.counter 'tabset-number'
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
tabs_id = attrs['id'] || (generate_id %(tabset #{tabset_number}), doc)
|
21
|
+
parent << (create_html_fragment parent, %(<div id="#{tabs_id}" class="tabset is-loading">))
|
22
|
+
if (title = attrs['title'])
|
23
|
+
parent << (create_html_fragment parent, %(<div class="title">#{parent.apply_subs title}</div>))
|
24
|
+
end
|
22
25
|
(tabs = create_list parent, :ulist).add_role 'tabs'
|
23
26
|
panes = {}
|
24
27
|
set_id_on_tab = (doc.backend == 'html5') || (list_item_supports_id? doc)
|
25
28
|
source_tabs.items.each do |labels, content|
|
26
29
|
tab_ids = labels.map do |tab|
|
27
30
|
tabs << tab
|
28
|
-
tab_id = generate_id tab.text,
|
29
|
-
|
31
|
+
tab_id = generate_id tab.text, doc, tabs_id
|
32
|
+
tab_source_text = tab.instance_variable_get :@text
|
33
|
+
set_id_on_tab ? (tab.id = tab_id) : (tab.text = %([[#{tab_id}]]#{tab_source_text}))
|
34
|
+
(doc.register :refs, [tab_id, tab]).set_attr 'reftext', tab_source_text
|
30
35
|
tab_id
|
31
36
|
end
|
32
37
|
if content
|
33
|
-
|
38
|
+
tab_blocks = content.text? ? [(create_paragraph parent, (content.instance_variable_get :@text), nil)] : []
|
34
39
|
if content.blocks?
|
35
40
|
if (block0 = (blocks = content.blocks)[0]).context == :open && blocks.size == 1 && block0.blocks?
|
36
41
|
blocks = block0.blocks
|
37
42
|
end
|
38
|
-
blocks
|
39
|
-
elsif text
|
40
|
-
blocks = [text]
|
43
|
+
tab_blocks.push(*blocks)
|
41
44
|
end
|
42
45
|
end
|
43
|
-
panes[tab_ids] =
|
46
|
+
panes[tab_ids] = tab_blocks || []
|
44
47
|
end
|
45
48
|
parent << tabs
|
46
49
|
parent << (create_html_fragment parent, '<div class="content">')
|
@@ -50,7 +53,7 @@ module Asciidoctor
|
|
50
53
|
parent << (create_html_fragment parent, '</div>')
|
51
54
|
end
|
52
55
|
parent << (create_html_fragment parent, '</div>')
|
53
|
-
create_html_fragment parent, '</div>', 'id' =>
|
56
|
+
create_html_fragment parent, '</div>', 'id' => tabs_id
|
54
57
|
end
|
55
58
|
|
56
59
|
private
|
@@ -59,12 +62,14 @@ module Asciidoctor
|
|
59
62
|
create_block parent, :pass, html, attributes
|
60
63
|
end
|
61
64
|
|
62
|
-
def generate_id str,
|
63
|
-
|
64
|
-
|
65
|
+
def generate_id str, doc, base_id = nil
|
66
|
+
if base_id
|
67
|
+
restore_idprefix = (attrs = doc.attributes)['idprefix']
|
68
|
+
attrs['idprefix'] = %(#{base_id}#{attrs['idseparator'] || '_'})
|
69
|
+
end
|
65
70
|
::Asciidoctor::Section.generate_id str, doc
|
66
71
|
ensure
|
67
|
-
restore_idprefix ? (attrs['idprefix'] = restore_idprefix) : (attrs.delete 'idprefix')
|
72
|
+
restore_idprefix ? (attrs['idprefix'] = restore_idprefix) : (attrs.delete 'idprefix') if base_id
|
68
73
|
end
|
69
74
|
|
70
75
|
def list_item_supports_id? doc
|
@@ -4,12 +4,12 @@ module Asciidoctor
|
|
4
4
|
module Tabs
|
5
5
|
module Docinfo
|
6
6
|
if RUBY_ENGINE == 'opal'
|
7
|
-
DATA_DIR = ::File.absolute_path '../
|
7
|
+
DATA_DIR = ::File.absolute_path '../dist', %x(__dirname)
|
8
8
|
else
|
9
9
|
DATA_DIR = ::File.join (::File.absolute_path '../../..', __dir__), 'data'
|
10
10
|
end
|
11
11
|
|
12
|
-
class
|
12
|
+
class Style < ::Asciidoctor::Extensions::DocinfoProcessor
|
13
13
|
use_dsl
|
14
14
|
at_location :head
|
15
15
|
|
@@ -17,10 +17,14 @@ module Asciidoctor
|
|
17
17
|
|
18
18
|
def process doc
|
19
19
|
return unless (path = doc.attr 'tabs-stylesheet')
|
20
|
-
|
21
|
-
(doc.
|
22
|
-
(
|
23
|
-
|
20
|
+
if doc.attr? 'linkcss'
|
21
|
+
href = doc.normalize_web_path (path.empty? ? 'asciidoctor-tabs.css' : path), (doc.attr 'stylesdir')
|
22
|
+
%(<link rel="stylesheet" href="#{href}"#{(doc.attr? 'htmlsyntax', 'xml') ? '/' : ''}>) # rubocop:disable Style/TernaryParentheses
|
23
|
+
elsif (styles = path.empty? ?
|
24
|
+
(doc.read_asset DEFAULT_STYLESHEET_FILE) :
|
25
|
+
(doc.read_contents path, start: (doc.attr 'stylesdir'), warn_on_failure: true, label: 'tabs stylesheet'))
|
26
|
+
%(<style>\n#{styles.chomp}\n</style>)
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
@@ -31,8 +35,12 @@ module Asciidoctor
|
|
31
35
|
JAVASCRIPT_FILE = ::File.join DATA_DIR, 'js/tabs.js'
|
32
36
|
|
33
37
|
def process doc
|
34
|
-
|
35
|
-
|
38
|
+
if doc.attr? 'linkcss'
|
39
|
+
src = doc.normalize_web_path 'asciidoctor-tabs.js', (doc.attr 'scriptsdir')
|
40
|
+
%(<script src="#{src}"></script>)
|
41
|
+
elsif (script = doc.read_asset JAVASCRIPT_FILE)
|
42
|
+
%(<script>\n#{script.chomp}\n</script>)
|
43
|
+
end
|
36
44
|
end
|
37
45
|
end
|
38
46
|
end
|
@@ -21,7 +21,7 @@ module Asciidoctor
|
|
21
21
|
((doc.options[:attributes] || {}).transform_keys {|it| it.delete '@!' }.key? 'tabs-stylesheet')
|
22
22
|
doc.set_attr 'tabs-stylesheet'
|
23
23
|
end
|
24
|
-
docinfo_processor Docinfo::
|
24
|
+
docinfo_processor Docinfo::Style
|
25
25
|
docinfo_processor Docinfo::Behavior
|
26
26
|
nil
|
27
27
|
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.
|
4
|
+
version: 1.0.0.alpha.6
|
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-
|
11
|
+
date: 2022-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|