coradoc-adoc 2.0.24 → 2.0.25

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coradoc/asciidoc/builder/detection.rb +4 -4
  3. data/lib/coradoc/asciidoc/model/attribute_list/matchers.rb +4 -4
  4. data/lib/coradoc/asciidoc/model/block/core.rb +1 -1
  5. data/lib/coradoc/asciidoc/model/content_list.rb +8 -8
  6. data/lib/coradoc/asciidoc/model/inline/bold.rb +1 -1
  7. data/lib/coradoc/asciidoc/model/inline/highlight.rb +1 -1
  8. data/lib/coradoc/asciidoc/model/inline/italic.rb +1 -1
  9. data/lib/coradoc/asciidoc/model/inline/monospace.rb +1 -1
  10. data/lib/coradoc/asciidoc/model/inline/strikethrough.rb +2 -2
  11. data/lib/coradoc/asciidoc/model/inline/subscript.rb +1 -1
  12. data/lib/coradoc/asciidoc/model/inline/superscript.rb +1 -1
  13. data/lib/coradoc/asciidoc/model/serialization/asciidoc_mapping.rb +3 -4
  14. data/lib/coradoc/asciidoc/model/text_element.rb +22 -0
  15. data/lib/coradoc/asciidoc/parser/block.rb +3 -3
  16. data/lib/coradoc/asciidoc/transform/from_core_model.rb +5 -2
  17. data/lib/coradoc/asciidoc/transform/inline_transform_visitor.rb +6 -1
  18. data/lib/coradoc/asciidoc/transformer/block_rules.rb +3 -7
  19. data/lib/coradoc/asciidoc/transformer/block_type_classifier.rb +10 -10
  20. data/lib/coradoc/asciidoc/transformer/header_rules.rb +3 -6
  21. data/lib/coradoc/asciidoc/transformer/inline_rules.rb +20 -40
  22. data/lib/coradoc/asciidoc/transformer/list_rules.rb +5 -10
  23. data/lib/coradoc/asciidoc/transformer/misc_rules.rb +10 -20
  24. data/lib/coradoc/asciidoc/transformer/source_line_extractor.rb +0 -1
  25. data/lib/coradoc/asciidoc/transformer/structural_rules.rb +3 -7
  26. data/lib/coradoc/asciidoc/transformer/table_layout.rb +1 -3
  27. data/lib/coradoc/asciidoc/transformer/text_rules.rb +9 -18
  28. data/lib/coradoc/asciidoc/transformer.rb +26 -2
  29. data/lib/coradoc/asciidoc/version.rb +1 -1
  30. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d135f788f7205a03a242f7d1e9242b84fdc76994f6eff372579db29c9c420d51
4
- data.tar.gz: 6eafdb8eb6a101650e48e6a29d5e719f729d8c7888c506a5e67a33511640db2f
3
+ metadata.gz: 4ecb988af13f918e49f0249e3691e22fd98f21beffd3f0e2d6c98affc39d64dc
4
+ data.tar.gz: 4db6ab5b2227364c2092f00b40167fa054ed1dd43592150baf1c745e39f98a09
5
5
  SHA512:
6
- metadata.gz: cfe57d959c7d69cf47aadb30526cd826ac85720d1f3f4426c4f6fc4d769c2618ad2c31cd713e3b86b4480f79fdf41d473457623c145746eb7fc25155c47b2dfc
7
- data.tar.gz: 07dcf6099269006d16c34a21f5ca9457227fe9e7fcd597607716511ddecf7a3a1b7d794d5f32a29c6542a4b4f93ced0f61b37ae7e06553d775a0068ad4f7f363
6
+ metadata.gz: 26ea9aeac36925a4ce0df0221ffba1e0c5ba41fc33de0b8c0937229e353f2f758e101a873e0eab76ed46408fe71990c0001088612ecef50c0f3a22fba17646db
7
+ data.tar.gz: 2a7a709b48e9c0764c12b5a54be0846ecd08551245e92dd6028deb881c1ebff634514445a72cf28d24a6e31a5bdd90b12c6519e523e440977a7bfe9f767949a5
@@ -70,10 +70,10 @@ module Coradoc
70
70
  return false
71
71
  end
72
72
 
73
- key = "#{format_type}_constrained".to_sym
73
+ key = :"#{format_type}_constrained"
74
74
  return true if ast.key?(key)
75
75
 
76
- unconstrained_key = "#{format_type}_unconstrained".to_sym
76
+ unconstrained_key = :"#{format_type}_unconstrained"
77
77
  return false if ast.key?(unconstrained_key)
78
78
 
79
79
  true
@@ -158,8 +158,8 @@ module Coradoc
158
158
  def extract_inline_content(ast, format_type)
159
159
  content_key = format_type.to_sym
160
160
  content = ast[content_key] ||
161
- ast["#{format_type}_constrained".to_sym] ||
162
- ast["#{format_type}_unconstrained".to_sym]
161
+ ast[:"#{format_type}_constrained"] ||
162
+ ast[:"#{format_type}_unconstrained"]
163
163
 
164
164
  extract_text_content(content)
165
165
  end
@@ -5,8 +5,8 @@ module Coradoc
5
5
  module Model
6
6
  class AttributeList < Base
7
7
  module Matchers
8
- def one(*args)
9
- One.new(*args)
8
+ def one(*)
9
+ One.new(*)
10
10
  end
11
11
 
12
12
  class One
@@ -19,8 +19,8 @@ module Coradoc
19
19
  end
20
20
  end
21
21
 
22
- def many(*args)
23
- Many.new(*args)
22
+ def many(*)
23
+ Many.new(*)
24
24
  end
25
25
 
26
26
  # NOTE: The Many matcher validates that all values in an array/string match
@@ -54,7 +54,7 @@ module Coradoc
54
54
  include Coradoc::AsciiDoc::Model::Anchorable
55
55
 
56
56
  attribute :id, :string
57
- attribute :title, :string, default: -> { nil } # Polymorphic: string or array of Model objects
57
+ attribute :title, :string, default: -> {} # Polymorphic: string or array of Model objects
58
58
  attribute :attributes, Coradoc::AsciiDoc::Model::AttributeList, default: lambda {
59
59
  Coradoc::AsciiDoc::Model::AttributeList.new
60
60
  }
@@ -86,8 +86,8 @@ module Coradoc
86
86
  # @example Iterate
87
87
  # content.each { |item| puts item }
88
88
  #
89
- def each(&block)
90
- @items.each(&block)
89
+ def each(&)
90
+ @items.each(&)
91
91
  end
92
92
 
93
93
  # Add an item to the content
@@ -199,8 +199,8 @@ module Coradoc
199
199
  # @example Map
200
200
  # content.map(&:class) # => [String, Bold, String]
201
201
  #
202
- def map(&block)
203
- @items.map(&block)
202
+ def map(&)
203
+ @items.map(&)
204
204
  end
205
205
 
206
206
  # Select items matching predicate
@@ -211,8 +211,8 @@ module Coradoc
211
211
  # @example Select strings
212
212
  # content.select { |i| i.is_a?(String) }
213
213
  #
214
- def select(&block)
215
- @items.select(&block)
214
+ def select(&)
215
+ @items.select(&)
216
216
  end
217
217
 
218
218
  # Reject items matching predicate
@@ -220,8 +220,8 @@ module Coradoc
220
220
  # @yield [Object] Each item
221
221
  # @return [Array] Remaining items
222
222
  #
223
- def reject(&block)
224
- @items.reject(&block)
223
+ def reject(&)
224
+ @items.reject(&)
225
225
  end
226
226
 
227
227
  # Check if content includes an item
@@ -25,7 +25,7 @@ module Coradoc
25
25
  class Bold < Base
26
26
  attribute :content,
27
27
  Lutaml::Model::Serializable,
