asciidoctor-reducer 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: 6b897d6327d17f704a62f21f7649a2ae1a4f2643bf7f8f41445c126aafbf77e2
4
+ data.tar.gz: d3c11b63175f9f235f459a2c8822d0ee2d08e2762f2cab5273f30c238797db49
5
+ SHA512:
6
+ metadata.gz: 421524a636890420cebe721455f2ba348cb514b8b576d125c1baa2d9e474297a2763b3c325d7c8948e7bd12d28276f8e27b5171cfecc0d92be62b1f1e8094f11
7
+ data.tar.gz: 7c148e99347aaf86474d376b80e8beb7a35cb96fe211ace49c5ba6a8e8a8bfb40716225c995107407ff3c13c9f3e850f8fc3b83ce9e4e172102b719a2ef48dca
data/CHANGELOG.adoc ADDED
@@ -0,0 +1,13 @@
1
+ = Asciidoctor Reducer Changelog
2
+ :url-repo: https://github.com/asciidoctor/asciidoctor-reducer
3
+
4
+ This document provides a high-level view of the changes to the Asciidoctor Reducer by 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-01-12) - @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) 2021 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,113 @@
1
+ = Asciidoctor Reducer
2
+ Dan Allen <https://github.com/mojavelinux[@mojavelinux]>
3
+ v1.0.0.alpha.1, 2022-01-12
4
+ :idprefix:
5
+ :idseparator: -
6
+ ifndef::env-github[:icons: font]
7
+ ifdef::env-github[]
8
+ :caution-caption: :fire:
9
+ :important-caption: :exclamation:
10
+ :note-caption: :paperclip:
11
+ :tip-caption: :bulb:
12
+ :warning-caption: :warning:
13
+ endif::[]
14
+ :url-rvm: https://rvm.io
15
+
16
+ Asciidoctor Reducer is a tool that reduces an AsciiDoc document with includes to a single document by expanding the includes reachable from the specified parent document.
17
+ If the document does not contain any includes, the tool returns the original source.
18
+
19
+ == Prerequisites
20
+
21
+ To install and run Asciidoctor Reducer, you need Ruby 2.5 or better installed and the Asciidoctor gem.
22
+ The instructions for installing the gems is covered in the next section.
23
+
24
+ To check whether you have Ruby installed, and which version, run the following command:
25
+
26
+ $ ruby -v
27
+
28
+ If Ruby is not installed, you can install it using {url-rvm}[RVM] (or, if you prefer, the package manager for your system).
29
+ We generally recommend using RVM because it allows you to install gems without requiring elevated privileges or messing with system libraries.
30
+
31
+ == Installation
32
+
33
+ Asciidoctor Reducer is published to RubyGems.org as the gem named *asciidoctor-reducer*.
34
+
35
+ You can install the latest version of the gem using the following command:
36
+
37
+ $ gem install asciidoctor-reducer --pre
38
+
39
+ Installing this gem makes the `asciidoctor-reducer` command available on your $PATH.
40
+ You can also require the gem to use it as an Asciidoctor extension.
41
+
42
+ == Usage
43
+
44
+ === As command
45
+
46
+ You can run this tool using the provided command (i.e., CLI), named `asciidoctor-reducer`.
47
+ To learn how to use the command, and to verify it's available, run the command with the `-h` option:
48
+
49
+ $ asciidoctor-reducer -h
50
+
51
+ On the first line of the help text, you'll see a synopsis of the command:
52
+
53
+ ....
54
+ asciidoctor-reducer [OPTION]... FILE
55
+ ....
56
+
57
+ The argument `FILE` is the AsciiDoc file you want to reduce.
58
+ To use the command, pass the AsciiDoc file as the sole argument:
59
+
60
+ $ asciidoctor-reducer input.adoc
61
+
62
+ By default, the command will output the reduced AsciiDoc document to the terminal (via stdout).
63
+ To write the output to a file, specify an output file using the `-o` option.
64
+
65
+ $ asciidoctor-reducer -o output.adoc input.adoc
66
+
67
+ The command can also read the input document from stdin instead of a file.
68
+ To use the command in this way, pass `-` as the first argument:
69
+
70
+ $ cat input.adoc | asciidoctor-reducer -
71
+
72
+ To write the output to a file, also specify the `-o` option:
73
+
74
+ $ cat input.adoc | asciidoctor-reducer -o output.adoc -
75
+
76
+ Note that top-level include files in the input AsciiDoc document are resolved relative to current working directory.
77
+
78
+ === As extension
79
+
80
+ You can use this tool as an Asciidoctor extension when using the Asciidoctor API.
81
+ To do so, require it before calling the `Asciidoctor.load` method.
82
+
83
+ [,ruby]
84
+ ----
85
+ require 'asciidoctor/reducer'
86
+ ----
87
+
88
+ Next, load a parent document that contains includes.
89
+
90
+ [,ruby]
91
+ ----
92
+ doc = Asciidoctor.load_file 'sample.adoc', safe: :safe
93
+ ----
94
+
95
+ Finally, you can retrieve the reduced source from the returned document.
96
+
97
+ [,ruby]
98
+ ----
99
+ puts doc.source
100
+ ----
101
+
102
+ You can write this source to a file to save the reduced document.
103
+
104
+ == Copyright and License
105
+
106
+ Copyright (C) 2021-present Dan Allen.
107
+ Use of this software is granted under the terms of the MIT License.
108
+
109
+ See the link:LICENSE[LICENSE] for the full license text.
110
+
111
+ == Trademarks
112
+
113
+ AsciiDoc(R) and AsciiDoc Language(TM) are trademarks of the Eclipse Foundation, Inc.
@@ -0,0 +1,41 @@
1
+ begin
2
+ require_relative 'lib/asciidoctor/reducer/version'
3
+ rescue LoadError
4
+ require 'asciidoctor/reducer/version'
5
+ end
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = 'asciidoctor-reducer'
9
+ s.version = Asciidoctor::Reducer::VERSION
10
+ # Reduces a set of AsciiDoc documents into a single document by expanding all includes reachable from the parent document.
11
+
12
+ s.summary = 'Reduces an AsciiDoc document with includes to a single AsciiDoc document.'
13
+ s.description = 'A tool that reduces an AsciiDoc document with includes to a single AsciiDoc document by expanding the includes reachable from the specified parent document.'
14
+ s.authors = ['Dan Allen']
15
+ s.email = 'dan.j.allen@gmail.com'
16
+ s.homepage = 'https://asciidoctor.org'
17
+ s.license = 'MIT'
18
+ # NOTE required ruby version is informational only; it's not enforced since it can't be overridden and can cause builds to break
19
+ #s.required_ruby_version = '>= 2.5.0'
20
+ s.metadata = {
21
+ 'bug_tracker_uri' => 'https://github.com/asciidoctor/asciidoctor-reducer/issues',
22
+ 'changelog_uri' => 'https://github.com/asciidoctor/asciidoctor-reducer/blob/main/CHANGELOG.adoc',
23
+ 'mailing_list_uri' => 'https://asciidoctor.zulipchat.com',
24
+ 'source_code_uri' => 'https://github.com/asciidoctor/asciidoctor-reducer'
25
+ }
26
+
27
+ # NOTE the logic to build the list of files is designed to produce a usable package even when the git command is not available
28
+ begin
29
+ files = (result = `git ls-files -z`.split ?\0).empty? ? Dir['**/*'] : result
30
+ rescue
31
+ files = Dir['**/*']
32
+ end
33
+ s.files = files.grep %r/^(?:lib\/.+|LICENSE|(?:CHANGELOG|README)\.adoc|#{s.name}\.gemspec)$/
34
+ s.executables = (files.grep %r/^bin\//).map {|f| File.basename f }
35
+ s.require_paths = ['lib']
36
+
37
+ s.add_runtime_dependency 'asciidoctor', '~> 2.0'
38
+
39
+ s.add_development_dependency 'rake', '~> 13.0.0'
40
+ s.add_development_dependency 'rspec', '~> 3.10.0'
41
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ asciidoctor_reducer = File.absolute_path '../lib/asciidoctor/reducer', __dir__
5
+ if File.exist? asciidoctor_reducer
6
+ require asciidoctor_reducer
7
+ else
8
+ require 'asciidoctor/reducer'
9
+ end
10
+
11
+ require 'asciidoctor/reducer/cli'
12
+
13
+ exit Asciidoctor::Reducer::Cli.run
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ autoload :OptionParser, 'optparse'
4
+ autoload :Pathname, 'pathname'
5
+
6
+ module Asciidoctor::Reducer
7
+ autoload :VERSION, (::File.join __dir__, 'version.rb')
8
+
9
+ class Cli
10
+ def parse args
11
+ options = {}
12
+
13
+ opt_parser = ::OptionParser.new do |opts|
14
+ opts.program_name = 'asciidoctor-reducer'
15
+ opts.banner = <<~EOS
16
+ Usage: #{opts.program_name} [OPTION]... FILE
17
+
18
+ Reduces an AsciiDoc document with includes to a single AsciiDoc document.
19
+
20
+ EOS
21
+
22
+ opts.on '-o FILE', '--output=FILE', 'Set the output filename or stream' do |file|
23
+ options[:output_file] = file
24
+ end
25
+
26
+ opts.on '-h', '--help', 'Display this help text and exit' do
27
+ $stdout.write opts.help
28
+ return 0
29
+ end
30
+
31
+ opts.on '-v', '--version', %(Display version information and exit) do
32
+ $stdout.write %(#{opts.program_name} #{::Asciidoctor::Reducer::VERSION}\n)
33
+ return 0
34
+ end
35
+ end
36
+
37
+ args = opt_parser.parse args
38
+
39
+ if args.empty?
40
+ opt_parser.warn 'Please specify an AsciiDoc file to reduce.'
41
+ $stdout.write opt_parser.help
42
+ 1
43
+ elsif args.size == 1
44
+ options[:input_file] = args[0]
45
+ options[:output_file] = '-' unless options[:output_file]
46
+ [0, options]
47
+ else
48
+ opt_parser.warn %(extra arguments detected (unparsed arguments: #{(args.drop 1).join ' '}))
49
+ $stdout.write opt_parser.help
50
+ [1, options]
51
+ end
52
+ rescue ::OptionParser::InvalidOption
53
+ $stderr.write %(#{opt_parser.program_name}: #{$!.message}\n)
54
+ $stdout.write opt_parser.help
55
+ 1
56
+ end
57
+
58
+ def self.run args = ARGV
59
+ code, options = new.parse (Array args)
60
+ return code unless code == 0 && options
61
+ if (output_file = options.delete :output_file) == '-'
62
+ to = $stdout
63
+ else
64
+ (to = ::Pathname.new output_file).dirname.mkpath
65
+ end
66
+ if (input_file = options.delete :input_file) == '-'
67
+ reduced = (Asciidoctor.load $stdin, safe: :safe).source + ?\n
68
+ else
69
+ reduced = (Asciidoctor.load_file input_file, safe: :safe, to_file: false).source + ?\n
70
+ end
71
+ Pathname === to ? (to.write reduced, encoding: ::Encoding::UTF_8) : (to.write reduced)
72
+ 0
73
+ rescue ::IOError
74
+ $stderr.write %(asciidoctor-reducer: #{$!.message}\n)
75
+ 1
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor::Reducer
4
+ module AsciidoctorExt
5
+ module PreprocessorReader
6
+ def preprocess_include_directive target, attrlist
7
+ @x_include_directive_line = %(include::#{target}[#{attrlist}])
8
+ @x_push_include_called = false
9
+ inc_lineno = @lineno - 1 # we're currently on the include line, which is 1-based
10
+ result = super
11
+ return result if @x_push_include_called
12
+ parent_depth = (parents = @x_parents).length
13
+ depth_change = @include_stack.length - (parent_depth - 1)
14
+ parent_depth -= (parents.slice! parent_depth + depth_change, -depth_change).length if depth_change < 0
15
+ lines = ((line = @lines[-1].to_s).start_with? 'Unresolved directive in ') && (line.end_with? ']') ? [line] : []
16
+ @x_include_replacements << {
17
+ lines: lines,
18
+ into: parents[parent_depth - 1],
19
+ index: inc_lineno,
20
+ replace: @x_include_directive_line,
21
+ }
22
+ end
23
+
24
+ def push_include data, file, path, lineno, attrs
25
+ @x_push_include_called = true
26
+ inc_lineno = @lineno - 2 # we're below the include line, which is 1-based
27
+ prev_inc_depth = @include_stack.length
28
+ # Q: can we do this without resetting the lineno?
29
+ lineno = 1 # rubocop:disable Lint/ShadowedArgument
30
+ super
31
+ inc_depth = @include_stack.length
32
+ parent_depth = (parents = @x_parents).length
33
+ # push_include did not push to the stack
34
+ if inc_depth == prev_inc_depth
35
+ depth_change = inc_depth - (parent_depth - 1)
36
+ parent_depth -= (parents.slice! parent_depth + depth_change, -depth_change).length if depth_change < 0
37
+ @x_include_replacements << {
38
+ lines: [],
39
+ into: parents[parent_depth - 1],
40
+ index: inc_lineno,
41
+ replace: @x_include_directive_line,
42
+ }
43
+ else
44
+ depth_change = inc_depth - parent_depth
45
+ if depth_change > 0
46
+ parents << @x_include_replacements.length.pred
47
+ parent_depth += 1
48
+ elsif depth_change < 0
49
+ parent_depth -= (parents.slice! parent_depth + depth_change, -depth_change).length
50
+ end
51
+ @x_include_replacements << {
52
+ lines: @lines.reverse,
53
+ into: parents[parent_depth - 1],
54
+ index: inc_lineno,
55
+ replace: @x_include_directive_line,
56
+ }
57
+ end
58
+ self
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'preprocessor'
4
+ require_relative 'tree_processor'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ext/asciidoctor/preprocessor_reader'
4
+
5
+ module Asciidoctor::Reducer
6
+ class Preprocessor < ::Asciidoctor::Extensions::Preprocessor
7
+ def process doc, reader
8
+ return if doc.options[:reduced]
9
+ doc.sourcemap = true
10
+ # Q: is there a better place we can store the original logger?
11
+ ::Asciidoctor::LoggerManager.instance_variable_set :@original_logger, ::Asciidoctor::LoggerManager.logger
12
+ ::Asciidoctor::LoggerManager.logger = ::Asciidoctor::NullLogger.new
13
+ reader.singleton_class.prepend AsciidoctorExt::PreprocessorReader
14
+ reader.instance_variable_set :@x_include_replacements, []
15
+ reader.instance_variable_set :@x_parents, [-1]
16
+ nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor::Reducer
4
+ class TreeProcessor < ::Asciidoctor::Extensions::TreeProcessor
5
+ def process doc
6
+ return if doc.options[:reduced]
7
+ unless (inc_replacements = doc.reader.instance_variable_get :@x_include_replacements).empty?
8
+ resolved_source_lines = doc.source_lines.dup
9
+ inc_replacements.reverse_each do |it|
10
+ # when into is -1, it indicates this is a top-level include
11
+ target_lines = (into = it[:into]) < 0 ? resolved_source_lines : inc_replacements[into][:lines]
12
+ # adds extra bit of assurance that we're replacing the correct line
13
+ if target_lines[(index = it[:index])] == it[:replace]
14
+ target_lines[index..index] = it[:lines]
15
+ end
16
+ end
17
+ # WARNING: if include directives remain that can still be resolved, the sourcemap won't match the source lines
18
+ doc = ::Asciidoctor.load resolved_source_lines, (doc.options.merge sourcemap: true, reduced: true)
19
+ end
20
+ ::Asciidoctor::LoggerManager.logger = ::Asciidoctor::LoggerManager.instance_variable_get :@original_logger
21
+ ::Asciidoctor::LoggerManager.remove_instance_variable :@original_logger
22
+ doc
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor
4
+ module Reducer
5
+ VERSION = '1.0.0.alpha.1'
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'asciidoctor'
4
+ require_relative 'reducer/extensions'
5
+
6
+ Asciidoctor::Extensions.register do
7
+ preprocessor Asciidoctor::Reducer::Preprocessor
8
+ tree_processor Asciidoctor::Reducer::TreeProcessor
9
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'asciidoctor/reducer'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asciidoctor-reducer
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-01-12 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'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 13.0.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 13.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.10.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.10.0
55
+ description: A tool that reduces an AsciiDoc document with includes to a single AsciiDoc
56
+ document by expanding the includes reachable from the specified parent document.
57
+ email: dan.j.allen@gmail.com
58
+ executables:
59
+ - asciidoctor-reducer
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - CHANGELOG.adoc
64
+ - LICENSE
65
+ - README.adoc
66
+ - asciidoctor-reducer.gemspec
67
+ - bin/asciidoctor-reducer
68
+ - lib/asciidoctor-reducer.rb
69
+ - lib/asciidoctor/reducer.rb
70
+ - lib/asciidoctor/reducer/cli.rb
71
+ - lib/asciidoctor/reducer/ext/asciidoctor/preprocessor_reader.rb
72
+ - lib/asciidoctor/reducer/extensions.rb
73
+ - lib/asciidoctor/reducer/preprocessor.rb
74
+ - lib/asciidoctor/reducer/tree_processor.rb
75
+ - lib/asciidoctor/reducer/version.rb
76
+ homepage: https://asciidoctor.org
77
+ licenses:
78
+ - MIT
79
+ metadata:
80
+ bug_tracker_uri: https://github.com/asciidoctor/asciidoctor-reducer/issues
81
+ changelog_uri: https://github.com/asciidoctor/asciidoctor-reducer/blob/main/CHANGELOG.adoc
82
+ mailing_list_uri: https://asciidoctor.zulipchat.com
83
+ source_code_uri: https://github.com/asciidoctor/asciidoctor-reducer
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">"
96
+ - !ruby/object:Gem::Version
97
+ version: 1.3.1
98
+ requirements: []
99
+ rubygems_version: 3.2.32
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Reduces an AsciiDoc document with includes to a single AsciiDoc document.
103
+ test_files: []