asciidoctor-tabs 1.0.0.alpha.1

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