28
- default: -> { nil },
28
+ default: -> {},
29
29
  polymorphic: [
30
30
  Lutaml::Model::Type::String,
31
31
  :array
@@ -23,7 +23,7 @@ module Coradoc
23
23
  class Highlight < Base
24
24
  attribute :content,
25
25
  Lutaml::Model::Serializable,
26
- default: -> { nil },
26
+ default: -> {},
27
27
  polymorphic: [
28
28
  Lutaml::Model::Type::String,
29
29
  :array
@@ -25,7 +25,7 @@ module Coradoc
25
25
  class Italic < Base
26
26
  attribute :content,
27
27
  Lutaml::Model::Serializable,
28
- default: -> { nil },
28
+ default: -> {},
29
29
  polymorphic: [
30
30
  Lutaml::Model::Type::String,
31
31
  :array
@@ -26,7 +26,7 @@ module Coradoc
26
26
  class Monospace < Base
27
27
  attribute :content,
28
28
  Lutaml::Model::Serializable,
29
- default: -> { nil },
29
+ default: -> {},
30
30
  polymorphic: [
31
31
  Lutaml::Model::Type::String,
32
32
  :array
@@ -25,12 +25,12 @@ module Coradoc
25
25
  class Strikethrough < Base
26
26
  attribute :content,
27
27
  Lutaml::Model::Serializable,
28
- default: -> { nil },
28
+ default: -> {},
29
29
  polymorphic: [
30
30
  Lutaml::Model::Type::String,
31
31
  :array
32
32
  ]
33
- attribute :text, :string, default: -> { nil }
33
+ attribute :text, :string, default: -> {}
34
34
  attribute :unconstrained, :boolean, default: -> { false }
35
35
  end
36
36
  end
@@ -21,7 +21,7 @@ module Coradoc
21
21
  class Subscript < Base
22
22
  attribute :content,
23
23
  Lutaml::Model::Serializable,
24
- default: -> { nil },
24
+ default: -> {},
25
25
  polymorphic: [
26
26
  Lutaml::Model::Type::String,
27
27
  :array
@@ -21,7 +21,7 @@ module Coradoc
21
21
  class Superscript < Base
22
22
  attribute :content,
23
23
  Lutaml::Model::Serializable,
24
- default: -> { nil },
24
+ default: -> {},
25
25
  polymorphic: [
26
26
  Lutaml::Model::Type::String,
27
27
  :array
@@ -6,8 +6,7 @@ module Coradoc
6
6
  module Serialization
7
7
  # Define the DSL for defining mappings in Asciidoc format
8
8
  class AsciidocMapping < Lutaml::Model::Mapping
9
- attr_reader :mappings
10
- attr_writer :mappings
9
+ attr_accessor :mappings
11
10
 
12
11
  def initialize
13
12
  super
@@ -33,8 +32,8 @@ module Coradoc
33
32
 
34
33
  private
35
34
 
36
- def add_mapping(name, to, **options)
37
- @mappings << AsciidocMappingRule.new(name, to: to, **options)
35
+ def add_mapping(name, to, **)
36
+ @mappings << AsciidocMappingRule.new(name, to: to, **)
38
37
  end
39
38
  end
40
39
  end
@@ -3,6 +3,16 @@
3
3
  module Coradoc
4
4
  module AsciiDoc
5
5
  module Model
6
+ # Single source of truth for the markers AsciiDoc uses to terminate
7
+ # a TextElement. Exposed as a module so the transformer can compare
8
+ # against the constant without hand-writing string literals across
9
+ # the codebase (DRY), and so future markers (e.g. a hypothetical
10
+ # backslash-style hard break) extend one place.
11
+ module LineBreakMarker
12
+ HARD = '+'
13
+ end
14
+ private_constant :LineBreakMarker
15
+
6
16
  class TextElement < Base
7
17
  def inline?
8
18
  true
@@ -18,6 +28,18 @@ module Coradoc
18
28
  ]
19
29
  attribute :line_break, :string, default: -> { '' }
20
30
 
31
+ # Semantic predicates over the line-break marker. Consumers (the
32
+ # transformer, the serializer) call these instead of comparing
33
+ # line_break against literal strings, so the wire format for
34
+ # hard breaks is owned by the model layer (SRP).
35
+ def hard_break?
36
+ line_break == LineBreakMarker::HARD
37
+ end
38
+
39
+ def soft_break?
40
+ line_break.to_s.empty?
41
+ end
42
+
21
43
  def self.escape_keychars(string)
22
44
  subs = { '*' => '\*', '_' => '\_' }
23
45
  string
@@ -73,14 +73,14 @@ module Coradoc
73
73
  closing_fence = dynamic do |_s, c|
74
74
  str(c.captures[capture_key].to_s.strip)
75
75
  end
76
- language = (space? >> match("[A-Za-z0-9_+.-]").repeat(1).as(:language)).maybe
76
+ language = (space? >> match('[A-Za-z0-9_+.-]').repeat(1).as(:language)).maybe
77
77
 
78
78
  block_content_with_closing = dynamic do |_s, c|
79
- fence_str = c.captures[capture_key].to_s.strip
79
+ c.captures[capture_key].to_s.strip
80
80
  closing_pattern = closing_fence >> space? >> newline
81
81
 
82
82
  content = text_line(false, unguarded: true, verbatim: true) |
83
- empty_line.as(:line_break)
83
+ empty_line.as(:line_break)
84
84
 
85
85
  (closing_pattern.absent? >> content).repeat(1)
86
86
  end
@@ -300,8 +300,11 @@ module Coradoc
300
300
  end
301
301
 
302
302
  def transform_image(image)
303
- target_class = image.inline ? Coradoc::AsciiDoc::Model::Image::InlineImage
304
- : Coradoc::AsciiDoc::Model::Image::BlockImage
303
+ target_class = if image.inline
304
+ Coradoc::AsciiDoc::Model::Image::InlineImage
305
+ else
306
+ Coradoc::AsciiDoc::Model::Image::BlockImage
307
+ end
305
308
  target_class.new(**image_attributes(image))
306
309
  end
307
310
 
@@ -62,10 +62,15 @@ module Coradoc
62
62
  result
63
63
  end
64
64
 
65
+ # Two adjacent TextElements in the content array indicate the
66
+ # parser split a paragraph across source lines. Join them with a
67
+ # space (soft break) unless the second one carries a hard-break
68
+ # marker — the model owns that predicate, so this method does
69
+ # not reach into parser-specific line_break string values.
65
70
  def soft_break_before?(previous, current)
66
71
  previous.is_a?(Model::TextElement) &&
67
72
  current.is_a?(Model::TextElement) &&
68
- current.line_break != '+'
73
+ !current.hard_break?
69
74
  end
70
75
 
71
76
  def visit_model(model)
@@ -23,8 +23,7 @@ module Coradoc
23
23
  title: title,
24
24
  delimiter_len: delimiter.size,
25
25
  lines: lines,
26
- ordering: ordering,
27
- source_line: SourceLineExtractor.extract(block)
26
+ ordering: ordering
28
27
  }
29
28
  # Markdown fences carry the language tag inline (```ruby);
30
29
  # pass it through so the SourceCode classifier entry can set
@@ -37,8 +36,7 @@ module Coradoc
37
36
  rule(example: sequence(:example)) do
38
37
  Model::Block::Example.new(
39
38
  title: '',
40
- lines: example,
41
- source_line: SourceLineExtractor.extract(example)
39
+ lines: example
42
40
  )
43
41
  end
44
42
 
@@ -52,8 +50,7 @@ module Coradoc
52
50
  canonical = Coradoc::AsciiDoc::Transform::ElementTransformers::AdmonitionStyles.canonicalize(admonition_type.to_s)
53
51
  Model::Admonition.new(
54
52
  content: content,
55
- type: canonical,
56
- source_line: SourceLineExtractor.extract(admonition_type)
53
+ type: canonical
57
54
  )
58
55
  end
59
56
 
@@ -72,7 +69,6 @@ module Coradoc
72
69
  src: path,
73
70
  attributes: residual,
74
71
  line_break: "\n",
75
- source_line: SourceLineExtractor.extract(block_image),
76
72
  **promoted
77
73
  )
78
74
  end
@@ -16,23 +16,23 @@ module Coradoc
16
16
  # returning a Model::Block::* instance. `max_length` nil means
17
17
  # unbounded.
18
18
  DELIMITER_CLASSIFICATIONS = [
19
- ['*', 4, nil, ->(opts, attrs) {
19
+ ['*', 4, nil, lambda { |opts, attrs|
20
20
  if attrs && attrs.positional == [] && attrs.named.first&.name == 'reviewer'
21
- Model::Block::ReviewerComment.new(**opts.merge(attributes: attrs))
21
+ Model::Block::ReviewerComment.new(**opts, attributes: attrs)
22
22
  else
23
- Model::Block::Side.new(**opts.merge(attributes: attrs))
23
+ Model::Block::Side.new(**opts, attributes: attrs)
24
24
  end
25
25
  }],
26
- ['=', 4, nil, ->(opts, attrs) { Model::Block::Example.new(**opts.merge(attributes: attrs)) }],
27
- ['+', 4, nil, ->(opts, attrs) { Model::Block::Pass.new(**opts.merge(attributes: attrs)) }],
28
- ['.', 4, nil, ->(opts, attrs) { Model::Block::Literal.new(**opts.merge(attributes: attrs)) }],
29
- ['_', 4, nil, ->(opts, attrs) { Model::Block::Quote.new(**opts.merge(attributes: attrs)) }],
30
- ['-', 4, nil, ->(opts, attrs) { Model::Block::SourceCode.new(**opts.merge(attributes: attrs)) }],
31
- ['-', 2, 2, ->(opts, attrs) { Model::Block::Open.new(**opts.merge(attributes: attrs)) }],
26
+ ['=', 4, nil, ->(opts, attrs) { Model::Block::Example.new(**opts, attributes: attrs) }],
27
+ ['+', 4, nil, ->(opts, attrs) { Model::Block::Pass.new(**opts, attributes: attrs) }],
28
+ ['.', 4, nil, ->(opts, attrs) { Model::Block::Literal.new(**opts, attributes: attrs) }],
29
+ ['_', 4, nil, ->(opts, attrs) { Model::Block::Quote.new(**opts, attributes: attrs) }],
30
+ ['-', 4, nil, ->(opts, attrs) { Model::Block::SourceCode.new(**opts, attributes: attrs) }],
31
+ ['-', 2, 2, ->(opts, attrs) { Model::Block::Open.new(**opts, attributes: attrs) }],
32
32
  # Markdown-style triple-backtick fence: behaves as a SourceCode
33
33
  # block. The language tag parsed from the opening fence is passed
34
34
  # through opts[:lang]; extract_block_language prefers block.lang.
35
- ['`', 3, nil, ->(opts, attrs) {
35
+ ['`', 3, nil, lambda { |opts, attrs|
36
36
  model_opts = opts.merge(attributes: attrs, delimiter_char: '`')
37
37
  model_opts[:lang] = opts[:lang] if opts.key?(:lang)
38
38
  Model::Block::SourceCode.new(**model_opts)
@@ -22,8 +22,7 @@ module Coradoc
22
22
  id = nil if id && id.empty?
23
23
 
24
24
  Model::Header.new(
25
- id:, title:, author:, revision:,
26
- source_line: SourceLineExtractor.extract(header)
25
+ id:, title:, author:, revision:
27
26
  )
28
27
  end
29
28
 
@@ -38,8 +37,7 @@ module Coradoc
38
37
  email: simple(:email)
39
38
  ) do
40
39
  Model::Author.new(
41
- first_name:, last_name:, email:, middle_name: nil,
42
- source_line: SourceLineExtractor.extract(first_name)
40
+ first_name:, last_name:, email:, middle_name: nil
43
41
  )
44
42
  end
45
43
 
@@ -50,8 +48,7 @@ module Coradoc
50
48
  remark: simple(:remark)
51
49
  ) do
52
50
  Model::Revision.new(
53
- number:, date:, remark:,
54
- source_line: SourceLineExtractor.extract(number)
51
+ number:, date:, remark:
55
52
  )
56
53
  end
57
54
  end
@@ -10,8 +10,8 @@ module Coradoc
10
10
  # `span` is excluded because it carries `text:` + `attributes:`
11
11
  # rather than `content:`, so it gets its own pair of rules.
12
12
  FORMATTING_VARIANTS = [
13
- %i[bold Bold],
14
- %i[italic Italic],
13
+ %i[bold Bold],
14
+ %i[italic Italic],
15
15
  %i[highlight Highlight],
16
16
  %i[monospace Monospace]
17
17
  ].freeze
@@ -22,8 +22,7 @@ module Coradoc
22
22
  rule(link: subtree(:link)) do
23
23
  Model::Inline::Link.new(
24
24
  path: link[:path].to_s,
25
- name: link[:text]&.to_s,
26
- source_line: SourceLineExtractor.extract(link)
25
+ name: link[:text]&.to_s
27
26
  )
28
27
  end
29
28
 
@@ -33,8 +32,7 @@ module Coradoc
33
32
  text = xref[:text]
34
33
  args = text ? [text.to_s] : []
35
34
  Model::Inline::CrossReference.new(
36
- href:, args:,
37
- source_line: SourceLineExtractor.extract(xref)
35
+ href:, args:
38
36
  )
39
37
  end
40
38
 
@@ -47,7 +45,6 @@ module Coradoc
47
45
  Model::Image::InlineImage.new(
48
46
  src: inline_image[:path],
49
47
  attributes: residual,
50
- source_line: SourceLineExtractor.extract(inline_image),
51
48
  **promoted
52
49
  )
53
50
  end
@@ -59,16 +56,14 @@ module Coradoc
59
56
  rule(inline_passthrough: subtree(:passthrough)) do
60
57
  Model::Inline::Passthrough.new(
61
58
  content: passthrough[:raw].to_s,
62
- form: 'triple',
63
- source_line: SourceLineExtractor.extract(passthrough)
59
+ form: 'triple'
64
60
  )
65
61
  end
66
62
 
67
63
  # Attribute reference
68
64
  rule(attribute_reference: simple(:name)) do
69
65
  Model::Inline::AttributeReference.new(
70
- name:,
71
- source_line: SourceLineExtractor.extract(name)
66
+ name:
72
67
  )
73
68
  end
74
69
 
@@ -78,9 +73,7 @@ module Coradoc
78
73
  # blank lines. Hard breaks carry semantic meaning: HTML/Markdown
79
74
  # renderers map them to <br>.
80
75
  rule(hard_line_break: simple(:hard_line_break)) do
81
- Model::Inline::HardLineBreak.new(
82
- source_line: SourceLineExtractor.extract(hard_line_break)
83
- )
76
+ Model::Inline::HardLineBreak.new
84
77
  end
85
78
 
86
79
  # Term
@@ -89,8 +82,7 @@ module Coradoc
89
82
  term: simple(:term)
90
83
  ) do
91
84
  Coradoc::AsciiDoc::Model::Term.new(
92
- term:, type: term_type, lang: :en,
93
- source_line: SourceLineExtractor.extract(term_type)
85
+ term:, type: term_type, lang: :en
94
86
  )
95
87
  end
96
88
 
@@ -98,16 +90,14 @@ module Coradoc
98
90
  rule(footnote: simple(:footnote)) do
99
91
  text_str = footnote.to_s
100
92
  Coradoc::AsciiDoc::Model::Inline::Footnote.new(
101
- text: text_str,
102
- source_line: SourceLineExtractor.extract(footnote)
93
+ text: text_str
103
94
  )
104
95
  end
105
96
 
106
97
  rule(footnote: simple(:footnote), id: simple(:id)) do
107
98
  text_str = footnote.to_s
108
99
  Coradoc::AsciiDoc::Model::Inline::Footnote.new(
109
- text: text_str, id: id.to_s,
110
- source_line: SourceLineExtractor.extract(footnote)
100
+ text: text_str, id: id.to_s
111
101
  )
112
102
  end
113
103
 
@@ -115,8 +105,7 @@ module Coradoc
115
105
  rule(footnote: sequence(:footnote), id: simple(:id)) do
116
106
  text_str = footnote.map(&:to_s).join
117
107
  Coradoc::AsciiDoc::Model::Inline::Footnote.new(
118
- text: text_str, id: id.to_s,
119
- source_line: SourceLineExtractor.extract(footnote)
108
+ text: text_str, id: id.to_s
120
109
  )
121
110
  end
122
111
 
@@ -124,8 +113,7 @@ module Coradoc
124
113
  rule(footnote: sequence(:footnote)) do
125
114
  text_str = footnote.map(&:to_s).join
126
115
  Coradoc::AsciiDoc::Model::Inline::Footnote.new(
127
- text: text_str,
128
- source_line: SourceLineExtractor.extract(footnote)
116
+ text: text_str
129
117
  )
130
118
  end
131
119
 
@@ -141,15 +129,13 @@ module Coradoc
141
129
  rule(constrained_key => subtree(:subtree)) do
142
130
  content = Transformer.extract_inline_content(subtree)
143
131
  klass.new(
144
- content: content, unconstrained: false,
145
- source_line: SourceLineExtractor.extract(subtree)
132
+ content: content, unconstrained: false
146
133
  )
147
134
  end
148
135
  rule(unconstrained_key => subtree(:subtree)) do
149
136
  content = Transformer.extract_inline_content(subtree)
150
137
  klass.new(
151
- content: content, unconstrained: true,
152
- source_line: SourceLineExtractor.extract(subtree)
138
+ content: content, unconstrained: true
153
139
  )
154
140
  end
155
141
  end
@@ -159,8 +145,7 @@ module Coradoc
159
145
  Model::Inline::Span.new(
160
146
  text: span_constrained[:text],
161
147
  unconstrained: false,
162
- attributes: span_constrained[:attribute_list],
163
- source_line: SourceLineExtractor.extract(span_constrained)
148
+ attributes: span_constrained[:attribute_list]
164
149
  )
165
150
  end
166
151
 
@@ -169,8 +154,7 @@ module Coradoc
169
154
  Model::Inline::Span.new(
170
155
  text: span_unconstrained[:text],
171
156
  unconstrained: true,
172
- attributes: span_unconstrained[:attribute_list],
173
- source_line: SourceLineExtractor.extract(span_unconstrained)
157
+ attributes: span_unconstrained[:attribute_list]
174
158
  )
175
159
  end
176
160
 
@@ -178,8 +162,7 @@ module Coradoc
178
162
  rule(superscript: subtree(:superscript)) do
179
163
  content = Transformer.extract_simple_inline_content(superscript)
180
164
  Model::Inline::Superscript.new(
181
- content:,
182
- source_line: SourceLineExtractor.extract(superscript)
165
+ content:
183
166
  )
184
167
  end
185
168
 
@@ -187,24 +170,21 @@ module Coradoc
187
170
  rule(subscript: subtree(:subscript)) do
188
171
  content = Transformer.extract_simple_inline_content(subscript)
189
172
  Model::Inline::Subscript.new(
190
- content:,
191
- source_line: SourceLineExtractor.extract(subscript)
173
+ content:
192
174
  )
193
175
  end
194
176
 
195
177
  # Highlight (simple)
196
178
  rule(highlight: simple(:text)) do
197
179
  Model::Highlight.new(
198
- content: text,
199
- source_line: SourceLineExtractor.extract(text)
180
+ content: text
200
181
  )
201
182
  end
202
183
  # Stem
203
184
  rule(stem: subtree(:stem)) do
204
185
  Coradoc::AsciiDoc::Model::Inline::Stem.new(
205
186
  type: stem[:stem_type],
206
- content: stem[:content],
207
- source_line: SourceLineExtractor.extract(stem)
187
+ content: stem[:content]
208
188
  )
209
189
  end
210
190
  end
@@ -74,8 +74,7 @@ module Coradoc
74
74
  end
75
75
 
76
76
  Model::List::Item.new(
77
- content: content, id:, marker:, attached:, nested:, line_break:,
78
- source_line: SourceLineExtractor.extract(list_item)
77
+ content: content, id:, marker:, attached:, nested:, line_break:
79
78
  )
80
79
  end
81
80
 
@@ -87,8 +86,7 @@ module Coradoc
87
86
  # Unordered list
88
87
  rule(unordered: sequence(:list_items)) do
89
88
  Model::List::Unordered.new(
90
- items: list_items,
91
- source_line: SourceLineExtractor.extract(list_items)
89
+ items: list_items
92
90
  )
93
91
  end
94
92
 
@@ -98,16 +96,14 @@ module Coradoc
98
96
  ) do
99
97
  Model::List::Unordered.new(
100
98
  items: list_items,
101
- attrs: attribute_list,
102
- source_line: SourceLineExtractor.extract(attribute_list)
99
+ attrs: attribute_list
103
100
  )
104
101
  end
105
102
 
106
103
  # Ordered list
107
104
  rule(ordered: sequence(:list_items)) do
108
105
  Model::List::Ordered.new(
109
- items: list_items,
110
- source_line: SourceLineExtractor.extract(list_items)
106
+ items: list_items
111
107
  )
112
108
  end
113
109
 
@@ -117,8 +113,7 @@ module Coradoc
117
113
  ) do
118
114
  Model::List::Ordered.new(
119
115
  items: list_items,
120
- attrs: attribute_list,
121
- source_line: SourceLineExtractor.extract(attribute_list)
116
+ attrs: attribute_list
122
117
  )
123
118
  end
124
119
 
@@ -14,23 +14,19 @@ module Coradoc
14
14
  }) do
15
15
  Model::CommentLine.new(
16
16
  text: comment_text,
17
- line_break: line_break,
18
- source_line: SourceLineExtractor.extract(comment_text)
17
+ line_break: line_break
19
18
  )
20
19
  end
21
20
 
22
21
  rule(comment_block: { comment_text: simple(:comment_text) }) do
23
22
  Model::CommentBlock.new(
24
- text: comment_text,
25
- source_line: SourceLineExtractor.extract(comment_text)
23
+ text: comment_text
26
24
  )
27
25
  end
28
26
 
29
27
  # Page break
30
28
  rule(page_break: simple(:page_break)) do
31
- Model::Break::PageBreak.new(
32
- source_line: SourceLineExtractor.extract(page_break)
33
- )
29
+ Model::Break::PageBreak.new
34
30
  end
35
31
 
36
32
  # Tag
@@ -39,8 +35,7 @@ module Coradoc
39
35
  name: tag[:name],
40
36
  attrs: tag[:attribute_list],
41
37
  line_break: tag[:line_break],
42
- prefix: tag[:prefix],
43
- source_line: SourceLineExtractor.extract(tag)
38
+ prefix: tag[:prefix]
44
39
  )
45
40
  end
46
41
 
@@ -63,9 +58,8 @@ module Coradoc
63
58
  end
64
59
 
65
60
  rule(attribute_array: sequence(:attributes)) do
66
- attr_list = Model::AttributeList.new(
67
- source_line: SourceLineExtractor.extract(attributes)
68
- )
61
+ attr_list = Model::AttributeList.new
62
+
69
63
  attributes.each do |a|
70
64
  case a
71
65
  when Parslet::Slice
@@ -119,8 +113,7 @@ module Coradoc
119
113
  Model::Include.new(
120
114
  path: path.to_s,
121
115
  attributes: attribute_list,
122
- line_break: line_break,
123
- source_line: SourceLineExtractor.extract(path)
116
+ line_break: line_break
124
117
  )
125
118
  end
126
119
 
@@ -135,8 +128,7 @@ module Coradoc
135
128
  Model::Audio.new(
136
129
  src: path.to_s,
137
130
  attributes: attribute_list,
138
- line_break: line_break,
139
- source_line: SourceLineExtractor.extract(path)
131
+ line_break: line_break
140
132
  )
141
133
  end
142
134
 
@@ -151,8 +143,7 @@ module Coradoc
151
143
  Model::Video.new(
152
144
  src: path.to_s,
153
145
  attributes: attribute_list,
154
- line_break: line_break,
155
- source_line: SourceLineExtractor.extract(path)
146
+ line_break: line_break
156
147
  )
157
148
  end
158
149
 
@@ -180,8 +171,7 @@ module Coradoc
180
171
  date: attrs[:date],
181
172
  from: attrs[:from],
182
173
  to: attrs[:to],
183
- content: Transformer.lines_to_text_elements(lines),
184
- source_line: SourceLineExtractor.extract(reviewer_note)
174
+ content: Transformer.lines_to_text_elements(lines)
185
175
  )
186
176
  end
187
177
  end
@@ -37,7 +37,6 @@ module Coradoc
37
37
  when Coradoc::AsciiDoc::Model::Base then node.source_line
38
38
  when Hash then extract_from_hash(node)
39
39
  when Array then extract_from_array(node)
40
- else nil
41
40
  end
42
41
  end
43
42
 
@@ -72,7 +72,6 @@ module Coradoc
72
72
  opts = { rows: Transformer.regroup_table_rows(rows, attrs), attrs: attrs }
73
73
  opts[:id] = id if id
74
74
  opts[:title] = title unless title.nil? || title.empty?
75
- opts[:source_line] = SourceLineExtractor.extract(table)
76
75
  Model::Table.new(**opts)
77
76
  end
78
77
 
@@ -85,8 +84,7 @@ module Coradoc
85
84
  Model::Title.new(
86
85
  content: text,
87
86
  level_int: level.size - 1,
88
- line_break: line_break,
89
- source_line: SourceLineExtractor.extract(level)
87
+ line_break: line_break
90
88
  )
91
89
  end
92
90
 
@@ -100,8 +98,7 @@ module Coradoc
100
98
  content: text,
101
99
  level_int: level.size - 1,
102
100
  line_break: line_break,
103
- id: name,
104
- source_line: SourceLineExtractor.extract(name)
101
+ id: name
105
102
  )
106
103
  end
107
104
 
@@ -120,8 +117,7 @@ module Coradoc
120
117
  id: id,
121
118
  attribute_list: attribute_list,
122
119
  contents: contents,
123
- sections: sections,
124
- source_line: SourceLineExtractor.extract(section)
120
+ sections: sections
125
121
  )
126
122
  end
127
123
 
@@ -46,9 +46,7 @@ module Coradoc
46
46
  normalized_cells = cells.map { |cell| TableCellBuilder.normalize_cell(cell) }
47
47
 
48
48
  col_count = explicit_col_count
49
- if col_count.nil? || col_count.zero?
50
- col_count = infer_column_count(normalized_cells)
51
- end
49
+ col_count = infer_column_count(normalized_cells) if col_count.nil? || col_count.zero?
52
50
  col_count = normalized_cells.size if col_count.nil? || col_count.zero?
53
51
 
54
52
  rows = []
@@ -10,8 +10,7 @@ module Coradoc
10
10
  # Text Model
11
11
  rule(text: simple(:text)) do
12
12
  Model::TextElement.new(
13
- content: text.to_s,
14
- source_line: Transformer::SourceLineExtractor.extract(text)
13
+ content: text.to_s
15
14
  )
16
15
  end
17
16
 
@@ -22,31 +21,27 @@ module Coradoc
22
21
  rule(text: simple(:text), line_break: simple(:line_break)) do
23
22
  Model::TextElement.new(
24
23
  content: text.to_s,
25
- line_break: line_break,
26
- source_line: Transformer::SourceLineExtractor.extract(text)
24
+ line_break: line_break
27
25
  )
28
26
  end
29
27
 
30
28
  rule(text: sequence(:text), line_break: simple(:line_break)) do
31
29
  Model::TextElement.new(
32
30
  content: text,
33
- line_break: line_break,
34
- source_line: Transformer::SourceLineExtractor.extract(text)
31
+ line_break: line_break
35
32
  )
36
33
  end
37
34
 
38
35
  rule(id: simple(:id), text: simple(:text)) do
39
36
  Model::TextElement.new(
40
37
  content: text.to_s,
41
- id: id.to_s,
42
- source_line: Transformer::SourceLineExtractor.extract(id)
38
+ id: id.to_s
43
39
  )
44
40
  end
45
41
 
46
42
  rule(text: sequence(:text)) do
47
43
  Model::TextElement.new(
48
- content: text,
49
- source_line: Transformer::SourceLineExtractor.extract(text)
44
+ content: text
50
45
  )
51
46
  end
52
47
 
@@ -58,8 +53,7 @@ module Coradoc
58
53
  Model::TextElement.new(
59
54
  content: text.to_s,
60
55
  id: id.to_s,
61
- line_break: line_break,
62
- source_line: Transformer::SourceLineExtractor.extract(id)
56
+ line_break: line_break
63
57
  )
