asciidoctor-tabs 1.0.0.alpha.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 370d0b3ca4f09c79c9e427316a4caaebea3f00d1759767967d0ef97a9195748d
4
+ data.tar.gz: 6e6da5d865f2c664aad52cd5ae7806623fc125f73139bd774c2594fa5cee171c
5
+ SHA512:
6
+ metadata.gz: 79f7f471c4ca7a4c240b8015fc4a160d802d73e898af80529cf5da51e9e5fbbb02e029d2786007bdd39aac2f10f686de6fd8fdec683dbea552bd9811f89505ba
7
+ data.tar.gz: b954ee1788718b5b63b4536555c7d5b51260108946d34200cc84a53cee2b64304a7d266effba6d0eaf485c862c820e26259fd005f3c018749c613994e46701ca
data/CHANGELOG.adoc ADDED
@@ -0,0 +1,13 @@
1
+ = Asciidoctor Tabs Changelog
2
+ :url-repo: https://github.com/asciidoctor/asciidoctor-tabs
3
+
4
+ This document provides a curated view of the changes to Asciidoctor Tabs per release.
5
+ For a detailed view of what has changed, refer to the {url-repo}/commits/main[commit history] on GitHub.
6
+
7
+ == 1.0.0-alpha.1 (2022-10-01) - @mojavelinux
8
+
9
+ _Initial release._
10
+
11
+ === Details
12
+
13
+ {url-repo}/releases/tag/v1.0.0-alpha.1[git tag]
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (C) 2022-present Dan Allen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.adoc ADDED
@@ -0,0 +1,87 @@
1
+ = Asciidoctor Tabs
2
+ Dan Allen <https://github.com/mojavelinux[@mojavelinux]>
3
+ v1.0.0-alpha.1, 2022-10-01
4
+ :idprefix:
5
+ :idseparator: -
6
+
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.
10
+
11
+ == Install
12
+
13
+ === Using gem command
14
+
15
+ $ gem install --prerelease asciidoctor-tabs
16
+
17
+ === Using Bundler
18
+
19
+ Create a [.path]_Gemfile_ in your project:
20
+
21
+ .Gemfile
22
+ [,ruby]
23
+ ----
24
+ source 'https://rubygems.org'
25
+
26
+ gem 'asciidoctor-tabs'
27
+
28
+ # or use the code directlly from GitHub
29
+ # gem 'asciidoctor-tabs', github: 'asciidoctor/asciidoctor-pdf'
30
+ ----
31
+
32
+ Then configure Bundler to install gems locally (optional):
33
+
34
+ $ bundle config --local path .bundle/gems
35
+
36
+ Then use Bundler to install the gem:
37
+
38
+ $ bundle
39
+
40
+ == Syntax
41
+
42
+ A tabset is defined using a dlist enclosed in an example block marked with the tabs style.
43
+ Each item in the dlist becomes a separate tab.
44
+ The term in the dlist item is used for the title of the tab.
45
+ The description in the dlist item is used for the contents of the tab.
46
+ The contents can be defined as primary text, attached blocks, or blocks enclosed in an attached open block.
47
+ If the blocks are enclosed in an attached open block, the open block enclosure itself will be discarded.
48
+
49
+ .document-with-tabs.adoc
50
+ [,asciidoc]
51
+ ----
52
+ [tabs]
53
+ ====
54
+ Tab A:: Contents of tab A.
55
+
56
+ Tab B::
57
+ +
58
+ Contents of tab B.
59
+
60
+ Tab C::
61
+ +
62
+ --
63
+ Contents of tab C.
64
+
65
+ Contains more than one block.
66
+ --
67
+ ====
68
+ ----
69
+
70
+ == Usage
71
+
72
+ $ asciidoctor -r asciidoctor-tabs document-with-tabs.adoc
73
+
74
+ == Authors
75
+
76
+ Asciidoctor Tabs was written by Dan Allen of OpenDevise Inc. and contributed to the Asciidoctor project.
77
+
78
+ == Copyright and License
79
+
80
+ Copyright (C) 2018-present Dan Allen (OpenDevise Inc.) and the individual contributors to this project.
81
+ Use of this software is granted under the terms of the MIT License.
82
+
83
+ See the link:LICENSE[LICENSE] for the full license text.
84
+
85
+ == Trademarks
86
+
87
+ AsciiDoc(R) is a trademark of the Eclipse Foundation, Inc.
@@ -0,0 +1,39 @@
1
+ begin
2
+ require_relative 'lib/asciidoctor/tabs/version'
3
+ rescue LoadError
4
+ require 'asciidoctor/tabs/version'
5
+ end
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'asciidoctor-tabs'
9
+ s.version = Asciidoctor::Tabs::VERSION
10
+ s.summary = 'An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.'
11
+ s.description = 'An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax. The tabset is constructed from a dlist enclosed in an example block marked with the tabs style.'
12
+ s.authors = ['Dan Allen']
13
+ s.email = 'dan@opendevise.com'
14
+ s.homepage = 'https://asciidoctor.org'
15
+ s.license = 'MIT'
16
+ # NOTE required ruby version is informational only; it's not enforced since it can't be overridden and can cause builds to break
17
+ #s.required_ruby_version = '>= 2.7.0'
18
+ s.metadata = {
19
+ 'bug_tracker_uri' => 'https://github.com/asciidoctor/asciidoctor-tabs/issues',
20
+ 'changelog_uri' => 'https://github.com/asciidoctor/asciidoctor-tabs/blob/main/CHANGELOG.adoc',
21
+ 'mailing_list_uri' => 'https://chat.asciidoctor.org',
22
+ 'source_code_uri' => 'https://github.com/asciidoctor/asciidoctor-tabs'
23
+ }
24
+
25
+ # NOTE the logic to build the list of files is designed to produce a usable package even when the git command is not available
26
+ begin
27
+ files = (result = `git ls-files -z`.split ?\0).empty? ? Dir['**/*'] : result
28
+ rescue
29
+ files = Dir['**/*']
30
+ end
31
+ s.files = files.grep %r/^(?:(?:data|lib)\/.+|LICENSE|(?:CHANGELOG|README)\.adoc|#{s.name}\.gemspec)$/
32
+ s.executables = (files.grep %r/^bin\//).map {|f| File.basename f }
33
+ s.require_paths = ['lib']
34
+
35
+ s.add_runtime_dependency 'asciidoctor', ['>= 2.0.0', '< 3.0.0']
36
+
37
+ s.add_development_dependency 'rake', '~> 13.0.0'
38
+ s.add_development_dependency 'rspec', '~> 3.11.0'
39
+ end
data/data/css/tabs.css ADDED
@@ -0,0 +1,67 @@
1
+ /*! Asciidoctor Tabs stylesheet | Copyright (c) 2018-present Dan Allen | MIT License */
2
+ .tabs ul {
3
+ display: flex;
4
+ flex-wrap: wrap;
5
+ list-style: none;
6
+ margin: 0 -0.25em 0 0;
7
+ padding: 0;
8
+ }
9
+
10
+ .tabs li {
11
+ align-items: center;
12
+ border: 1px solid black;
13
+ border-bottom: 0;
14
+ cursor: pointer;
15
+ display: flex;
16
+ font-weight: bold;
17
+ height: 2em;
18
+ line-height: 1;
19
+ margin-right: 0.25em;
20
+ padding: 0 1em;
21
+ position: relative;
22
+ }
23
+
24
+ .tabs.ulist li, .tabs.ulist p {
25
+ margin-bottom: 0;
26
+ }
27
+
28
+ .tabs li + li {
29
+ margin-top: 0;
30
+ }
31
+
32
+ .tabset.is-loading .tabs li:not(:first-child),
33
+ .tabset:not(.is-loading) .tabs li:not(.is-active) {
34
+ background-color: black;
35
+ color: white;
36
+ }
37
+
38
+ .tabset.is-loading .tabs li:first-child::after,
39
+ .tabs li.is-active::after {
40
+ background-color: white;
41
+ content: "";
42
+ display: block;
43
+ height: 3px; /* Chrome doesn't always paint the line accurately, so add a little extra */
44
+ position: absolute;
45
+ bottom: -1.5px;
46
+ left: 0;
47
+ right: 0;
48
+ }
49
+
50
+ .tabset > .content {
51
+ border: 1px solid gray;
52
+ padding: 1.25em;
53
+ margin-bottom: 1.25em;
54
+ }
55
+
56
+ .tabset.is-loading .tab-pane:not(:first-child),
57
+ .tabset:not(.is-loading) .tab-pane:not(.is-active) {
58
+ display: none;
59
+ }
60
+
61
+ .tab-pane > :first-child {
62
+ margin-top: 0;
63
+ }
64
+
65
+ .tab-pane > :last-child > :last-child {
66
+ margin-bottom: 0;
67
+ }
data/data/js/tabs.js ADDED
@@ -0,0 +1,51 @@
1
+ /*! Asciidoctor Tabs behavior | Copyright (c) 2018-present Dan Allen | MIT License */
2
+ ;(function () {
3
+ 'use strict'
4
+
5
+ var hash = window.location.hash
6
+ find('.tabset').forEach(function (tabset) {
7
+ var active
8
+ var tabs = tabset.querySelector('.tabs')
9
+ if (tabs) {
10
+ var first
11
+ find('li', tabs).forEach(function (tab, idx) {
12
+ var id = (tab.querySelector('a[id]') || tab).id
13
+ if (!id) return
14
+ var pane = getPane(id, tabset)
15
+ if (!idx) first = { tab: tab, pane: pane }
16
+ if (!active && hash === '#' + id && (active = true)) {
17
+ tab.classList.add('is-active')
18
+ if (pane) pane.classList.add('is-active')
19
+ } else if (!idx) {
20
+ tab.classList.remove('is-active')
21
+ if (pane) pane.classList.remove('is-active')
22
+ }
23
+ tab.addEventListener('click', activateTab.bind({ tabset: tabset, tab: tab, pane: pane }))
24
+ })
25
+ if (!active && first) {
26
+ first.tab.classList.add('is-active')
27
+ if (first.pane) first.pane.classList.add('is-active')
28
+ }
29
+ }
30
+ tabset.classList.remove('is-loading')
31
+ })
32
+
33
+ function activateTab (e) {
34
+ var tab = this.tab
35
+ var pane = this.pane
36
+ find('.tabs li, .tab-pane', this.tabset).forEach(function (it) {
37
+ it === tab || it === pane ? it.classList.add('is-active') : it.classList.remove('is-active')
38
+ })
39
+ e.preventDefault()
40
+ }
41
+
42
+ function find (selector, from) {
43
+ return Array.prototype.slice.call((from || document).querySelectorAll(selector))
44
+ }
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
+ })()
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module Tabs
5
+ class Block < ::Asciidoctor::Extensions::BlockProcessor
6
+ use_dsl
7
+ on_context :example
8
+
9
+ ID_SEPARATOR_CHAR = '-'
10
+ INVALID_ID_CHARS_RX = /[^a-zA-Z0-9_]/
11
+
12
+ def process parent, reader, attrs
13
+ block = create_block parent, :example, nil, attrs, content_model: :compound
14
+ children = (parse_content block, reader).blocks
15
+ 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'
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
34
+ end
35
+ if (block0 = blocks[0]).context == :open && blocks.size == 1 && block0.blocks?
36
+ blocks = block0.blocks
37
+ end
38
+ (panes[tab_id] = blocks).each {|it| it.parent = parent }
39
+ 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>')
46
+ 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
+ end
52
+
53
+ private
54
+
55
+ def create_html_fragment parent, html
56
+ create_block parent, 'pass', html, nil
57
+ end
58
+
59
+ def generate_id str, base_id
60
+ %(#{base_id}_#{str.downcase.gsub INVALID_ID_CHARS_RX, ID_SEPARATOR_CHAR})
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module Tabs
5
+ module Docinfo
6
+ if RUBY_ENGINE == 'opal'
7
+ DATA_DIR = ::File.absolute_path '../data', %x(__dirname)
8
+ FILE_READ_MODE = 'r'
9
+ else
10
+ DATA_DIR = ::File.join (::File.absolute_path '../../..', __dir__), 'data'
11
+ FILE_READ_MODE = 'rb:utf-8:utf-8'
12
+ end
13
+
14
+ class Styles < ::Asciidoctor::Extensions::DocinfoProcessor
15
+ use_dsl
16
+ at_location :head
17
+
18
+ STYLESHEET_FILE = ::File.join DATA_DIR, 'css/tabs.css'
19
+
20
+ def process _doc
21
+ %(<style>\n#{(::File.read STYLESHEET_FILE, mode: FILE_READ_MODE).chomp}\n</style>)
22
+ end
23
+ end
24
+
25
+ class Behavior < ::Asciidoctor::Extensions::DocinfoProcessor
26
+ use_dsl
27
+ at_location :footer
28
+
29
+ JAVASCRIPT_FILE = ::File.join DATA_DIR, 'js/tabs.js'
30
+
31
+ def process _doc
32
+ %(<script>\n#{(::File.read JAVASCRIPT_FILE, mode: FILE_READ_MODE).chomp}\n</script>)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'block'
4
+ require_relative 'docinfo'
5
+
6
+ module Asciidoctor
7
+ module Tabs
8
+ module Extensions
9
+ module_function
10
+
11
+ def group
12
+ proc do
13
+ block Block, :tabs
14
+ docinfo_processor Docinfo::Styles
15
+ docinfo_processor Docinfo::Behavior
16
+ end
17
+ end
18
+
19
+ def key
20
+ :tabs
21
+ end
22
+
23
+ def register
24
+ ::Asciidoctor::Extensions.register key, &group
25
+ end
26
+
27
+ def unregister
28
+ ::Asciidoctor::Extensions.groups.delete key
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module Tabs
5
+ VERSION = '1.0.0.alpha.1'
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tabs/extensions'
4
+
5
+ Asciidoctor::Tabs::Extensions.register
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'asciidoctor/tabs'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asciidoctor-tabs
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.alpha.1
5
+ platform: ruby
6
+ authors:
7
+ - Dan Allen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-10-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: asciidoctor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 3.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: rake
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 13.0.0
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 13.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 3.11.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 3.11.0
61
+ description: An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.
62
+ The tabset is constructed from a dlist enclosed in an example block marked with
63
+ the tabs style.
64
+ email: dan@opendevise.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - CHANGELOG.adoc
70
+ - LICENSE
71
+ - README.adoc
72
+ - asciidoctor-tabs.gemspec
73
+ - data/css/tabs.css
74
+ - data/js/tabs.js
75
+ - lib/asciidoctor-tabs.rb
76
+ - lib/asciidoctor/tabs.rb
77
+ - lib/asciidoctor/tabs/block.rb
78
+ - lib/asciidoctor/tabs/docinfo.rb
79
+ - lib/asciidoctor/tabs/extensions.rb
80
+ - lib/asciidoctor/tabs/version.rb
81
+ homepage: https://asciidoctor.org
82
+ licenses:
83
+ - MIT
84
+ metadata:
85
+ bug_tracker_uri: https://github.com/asciidoctor/asciidoctor-tabs/issues
86
+ changelog_uri: https://github.com/asciidoctor/asciidoctor-tabs/blob/main/CHANGELOG.adoc
87
+ mailing_list_uri: https://chat.asciidoctor.org
88
+ source_code_uri: https://github.com/asciidoctor/asciidoctor-tabs
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.3.1
103
+ requirements: []
104
+ rubygems_version: 3.3.7
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: An Asciidoctor extension that adds a tabs block to the AsciiDoc syntax.
108
+ test_files: []