asciidoctor-reducer 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: 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: []