64
58
  end
65
59
 
@@ -71,16 +65,14 @@ module Coradoc
71
65
  Model::TextElement.new(
72
66
  content: text,
73
67
  id: id.to_s,
74
- line_break: line_break,
75
- source_line: Transformer::SourceLineExtractor.extract(id)
68
+ line_break: line_break
76
69
  )
77
70
  end
78
71
 
79
72
  # Line break
80
73
  rule(line_break: simple(:line_break)) do
81
74
  Model::LineBreak.new(
82
- line_break:,
83
- source_line: Transformer::SourceLineExtractor.extract(line_break)
75
+ line_break:
84
76
  )
85
77
  end
86
78
 
@@ -95,8 +87,7 @@ module Coradoc
95
87
  content: Transformer.lines_to_text_elements(paragraph[:lines]),
96
88
  id: paragraph[:id],
97
89
  attributes: paragraph[:attribute_list],
98
- title: paragraph[:title],
99
- source_line: Transformer::SourceLineExtractor.extract(paragraph)
90
+ title: paragraph[:title]
100
91
  )
101
92
  end
102
93
  end
@@ -142,8 +142,7 @@ module Coradoc
142
142
 
143
143
  Model::TextElement.new(
144
144
  content: transformed,
145
- line_break: line[:line_break],
146
- source_line: SourceLineExtractor.extract(line)
145
+ line_break: line[:line_break]
147
146
  )
