asciidoctor-tabs 1.0.0.alpha.1 → 1.0.0.alpha.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: 370d0b3ca4f09c79c9e427316a4caaebea3f00d1759767967d0ef97a9195748d
4
- data.tar.gz: 6e6da5d865f2c664aad52cd5ae7806623fc125f73139bd774c2594fa5cee171c
3
+ metadata.gz: a6224fd054576b98130cb17fff445018029d8c3271cc4747ff00c112e513bb42
4
+ data.tar.gz: 1f1f618257e63009b54fc7d3fd11fd41bc490fc96c089fae0de75f6b74bb4239
5
5
  SHA512:
6
- metadata.gz: 79f7f471c4ca7a4c240b8015fc4a160d802d73e898af80529cf5da51e9e5fbbb02e029d2786007bdd39aac2f10f686de6fd8fdec683dbea552bd9811f89505ba
7
- data.tar.gz: b954ee1788718b5b63b4536555c7d5b51260108946d34200cc84a53cee2b64304a7d266effba6d0eaf485c862c820e26259fd005f3c018749c613994e46701ca
6
+ metadata.gz: 96ac2018cfaa5c8d0ee23c87c306cc64d0f67b76100d623816166ea1a09f9a9c1939503111717616dc2f062efe3d13bffe3469d88570011de18ff9a9c7ea6b82
7
+ data.tar.gz: 97b9ab0a22a0ffa2eadec746d963c91b5a9c60d274bb088e82ef3224f55116ec5353706601765c1d858c45a364b2e8d5ff3a9d61a51e8034d9b78a80f64b4cb8
data/CHANGELOG.adoc CHANGED
@@ -4,6 +4,52 @@
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.3 (2022-10-05) - @mojavelinux
8
+
9
+ === Added
10
+
11
+ * Provide fallback behavior for non-HTML backends (filetype is not html) (#4)
12
+ * Support multiple tab labels (terms) for the same content (description) (#8)
13
+ * Allow alternate stylesheet for tabs to be specified using `tabs-stylesheet` attribute (#6)
14
+
15
+ === Changed
16
+
17
+ * Assign ID directly to tab (list item) node (instead of using inline anchor) if backend supports it (#11)
18
+
19
+ === Fixed
20
+
21
+ * Create empty pane instead of crashing if dlist item has term only / no description
22
+
23
+ === Details
24
+
25
+ {url-repo}/releases/tag/v1.0.0-alpha.3[git tag] | {url-repo}/compare/v1.0.0-alpha.2\...v1.0.0-alpha.3[full diff]
26
+
27
+ == 1.0.0-alpha.2 (2022-10-03) - @mojavelinux
28
+
29
+ === Added
30
+
31
+ * Transpile `Asciidoctor::Tabs::Extensions` class for npm package
32
+
33
+ === Changed
34
+
35
+ * Rename `idx-tabset` counter to `tabset-number` to be consistent with built-in counter names
36
+ * Don't register docinfo extensions if converter is producing embedded output
37
+ * Update `register` and `unregister` on `Asciidoctor::Tabs::Extensions` to accept a registry argument
38
+ * Delegate registration of extension in npm package to `Asciidoctor::Tabs::Extensions.register` method
39
+ * Allow `Extensions` class to be required from `@asciidoctor/tabs/extensions` in Node.js; attach `Block` and `Docinfo` classes
40
+
41
+ === Fixed
42
+
43
+ * Preserve text of dlist item for tab if item has both text and blocks (#13)
44
+ * Honor explicit ID on tabs block and use it as ID prefix for tabs
45
+ * Register reference for tabset in document catalog
46
+ * Autogenerate IDs for tabsets and tabs in a manner consistent with section ID generation (#2)
47
+ * Fix context value on pass blocks created by extension
48
+
49
+ === Details
50
+
51
+ {url-repo}/releases/tag/v1.0.0-alpha.2[git tag] | {url-repo}/compare/v1.0.0-alpha.1\...v1.0.0-alpha.2[full diff]
52
+
7
53
  == 1.0.0-alpha.1 (2022-10-01) - @mojavelinux
8
54
 
9
55
  _Initial release._
data/README.adoc CHANGED
@@ -1,12 +1,18 @@
1
1
  = Asciidoctor Tabs
2
2
  Dan Allen <https://github.com/mojavelinux[@mojavelinux]>
3
- v1.0.0-alpha.1, 2022-10-01
3
+ v1.0.0-alpha.3, 2022-10-05
4
4
  :idprefix:
5
5
  :idseparator: -
6
+ ifndef::env-github[:icons: font]
7
+ ifdef::env-github[]
8
+ :note-caption: :paperclip:
9
+ endif::[]
6
10
 
7
- An Asciidoctor extension that adds tabs to the AsciiDoc syntax.
8
- The tabset is constructed from a dlist enclosed in an example block marked with the tabs style.
9
- This extension is only designed to be used with the `html` backend.
11
+ An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.
12
+ Each set of tabs (a "tabset") is constructed from a dlist enclosed in an example block marked with the tabs style.
13
+
14
+ NOTE: This extension is intended to be used with HTML backends (e.g., `html`).
15
+ For other backends (i.e., filetype is not html), the example block enclosure will be taken away and the dlist will be converted normally.
10
16
 
11
17
  == Install
12
18
 
@@ -41,7 +47,7 @@ Then use Bundler to install the gem:
41
47
 
42
48
  A tabset is defined using a dlist enclosed in an example block marked with the tabs style.
43
49
  Each item in the dlist becomes a separate tab.
44
- The term in the dlist item is used for the title of the tab.
50
+ The term in the dlist item is used as the tab's label.
45
51
  The description in the dlist item is used for the contents of the tab.
46
52
  The contents can be defined as primary text, attached blocks, or blocks enclosed in an attached open block.
47
53
  If the blocks are enclosed in an attached open block, the open block enclosure itself will be discarded.
@@ -69,8 +75,51 @@ Contains more than one block.
69
75
 
70
76
  == Usage
71
77
 
78
+ === CLI
79
+
72
80
  $ asciidoctor -r asciidoctor-tabs document-with-tabs.adoc
73
81
 
82
+ You can specify an alternate stylesheet for tabs using the `tabs-stylesheet` document attribute.
83
+ The value of this attribute is handled in the same way as the built-in `stylesheet` document attribute.
84
+ A relative path is resolved starting from the value of the `stylesdir` document attribute, which defaults to the directory of the document.
85
+
86
+ $ asciidoctor -r asciidoctor-tabs -a tabs-stylesheet=my-tabs.css document-with-tabs.adoc
87
+
88
+ === API
89
+
90
+ There are two ways to use the extension with the Asciidoctor API.
91
+ In either case, you must require the Asciidoctor gem (`asciidoctor`) before requiring this one.
92
+
93
+ You can require `asciidoctor/tabs` to register the extension as a global extension, just like with the CLI.
94
+
95
+ [,js]
96
+ ----
97
+ require 'asciidoctor'
98
+ require 'asciidoctor/tabs'
99
+
100
+ Asciidoctor.convert_file 'document-with-tabs.adoc', safe: :safe
101
+ ----
102
+
103
+ Or you can pass a registry instance to the `Extensions.register` method to register the extension with a scoped registry.
104
+
105
+ [,js]
106
+ ----
107
+ require 'asciidoctor'
108
+ require 'asciidoctor/tabs/extensions'
109
+
110
+ registry = Asciidoctor::Extensions.create
111
+ Asciidoctor::Tabs::Extensions.register registry
112
+
113
+ Asciidoctor.convert_file 'document-with-tabs.adoc', extension_registry: registry, safe: :safe
114
+ ----
115
+
116
+ If you're not using other scoped extensions, you can pass in the extensions group without creating a registry instance:
117
+
118
+ [,js]
119
+ ----
120
+ Asciidoctor.convert_file 'document-with-tabs.adoc', extensions: Asciidoctor::Tabs::Extensions.group, safe: :safe
121
+ ----
122
+
74
123
  == Authors
75
124
 
76
125
  Asciidoctor Tabs was written by Dan Allen of OpenDevise Inc. and contributed to the Asciidoctor project.
data/data/css/tabs.css CHANGED
@@ -1,5 +1,5 @@
1
1
  /*! Asciidoctor Tabs stylesheet | Copyright (c) 2018-present Dan Allen | MIT License */
2
- .tabs ul {
2
+ .tabs > ul {
3
3
  display: flex;
4
4
  flex-wrap: wrap;
5
5
  list-style: none;
@@ -7,7 +7,7 @@
7
7
  padding: 0;
8
8
  }
9
9
 
10
- .tabs li {
10
+ .tabs > ul li {
11
11
  align-items: center;
12
12
  border: 1px solid black;
13
13
  border-bottom: 0;
@@ -21,11 +21,11 @@
21
21
  position: relative;
22
22
  }
23
23
 
24
- .tabs.ulist li, .tabs.ulist p {
24
+ .tabs > ul li, .tabs > ul p {
25
25
  margin-bottom: 0;
26
26
  }
27
27
 
28
- .tabs li + li {
28
+ .tabs > ul li + li {
29
29
  margin-top: 0;
30
30
  }
31
31
 
data/data/js/tabs.js CHANGED
@@ -11,7 +11,8 @@
11
11
  find('li', tabs).forEach(function (tab, idx) {
12
12
  var id = (tab.querySelector('a[id]') || tab).id
13
13
  if (!id) return
14
- var pane = getPane(id, tabset)
14
+ var pane = tabset.querySelector('.tab-pane[aria-labelledby~="' + id + '"]')
15
+ if (!pane) return
15
16
  if (!idx) first = { tab: tab, pane: pane }
16
17
  if (!active && hash === '#' + id && (active = true)) {
17
18
  tab.classList.add('is-active')
@@ -42,10 +43,4 @@
42
43
  function find (selector, from) {
43
44
  return Array.prototype.slice.call((from || document).querySelectorAll(selector))
44
45
  }
45
-
46
- function getPane (id, tabset) {
47
- return find('.tab-pane', tabset).find(function (it) {
48
- return it.getAttribute('aria-labelledby') === id
49
- })
50
- }
51
46
  })()
@@ -6,58 +6,73 @@ module Asciidoctor
6
6
  use_dsl
7
7
  on_context :example
8
8
 
9
- ID_SEPARATOR_CHAR = '-'
10
- INVALID_ID_CHARS_RX = /[^a-zA-Z0-9_]/
11
-
12
9
  def process parent, reader, attrs
13
- block = create_block parent, :example, nil, attrs, content_model: :compound
10
+ block = create_block parent, attrs['cloaked-context'], nil, attrs, content_model: :compound
14
11
  children = (parse_content block, reader).blocks
15
12
  return block unless children.size == 1 && (source_tabs = children[0]).context == :dlist && source_tabs.items?
16
- nodes = []
17
- tabset_idx = parent.document.counter 'idx-tabset'
18
- id = block.id || %(tabset#{tabset_idx})
19
- nodes << (create_html_fragment parent, %(<div id="#{id}" class="tabset is-loading">))
20
- tabs = create_list parent, :ulist
21
- tabs.add_role 'tabs'
13
+ unless (doc = parent.document).attr? 'filetype', 'html'
14
+ source_tabs.id ||= attrs['id']
15
+ (reftext = attrs['reftext']) && (source_tabs.set_attr 'reftext', reftext) unless source_tabs.attr? 'reftext'
16
+ return source_tabs
17
+ end
18
+ tabset_number = doc.counter 'tabset-number'
19
+ id = attrs['id'] || %(#{doc.attributes['idprefix'] || '_'}tabset#{tabset_number})
20
+ parent << (create_html_fragment parent, %(<div id="#{id}" class="tabset is-loading">))
21
+ (tabs = create_list parent, :ulist).add_role 'tabs'
22
22
  panes = {}
23
- source_tabs.items.each do |(title), details|
24
- tab = create_list_item tabs
25
- tabs << tab
26
- tab_id = generate_id title.text, id
27
- tab.text = %([[#{tab_id}]]#{title.instance_variable_get :@text})
28
- if details.blocks?
29
- blocks = details.blocks
30
- elsif details.text?
31
- blocks = [(create_paragraph parent, (details.instance_variable_get :@text), {})]
32
- else
33
- next
23
+ set_id_on_tab = (doc.backend == 'html5') || (list_item_supports_id? doc)
24
+ source_tabs.items.each do |labels, content|
25
+ tab_ids = labels.map do |tab|
26
+ tabs << tab
27
+ tab_id = generate_id tab.text, id, doc
28
+ set_id_on_tab ? (tab.id = tab_id) : (tab.text = %([[#{tab_id}]]#{tab.instance_variable_get :@text}))
29
+ tab_id
34
30
  end
35
- if (block0 = blocks[0]).context == :open && blocks.size == 1 && block0.blocks?
36
- blocks = block0.blocks
31
+ if content
32
+ text = create_paragraph parent, (content.instance_variable_get :@text), nil if content.text?
33
+ if content.blocks?
34
+ if (block0 = (blocks = content.blocks)[0]).context == :open && blocks.size == 1 && block0.blocks?
35
+ blocks = block0.blocks
36
+ end
37
+ blocks.unshift text if text
38
+ elsif text
39
+ blocks = [text]
40
+ end
37
41
  end
38
- (panes[tab_id] = blocks).each {|it| it.parent = parent }
42
+ panes[tab_ids] = blocks || []
39
43
  end
40
- nodes << tabs
41
- nodes << (create_html_fragment parent, '<div class="content">')
42
- panes.each do |tab_id, blocks|
43
- nodes << (create_html_fragment parent, %(<div class="tab-pane" aria-labelledby="#{tab_id}">))
44
- nodes.push(*blocks)
45
- nodes << (create_html_fragment parent, '</div>')
44
+ parent << tabs
45
+ parent << (create_html_fragment parent, '<div class="content">')
46
+ panes.each do |tab_ids, blocks|
47
+ parent << (create_html_fragment parent, %(<div class="tab-pane" aria-labelledby="#{tab_ids.join ' '}">))
48
+ blocks.each {|it| parent << it }
49
+ parent << (create_html_fragment parent, '</div>')
46
50
  end
47
- nodes << (create_html_fragment parent, '</div>')
48
- nodes << (create_html_fragment parent, '</div>')
49
- nodes.each {|it| parent.blocks << it }
50
- nil
51
+ parent << (create_html_fragment parent, '</div>')
52
+ create_html_fragment parent, '</div>', 'id' => id
51
53
  end
52
54
 
53
55
  private
54
56
 
55
- def create_html_fragment parent, html
56
- create_block parent, 'pass', html, nil
57
+ def create_html_fragment parent, html, attributes = nil
58
+ create_block parent, :pass, html, attributes
57
59
  end
58
60
 
59
- def generate_id str, base_id
60
- %(#{base_id}_#{str.downcase.gsub INVALID_ID_CHARS_RX, ID_SEPARATOR_CHAR})
61
+ def generate_id str, base_id, doc
62
+ restore_idprefix = (attrs = doc.attributes)['idprefix']
63
+ attrs['idprefix'] = %(#{base_id}#{attrs['idseparator'] || '_'})
64
+ ::Asciidoctor::Section.generate_id str, doc
65
+ ensure
66
+ restore_idprefix ? (attrs['idprefix'] = restore_idprefix) : (attrs.delete 'idprefix')
67
+ end
68
+
69
+ def list_item_supports_id? doc
70
+ if (converter = doc.converter).instance_variable_defined? :@list_item_supports_id
71
+ converter.instance_variable_get :@list_item_supports_id
72
+ else
73
+ output = (create_list doc, :ulist).tap {|ul| ul << (create_list_item ul).tap {|li| li.id = 'name' } }.convert
74
+ converter.instance_variable_set :@list_item_supports_id, (output.include? ' id="name"')
75
+ end
61
76
  end
62
77
  end
63
78
  end
@@ -15,10 +15,15 @@ module Asciidoctor
15
15
  use_dsl
16
16
  at_location :head
17
17
 
18
- STYLESHEET_FILE = ::File.join DATA_DIR, 'css/tabs.css'
18
+ DEFAULT_STYLESHEET_FILE = ::File.join DATA_DIR, 'css/tabs.css'
19
19
 
20
- def process _doc
21
- %(<style>\n#{(::File.read STYLESHEET_FILE, mode: FILE_READ_MODE).chomp}\n</style>)
20
+ def process doc
21
+ return unless (path = doc.attr 'tabs-stylesheet')
22
+ styles = path.empty? ?
23
+ (::File.read DEFAULT_STYLESHEET_FILE, mode: FILE_READ_MODE) :
24
+ (doc.read_contents path, start: (doc.attr 'stylesdir'), warn_on_failure: true, label: 'tabs stylesheet')
25
+ return unless styles
26
+ %(<style>\n#{styles.chomp}\n</style>)
22
27
  end
23
28
  end
24
29
 
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'block'
4
- require_relative 'docinfo'
3
+ unless RUBY_ENGINE == 'opal'
4
+ require_relative 'block'
5
+ require_relative 'docinfo'
6
+ end
5
7
 
6
8
  module Asciidoctor
7
9
  module Tabs
@@ -11,8 +13,14 @@ module Asciidoctor
11
13
  def group
12
14
  proc do
13
15
  block Block, :tabs
16
+ next if (doc = @document).embedded? || !(doc.attr? 'filetype', 'html')
17
+ unless (doc.attribute_locked? 'tabs-stylesheet') ||
18
+ ((doc.options[:attributes] || {}).transform_keys {|it| it.delete '@!' }.key? 'tabs-stylesheet')
19
+ doc.set_attr 'tabs-stylesheet'
20
+ end
14
21
  docinfo_processor Docinfo::Styles
15
22
  docinfo_processor Docinfo::Behavior
23
+ nil
16
24
  end
17
25
  end
18
26
 
@@ -20,12 +28,13 @@ module Asciidoctor
20
28
  :tabs
21
29
  end
22
30
 
23
- def register
24
- ::Asciidoctor::Extensions.register key, &group
31
+ def register registry = nil
32
+ (registry || ::Asciidoctor::Extensions).groups[key] ||= group
25
33
  end
26
34
 
27
- def unregister
28
- ::Asciidoctor::Extensions.groups.delete key
35
+ def unregister registry = nil
36
+ (registry || ::Asciidoctor::Extensions).groups.delete key
37
+ nil
29
38
  end
30
39
  end
31
40
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module Tabs
5
- VERSION = '1.0.0.alpha.1'
5
+ VERSION = '1.0.0.alpha.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.alpha.1
4
+ version: 1.0.0.alpha.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: 2022-10-01 00:00:00.000000000 Z
11
+ date: 2022-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor