asciidoctor-reducer 1.0.0.alpha.7 → 1.0.0.alpha.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a685ae408de9db32a7ec96055b70120ea6f7476436dca071cc37155cc680d56
4
- data.tar.gz: 39d783c66481423417d64a232ee01bdaa88bef517474d22e8ec9fdeb670d09d9
3
+ metadata.gz: 7df897a17f1fc52a4240d6c4bfe476e9072014dae43042063485634bda01eb13
4
+ data.tar.gz: 5be6330e865889c0a93cf83eb6a884e5785d644d8421d962b5f33950a0da67bc
5
5
  SHA512:
6
- metadata.gz: a3376645764a9d608f3e3aad5f29f2080748d9ecd20d90a06e2335263cdd7c88c0450a72ea061f8f36c17fa19af0f985a89002ee70e12ce950f4320c483b8140
7
- data.tar.gz: a7899259cf2ff2daf619d13b97d88dd460a013b0bc85d2c8402e1283f1b3d6fff3780bc3c112e4c281463ad06e0bcb035385998771528a01e3aac487dd7c6e09
6
+ metadata.gz: f4a788b3926a6f9bf925ec5607cc1756688de3ade791ea2178b3e893b9ad35bf0f2912cb0e23b5fc16a8834d2f28be4cc6c0bf6173a10858942522107991091b
7
+ data.tar.gz: 04afd98f0789e686f0328eb721c56f2c2150261209a66c90025d2dd91c10d9397a969b6a45c0060d77559df549a80cf3839f2940030e47105ca11bcd9ba02e5c
data/CHANGELOG.adoc CHANGED
@@ -4,6 +4,27 @@
4
4
  This document provides a high-level view of the changes to the Asciidoctor Reducer by 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.8 (2022-02-23) - @mojavelinux
8
+
9
+ === Added
10
+
11
+ * Add secure mode as value of `-S` CLI option (#31)
12
+ * Add `--trace` option to CLI to trace cause of application errors (#29)
13
+
14
+ === Changed
15
+
16
+ * Replace include directive with link macro if safe mode is secure (#31)
17
+ * Track line numbers in include replacements using 1-based index
18
+ * Only mix in preprocessor conditional tracker if `:preserve_conditionals` option is not set (#36)
19
+
20
+ === Fixed
21
+
22
+ * Handle signals gracefully (#33)
23
+
24
+ === Details
25
+
26
+ {url-repo}/releases/tag/v1.0.0.alpha.8[git tag]
27
+
7
28
  == 1.0.0.alpha.7 (2022-02-14) - @mojavelinux
8
29
 
9
30
  === Added
@@ -23,6 +44,10 @@ For a detailed view of what has changed, refer to the {url-repo}/commits/main[co
23
44
 
24
45
  * Require asciidoctor/reducer/version automatically when `Asciidoctor::Reducer::VERSION` is accessed
25
46
 
47
+ === Details
48
+
49
+ {url-repo}/releases/tag/v1.0.0.alpha.7[git tag]
50
+
26
51
  == 1.0.0.alpha.6 (2022-02-10) - @mojavelinux
27
52
 
28
53
  === Added
@@ -43,6 +68,10 @@ For a detailed view of what has changed, refer to the {url-repo}/commits/main[co
43
68
  * Prevent custom extension registry from activating extensions twice during reload (#21)
44
69
  * Retain includes table in document catalog when reloading document (#23)
45
70
 
71
+ === Details
72
+
73
+ {url-repo}/releases/tag/v1.0.0.alpha.6[git tag]
74
+
46
75
  == 1.0.0.alpha.5 (2022-02-06) - @mojavelinux
47
76
 
48
77
  === Changed
@@ -56,12 +85,20 @@ For a detailed view of what has changed, refer to the {url-repo}/commits/main[co
56
85
 
57
86
  * Suppress log messages when reloading document (#14)
58
87
 
88
+ === Details
89
+
90
+ {url-repo}/releases/tag/v1.0.0.alpha.5[git tag]
91
+
59
92
  == 1.0.0.alpha.4 (2022-02-03) - @mojavelinux
60
93
 
61
94
  === Fixed
62
95
 
63
96
  * Fix replacement of nested empty and unresolved includes
64
97
 
98
+ === Details
99
+
100
+ {url-repo}/releases/tag/v1.0.0.alpha.4[git tag]
101
+
65
102
  == 1.0.0.alpha.3 (2022-02-02) - @mojavelinux
66
103
 
67
104
  === Changed
@@ -71,6 +108,10 @@ For a detailed view of what has changed, refer to the {url-repo}/commits/main[co
71
108
  * Only reload document if source lines have changed; otherwise, update source lines on reader directly
72
109
  * Change default safe mode for CLI to :unsafe
73
110
 
111
+ === Details
112
+
113
+ {url-repo}/releases/tag/v1.0.0.alpha.3[git tag]
114
+
74
115
  == 1.0.0.alpha.2 (2022-01-27) - @mojavelinux
75
116
 
76
117
  === Added
@@ -90,34 +131,14 @@ For a detailed view of what has changed, refer to the {url-repo}/commits/main[co
90
131
 
91
132
  * Preserve return value when overridding `preprocess_include_directive` method
92
133
 
93
- == 1.0.0.alpha.1 (2022-01-12) - @mojavelinux
94
-
95
- Initial release.
96
-
97
- === Details
98
-
99
- {url-repo}/releases/tag/v1.0.0.alpha.1[git tag]
100
-
101
134
  === Details
102
135
 
103
136
  {url-repo}/releases/tag/v1.0.0.alpha.2[git tag]
104
137
 
105
- === Details
106
-
107
- {url-repo}/releases/tag/v1.0.0.alpha.3[git tag]
108
-
109
- === Details
110
-
111
- {url-repo}/releases/tag/v1.0.0.alpha.4[git tag]
112
-
113
- === Details
114
-
115
- {url-repo}/releases/tag/v1.0.0.alpha.5[git tag]
116
-
117
- === Details
138
+ == 1.0.0.alpha.1 (2022-01-12) - @mojavelinux
118
139
 
119
- {url-repo}/releases/tag/v1.0.0.alpha.6[git tag]
140
+ Initial release.
120
141
 
121
142
  === Details
122
143
 
123
- {url-repo}/releases/tag/v1.0.0.alpha.7[git tag]
144
+ {url-repo}/releases/tag/v1.0.0.alpha.1[git tag]
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (C) 2021 Dan Allen
3
+ Copyright (C) 2021-present Dan Allen
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.adoc CHANGED
@@ -1,6 +1,6 @@
1
1
  = {project-name}
2
2
  Dan Allen <https://github.com/mojavelinux[@mojavelinux]>
3
- v1.0.0.alpha.7, 2022-02-14
3
+ v1.0.0.alpha.8, 2022-02-23
4
4
  :idprefix:
5
5
  :idseparator: -
6
6
  ifndef::env-github[:icons: font]
@@ -49,18 +49,22 @@ module Asciidoctor::Reducer
49
49
  (options[:requires] ||= []).concat path.split ','
50
50
  end
51
51
 
52
- opts.on '-S', '--safe-mode SAFE_MODE', ['unsafe', 'safe', 'server'],
53
- 'set supported safe mode level: [unsafe, safe, server] (default: unsafe)' do |name|
52
+ opts.on '-S', '--safe-mode SAFE_MODE', ['unsafe', 'safe', 'server', 'secure'],
53
+ 'set safe mode level: [unsafe, safe, server, secure] (default: unsafe)' do |name|
54
54
  options[:safe] = ::Asciidoctor::SafeMode.value_for_name name
55
55
  end
56
56
 
57
+ opts.on '--trace', 'trace the cause of application errors (default: false)' do
58
+ options[:trace] = true
59
+ end
60
+
57
61
  opts.on '-v', '--version', 'display the version information and exit' do
58
- $stdout.write %(#{opts.program_name} #{VERSION}\n)
62
+ print_version opts
59
63
  return 0
60
64
  end
61
65
 
62
66
  opts.on '-h', '--help', 'display this help text and exit' do
63
- $stdout.write opts.help
67
+ print_help opts
64
68
  return 0
65
69
  end
66
70
  end
@@ -69,14 +73,14 @@ module Asciidoctor::Reducer
69
73
 
70
74
  if args.empty?
71
75
  opt_parser.warn 'Please specify an AsciiDoc file to reduce.'
72
- $stdout.write opt_parser.help
76
+ print_help opt_parser
73
77
  1
74
78
  elsif args.size == 1
75
79
  if (requires = options.delete :requires)
76
80
  requires.uniq.each do |path|
77
81
  require path
78
82
  rescue ::LoadError
79
- $stderr.write %(#{opt_parser.program_name}: '#{path}' could not be required (reason: #{$!.message})\n)
83
+ $stderr.puts %(#{opt_parser.program_name}: '#{path}' could not be required (reason: #{$!.message}))
80
84
  return 1
81
85
  end
82
86
  end
@@ -85,18 +89,19 @@ module Asciidoctor::Reducer
85
89
  [0, options]
86
90
  else
87
91
  opt_parser.warn %(extra arguments detected (unparsed arguments: #{(args.drop 1).join ' '}))
88
- $stdout.write opt_parser.help
92
+ print_help opt_parser
89
93
  1
90
94
  end
91
95
  rescue ::OptionParser::InvalidOption
92
- $stderr.write %(#{opt_parser.program_name}: #{$!.message}\n)
93
- $stdout.write opt_parser.help
96
+ $stderr.puts %(#{opt_parser.program_name}: #{$!.message})
97
+ print_help opt_parser
94
98
  1
95
99
  end
96
100
 
97
101
  def self.run args = ARGV
98
102
  code, options = new.parse (Array args)
99
103
  return code unless code == 0 && options
104
+ trace = options.delete :trace
100
105
  old_logger = ::Asciidoctor::LoggerManager.logger
101
106
  if (log_level = options.delete :log_level)
102
107
  (options[:logger] = ::Asciidoctor::Logger.new $stderr).level = log_level
@@ -107,11 +112,26 @@ module Asciidoctor::Reducer
107
112
  input = (input_file = options.delete :input_file) == '-' ? $stdin : (::Pathname.new input_file)
108
113
  ::Asciidoctor::Reducer.reduce input, options
109
114
  0
115
+ rescue ::SignalException
116
+ $stderr.puts if ::Interrupt === $!
117
+ $!.signo
110
118
  rescue
111
- $stderr.write %(asciidoctor-reducer: #{$!.message}\n)
119
+ raise $! if trace
120
+ $stderr.puts %(asciidoctor-reducer: #{$!.message.delete_prefix 'asciidoctor: '})
121
+ $stderr.puts ' Use --trace to show backtrace'
112
122
  1
113
123
  ensure
114
124
  ::Asciidoctor::LoggerManager.logger = old_logger if old_logger
115
125
  end
126
+
127
+ private
128
+
129
+ def print_help opt_parser
130
+ $stdout.puts opt_parser.help.chomp
131
+ end
132
+
133
+ def print_version opt_parser
134
+ $stdout.puts %(#{opt_parser.program_name} #{VERSION})
135
+ end
116
136
  end
117
137
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor::Reducer
4
+ module ConditionalDirectiveTracker
5
+ def preprocess_conditional_directive keyword, target, delimiter, text
6
+ skip_active = @skipping
7
+ depth = @conditional_stack.size
8
+ cond_lineno = @lineno
9
+ result = super
10
+ return result if @skipping && skip_active
11
+ drop = @x_include_replacements.current[:drop] ||= []
12
+ if (depth_change = @conditional_stack.size - depth) < 0
13
+ if skip_active
14
+ drop.push(*(drop.pop..cond_lineno))
15
+ else
16
+ drop << cond_lineno
17
+ end
18
+ elsif depth_change > 0 || cond_lineno == @lineno
19
+ drop << cond_lineno
20
+ else
21
+ drop << [cond_lineno, text]
22
+ end
23
+ result
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Asciidoctor::Reducer
4
+ module IncludeDirectiveTracker
5
+ attr_writer :source_lines
6
+ attr_reader :x_include_replacements
7
+
8
+ def self.extended instance
9
+ instance.instance_variable_set :@x_include_replacements, ([{}].extend CurrentPosition)
10
+ instance.instance_variable_set :@x_include_directive_line, nil
11
+ instance.instance_variable_set :@x_include_pushed, nil
12
+ end
13
+
14
+ def preprocess_include_directive target, attrlist
15
+ @x_include_directive_line = %(include::#{target}[#{attrlist}])
16
+ @x_include_pushed = false
17
+ inc_lineno = @lineno # we're currently on the include line, which is 1-based
18
+ result = super
19
+ unless @x_include_pushed
20
+ if (ln = peek_line true) && (ln.end_with? ']') && !(unresolved = ln.start_with? 'Unresolved directive in ')
21
+ if @document.safe >= ::Asciidoctor::SafeMode::SECURE && inc_lineno == @lineno && (ln.start_with? 'link:')
22
+ unresolved = !(ln = %(#{ln.slice 0, (ln.length - 1)}role=include])).nil?
23
+ end
24
+ end
25
+ push_include_replacement inc_lineno, (unresolved ? [ln] : []), unresolved
26
+ end
27
+ @x_include_directive_line = @x_include_pushed = nil
28
+ result
29
+ end
30
+
31
+ def push_include data, file, path, lineno, attrs
32
+ @x_include_pushed = true
33
+ inc_lineno = @lineno - 1 # we're below the include line, which is 1-based
34
+ prev_inc_depth = @include_stack.size
35
+ result = super
36
+ push_include_replacement inc_lineno, (@include_stack.size > prev_inc_depth ? lines : [])
37
+ result
38
+ end
39
+
40
+ def pop_include
41
+ @x_include_replacements.pos = @x_include_replacements.current[:into] unless @x_include_pushed
42
+ super
43
+ end
44
+
45
+ private
46
+
47
+ def push_include_replacement lineno, lines, unresolved = false
48
+ (inc_replacements = @x_include_replacements) << {
49
+ into: inc_replacements.pos,
50
+ lineno: lineno,
51
+ line: @x_include_directive_line,
52
+ lines: lines,
53
+ }
54
+ inc_replacements.pos = inc_replacements.size - 1 unless unresolved || lines.empty?
55
+ nil
56
+ end
57
+ end
58
+
59
+ module CurrentPosition
60
+ attr_accessor :pos
61
+
62
+ def self.extended instance
63
+ instance.pos = instance.size - 1
64
+ end
65
+
66
+ def current
67
+ self[@pos]
68
+ end
69
+ end
70
+
71
+ private_constant :CurrentPosition
72
+ end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'preprocessor_directive_tracker'
3
+ require_relative 'include_directive_tracker'
4
+ require_relative 'conditional_directive_tracker'
4
5
 
5
6
  module Asciidoctor::Reducer
6
7
  class Preprocessor < ::Asciidoctor::Extensions::Preprocessor
7
- def process _, reader
8
- reader.extend PreprocessorDirectiveTracker
8
+ def process doc, reader
9
+ reader.extend IncludeDirectiveTracker
10
+ reader.extend ConditionalDirectiveTracker unless doc.options[:preserve_conditionals]
9
11
  end
10
12
  end
11
13
  end
@@ -3,19 +3,21 @@
3
3
  module Asciidoctor::Reducer
4
4
  class TreeProcessor < ::Asciidoctor::Extensions::TreeProcessor
5
5
  def process doc
6
- unless (inc_replacements = doc.reader.x_include_replacements).length == 1 && inc_replacements[0][:drop].empty?
6
+ if (inc_replacements = doc.reader.x_include_replacements).size > 1 || !(inc_replacements[0][:drop] || []).empty?
7
7
  inc_replacements[0][:lines] = doc.source_lines.dup
8
8
  inc_replacements.reverse_each do |it|
9
9
  if (into = it[:into])
10
10
  target_lines = inc_replacements[into][:lines]
11
11
  # adds extra bit of assurance that we're replacing the correct line
12
- next unless target_lines[(index = it[:lineno])] == it[:line]
12
+ next unless target_lines[(idx = it[:lineno] - 1)] == it[:line]
13
13
  end
14
14
  lines = it[:lines]
15
- unless (drop = it[:drop]).empty?
16
- drop.reverse_each {|idx| ::Array === idx ? (lines[idx[0]] = idx[1]) : (lines.delete_at idx) }
15
+ unless (drop = it[:drop] || []).empty?
16
+ drop.reverse_each do |drop_it|
17
+ ::Array === drop_it ? (lines[drop_it[0] - 1] = drop_it[1]) : (lines.delete_at drop_it - 1)
18
+ end
17
19
  end
18
- target_lines[index] = lines if target_lines
20
+ target_lines[idx] = lines if target_lines
19
21
  end
20
22
  source_lines = inc_replacements[0][:lines].flatten
21
23
  if doc.sourcemap
@@ -30,7 +32,7 @@ module Asciidoctor::Reducer
30
32
  doc.parse
31
33
  ::Asciidoctor::LoggerManager.logger = logger
32
34
  else
33
- source_lines.pop while (last = source_lines[-1]) && last.empty?
35
+ source_lines.pop while (source_lines[-1] || :eof).empty?
34
36
  doc.reader.source_lines = source_lines
35
37
  end
36
38
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Asciidoctor
4
4
  module Reducer
5
- VERSION = '1.0.0.alpha.7'
5
+ VERSION = '1.0.0.alpha.8'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-reducer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha.7
4
+ version: 1.0.0.alpha.8
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-02-14 00:00:00.000000000 Z
11
+ date: 2022-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -70,9 +70,10 @@ files:
70
70
  - lib/asciidoctor/reducer.rb
71
71
  - lib/asciidoctor/reducer/api.rb
72
72
  - lib/asciidoctor/reducer/cli.rb
73
+ - lib/asciidoctor/reducer/conditional_directive_tracker.rb
73
74
  - lib/asciidoctor/reducer/extensions.rb
75
+ - lib/asciidoctor/reducer/include_directive_tracker.rb
74
76
  - lib/asciidoctor/reducer/preprocessor.rb
75
- - lib/asciidoctor/reducer/preprocessor_directive_tracker.rb
76
77
  - lib/asciidoctor/reducer/tree_processor.rb
77
78
  - lib/asciidoctor/reducer/version.rb
78
79
  homepage: https://asciidoctor.org
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Asciidoctor::Reducer
4
- module PreprocessorDirectiveTracker
5
- attr_writer :source_lines
6
- attr_reader :x_include_replacements
7
-
8
- def self.extended instance
9
- instance.instance_variable_set :@x_include_replacements, ([{ drop: [] }].extend CurrentPosition)
10
- instance.instance_variable_set :@x_include_directive_line, nil
11
- instance.instance_variable_set :@x_include_pushed, nil
12
- end
13
-
14
- def preprocess_conditional_directive keyword, target, delimiter, text
15
- return super if @document.options[:preserve_conditionals]
16
- skip_active = @skipping
17
- depth = @conditional_stack.length
18
- cond_lineno = @lineno - 1
19
- result = super
20
- return result if @skipping && skip_active
21
- drop = @x_include_replacements.current[:drop]
22
- if (depth_change = @conditional_stack.length - depth) < 0
23
- if skip_active
24
- drop.push(*(drop.pop..cond_lineno))
25
- else
26
- drop << cond_lineno
27
- end
28
- elsif depth_change > 0 || cond_lineno == @lineno - 1
29
- drop << cond_lineno
30
- else
31
- drop << [cond_lineno, text]
32
- end
33
- result
34
- end
35
-
36
- def preprocess_include_directive target, attrlist
37
- @x_include_directive_line = %(include::#{target}[#{attrlist}])
38
- @x_include_pushed = false
39
- inc_lineno = @lineno - 1 # we're currently on the include line, which is 1-based
40
- result = super
41
- unless @x_include_pushed
42
- unresolved = (l = peek_line true) && (l.start_with? 'Unresolved directive in ') && (l.end_with? ']') || nil
43
- push_include_replacement inc_lineno, (unresolved ? [l] : []), unresolved
44
- end
45
- @x_include_directive_line = @x_include_pushed = nil
46
- result
47
- end
48
-
49
- def push_include data, file, path, lineno, attrs
50
- @x_include_pushed = true
51
- inc_lineno = @lineno - 2 # we're below the include line, which is 1-based
52
- prev_inc_depth = @include_stack.length
53
- result = super
54
- push_include_replacement inc_lineno, (@include_stack.length > prev_inc_depth ? lines : [])
55
- result
56
- end
57
-
58
- def pop_include
59
- @x_include_replacements.pos = @x_include_replacements.current[:into] unless @x_include_pushed
60
- super
61
- end
62
-
63
- private
64
-
65
- def push_include_replacement inc_lineno, inc_lines, unresolved = false
66
- @x_include_replacements << {
67
- into: @x_include_replacements.pos,
68
- lineno: inc_lineno,
69
- line: @x_include_directive_line,
70
- lines: inc_lines,
71
- drop: [],
72
- }
73
- @x_include_replacements.pos = @x_include_replacements.length - 1 unless unresolved || inc_lines.empty?
74
- nil
75
- end
76
- end
77
-
78
- module CurrentPosition
79
- attr_accessor :pos
80
-
81
- def self.extended instance
82
- instance.pos = instance.length - 1
83
- end
84
-
85
- def current
86
- self[@pos]
87
- end
88
- end
89
-
90
- private_constant :CurrentPosition
91
- end