148
147
  end
149
148
  end
@@ -153,6 +152,31 @@ module Coradoc
153
152
  def self.legacy_transform(syntax_tree)
154
153
  new.apply(syntax_tree)
155
154
  end
155
+
156
+ # Single deepening seam for source_line propagation. Parslet's
157
+ # transform pipeline funnels every rule block through
158
+ # +call_on_match(bindings, block)+; overriding it lets us post-
159
+ # process the block's result and inject +source_line+ from the
160
+ # matched bindings, so individual rules no longer need to call
161
+ # SourceLineExtractor.extract themselves (DRY — was 47 call
162
+ # sites across 7 rule files).
163
+ #
164
+ # Safety:
165
+ # * Only Model::Base results get an injection — Strings, Arrays,
166
+ # and intermediate hashes pass through unchanged.
167
+ # * Existing explicit source_line values are preserved — the
168
+ # injection is fill-in-the-blank, never overwrite.
169
+ # * No Slice in the bindings → SourceLineExtractor returns nil,
170
+ # no injection (synthetic transformations stay clean).
171
+ def call_on_match(bindings, block)
172
+ result = super
173
+ return result unless result.is_a?(Model::Base)
174
+ return result if result.source_line
175
+
176
+ line = self.class::SourceLineExtractor.extract(bindings)
177
+ result.source_line = line if line
178
+ result
179
+ end
156
180
  end
157
181
  end
158
182
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Coradoc
4
4
  module AsciiDoc
5
- VERSION = '2.0.24'
5
+ VERSION = '2.0.25'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coradoc-adoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.24
4
+ version: 2.0.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.