coradoc 2.0.1 → 2.0.3

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +77 -146
  3. data/coradoc-adoc/lib/coradoc/asciidoc/model/base.rb +4 -3
  4. data/coradoc-adoc/lib/coradoc/asciidoc/model/document.rb +1 -1
  5. data/coradoc-adoc/lib/coradoc/asciidoc/model/include.rb +1 -1
  6. data/coradoc-adoc/lib/coradoc/asciidoc/model/resolver.rb +2 -2
  7. data/coradoc-adoc/lib/coradoc/asciidoc/model/serialization/asciidoc_transform.rb +3 -3
  8. data/coradoc-adoc/lib/coradoc/asciidoc/model/table_row.rb +1 -1
  9. data/coradoc-adoc/lib/coradoc/asciidoc/model/text_element.rb +4 -8
  10. data/coradoc-adoc/lib/coradoc/asciidoc/parse_error.rb +6 -6
  11. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/adoc_serializer.rb +5 -10
  12. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/formatter.rb +4 -3
  13. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/base.rb +8 -20
  14. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/block/core.rb +1 -1
  15. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/document.rb +3 -6
  16. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/inline/strikethrough.rb +1 -1
  17. data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/list/item.rb +5 -9
  18. data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model.rb +26 -34
  19. data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model_registrations.rb +18 -18
  20. data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model.rb +96 -123
  21. data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model_registrations.rb +10 -6
  22. data/coradoc-adoc/lib/coradoc/asciidoc/transformer/header_rules.rb +5 -5
  23. data/coradoc-adoc/lib/coradoc/asciidoc/transformer/list_rules.rb +2 -2
  24. data/coradoc-adoc/lib/coradoc/asciidoc/transformer/structural_rules.rb +1 -1
  25. data/coradoc-adoc/lib/coradoc/asciidoc/transformer.rb +5 -5
  26. data/coradoc-adoc/lib/coradoc/asciidoc.rb +1 -1
  27. data/coradoc-adoc/lib/coradoc/util/asciidoc.rb +4 -3
  28. data/coradoc-adoc/spec/coradoc/asciidoc/transform/from_core_model_spec.rb +4 -2
  29. data/coradoc-docx/lib/coradoc/docx/transform/context.rb +1 -1
  30. data/coradoc-docx/lib/coradoc/docx/transform/from_core_model.rb +13 -6
  31. data/coradoc-docx/lib/coradoc/docx/transform/numbering_resolver.rb +9 -7
  32. data/coradoc-docx/lib/coradoc/docx/transform/ordered_content.rb +2 -2
  33. data/coradoc-docx/lib/coradoc/docx/transform/rules/image_rule.rb +4 -1
  34. data/coradoc-docx/lib/coradoc/docx/transform/rules/math_rule.rb +2 -1
  35. data/coradoc-docx/lib/coradoc/docx/transform/rules/run_rule.rb +20 -30
  36. data/coradoc-docx/lib/coradoc/docx/transform/rules/simple_field_rule.rb +7 -5
  37. data/coradoc-docx/lib/coradoc/docx/transform/rules/table_rule.rb +3 -5
  38. data/coradoc-docx/lib/coradoc/docx/transform/style_resolver.rb +19 -24
  39. data/coradoc-docx/lib/coradoc/docx/transform/to_core_model.rb +18 -11
  40. data/coradoc-docx/lib/coradoc/docx.rb +6 -4
  41. data/coradoc-docx/spec/coradoc/docx/transform/from_core_model_spec.rb +5 -2
  42. data/coradoc-docx/spec/coradoc/docx/transform/rules/rule_unit_spec.rb +27 -7
  43. data/coradoc-docx/spec/coradoc/docx/transform/to_core_model_spec.rb +6 -2
  44. data/coradoc-html/lib/coradoc/html/base.rb +3 -7
  45. data/coradoc-html/lib/coradoc/html/converter_base.rb +5 -15
  46. data/coradoc-html/lib/coradoc/html/converters/base.rb +22 -28
  47. data/coradoc-html/lib/coradoc/html/converters/comment_line.rb +2 -2
  48. data/coradoc-html/lib/coradoc/html/converters/link.rb +1 -1
  49. data/coradoc-html/lib/coradoc/html/converters/list_item.rb +3 -3
  50. data/coradoc-html/lib/coradoc/html/converters/ordered.rb +1 -1
  51. data/coradoc-html/lib/coradoc/html/converters/span.rb +2 -2
  52. data/coradoc-html/lib/coradoc/html/converters/table.rb +3 -3
  53. data/coradoc-html/lib/coradoc/html/converters/table_cell.rb +14 -28
  54. data/coradoc-html/lib/coradoc/html/converters/table_row.rb +2 -2
  55. data/coradoc-html/lib/coradoc/html/converters/text_element.rb +1 -5
  56. data/coradoc-html/lib/coradoc/html/input/converters/a.rb +2 -2
  57. data/coradoc-html/lib/coradoc/html/input/converters/dl.rb +1 -1
  58. data/coradoc-html/lib/coradoc/html/input/converters/figure.rb +2 -2
  59. data/coradoc-html/lib/coradoc/html/input/converters/markup.rb +3 -3
  60. data/coradoc-html/lib/coradoc/html/input/converters/p.rb +1 -1
  61. data/coradoc-html/lib/coradoc/html/input/converters/td.rb +1 -1
  62. data/coradoc-html/lib/coradoc/html/input/converters.rb +1 -2
  63. data/coradoc-html/lib/coradoc/html/input/html_converter.rb +3 -3
  64. data/coradoc-html/lib/coradoc/html/input/plugin.rb +2 -2
  65. data/coradoc-html/lib/coradoc/html/renderer.rb +4 -6
  66. data/coradoc-html/lib/coradoc/html/theme/base.rb +2 -3
  67. data/coradoc-html/lib/coradoc/html/theme/classic_renderer.rb +9 -12
  68. data/coradoc-html/lib/coradoc/html/theme/modern/serializers/document_serializer.rb +3 -3
  69. data/coradoc-html/lib/coradoc/html.rb +1 -1
  70. data/coradoc-markdown/lib/coradoc/markdown/model/base.rb +6 -5
  71. data/coradoc-markdown/lib/coradoc/markdown/serializer.rb +2 -2
  72. data/coradoc-markdown/lib/coradoc/markdown/toc_generator.rb +4 -5
  73. data/coradoc-markdown/lib/coradoc/markdown/transform/from_core_model.rb +2 -2
  74. data/coradoc-markdown/lib/coradoc/markdown/transformer.rb +5 -3
  75. data/coradoc-markdown/lib/coradoc/markdown.rb +1 -1
  76. data/lib/coradoc/configurable.rb +6 -2
  77. data/lib/coradoc/coradoc.rb +18 -16
  78. data/lib/coradoc/core_model/base.rb +3 -3
  79. data/lib/coradoc/core_model/list_item.rb +3 -3
  80. data/lib/coradoc/core_model/toc_generator.rb +1 -1
  81. data/lib/coradoc/document_manipulator.rb +9 -13
  82. data/lib/coradoc/format_module.rb +16 -4
  83. data/lib/coradoc/input.rb +1 -1
  84. data/lib/coradoc/output.rb +1 -1
  85. data/lib/coradoc/query.rb +38 -186
  86. data/lib/coradoc/registry.rb +5 -7
  87. data/lib/coradoc/serializer/registry.rb +3 -5
  88. data/lib/coradoc/validation.rb +40 -21
  89. data/lib/coradoc/version.rb +1 -1
  90. metadata +1 -1
@@ -67,6 +67,7 @@ module Coradoc
67
67
  # @param options [Hash] optional configuration (e.g., extensions: [])
68
68
  # @return [void]
69
69
  def register_format(format_name, format_module, **options)
70
+ format_module.extend(FormatModule::Interface) unless format_module.is_a?(FormatModule::Interface)
70
71
  registry.register(format_name, format_module, options)
71
72
  FormatModule.validate!(format_module, format_name)
72
73
  end
@@ -148,7 +149,7 @@ module Coradoc
148
149
  return model if model.is_a?(CoreModel::Base)
149
150
 
150
151
  registry.each_value do |format_module|
151
- next unless format_module.respond_to?(:handles_model?) && format_module.handles_model?(model)
152
+ next unless format_module.handles_model?(model)
152
153
 
153
154
  return format_module.to_core(model)
154
155
  end
@@ -195,7 +196,7 @@ module Coradoc
195
196
  # Coradoc.detect_format("file.md") # => :markdown
196
197
  def detect_format(filename)
197
198
  ext = File.extname(filename).downcase
198
- registry.each do |name, _mod|
199
+ registry.each_key do |name|
199
200
  opts = registry.options_for(name)
200
201
  return name if opts[:extensions]&.include?(ext)
201
202
  end
@@ -243,7 +244,7 @@ module Coradoc
243
244
  # @example
244
245
  # html = Coradoc.convert_file("document.adoc", to: :html)
245
246
  # adoc = Coradoc.convert_file("report.docx", to: :asciidoc)
246
- def convert_file(path, from: nil, to:, **options)
247
+ def convert_file(path, to:, from: nil, **options)
247
248
  source_format = from || detect_format(path)
248
249
  raise UnsupportedFormatError, "Could not detect format for: #{path}" unless source_format
249
250
 
@@ -270,7 +271,7 @@ module Coradoc
270
271
  return nil unless name
271
272
 
272
273
  key = name.to_s.downcase
273
- registry.each do |fmt_name, _mod|
274
+ registry.each_key do |fmt_name|
274
275
  opts = registry.options_for(fmt_name)
275
276
  return fmt_name if opts[:aliases]&.include?(key)
276
277
  end
@@ -285,9 +286,7 @@ module Coradoc
285
286
  mod = get_format(format)
286
287
  return false unless mod
287
288
 
288
- return mod.serialize? if mod.respond_to?(:serialize?)
289
-
290
- true
289
+ mod.serialize?
291
290
  end
292
291
 
293
292
  # Check if a format supports parsing (reading input)
@@ -296,7 +295,9 @@ module Coradoc
296
295
  # @return [Boolean] true if the format can parse
297
296
  def parse_format?(format)
298
297
  mod = get_format(format)
299
- mod&.respond_to?(:parse_to_core) || mod&.respond_to?(:parse) || false
298
+ return false unless mod
299
+
300
+ mod.public_methods.include?(:parse_to_core) || mod.public_methods.include?(:parse)
300
301
  end
301
302
 
302
303
  # Get capability summary for all registered formats
@@ -361,9 +362,9 @@ module Coradoc
361
362
  def document_stats(doc)
362
363
  stats = {}
363
364
 
364
- stats[:title] = doc.title if doc.respond_to?(:title) && doc.title
365
+ stats[:title] = doc.title if doc.title
365
366
 
366
- if doc.respond_to?(:children)
367
+ if doc.is_a?(CoreModel::StructuralElement)
367
368
  stats[:child_count] = count_elements(doc)
368
369
  stats[:element_counts] = count_element_types(doc)
369
370
  end
@@ -379,9 +380,9 @@ module Coradoc
379
380
  return elem.to_s unless elem.is_a?(CoreModel::Base)
380
381
 
381
382
  type = elem.class.name.split('::').last
382
- if elem.respond_to?(:title) && elem.title
383
+ if elem.title
383
384
  "#{type}: #{elem.title}"
384
- elsif elem.respond_to?(:content) && elem.content
385
+ elsif elem.is_a?(CoreModel::Block) && elem.content
385
386
  preview = elem.content.to_s[0..50]
386
387
  preview += '...' if elem.content.to_s.length > 50
387
388
  "#{type}: #{preview}"
@@ -411,10 +412,10 @@ module Coradoc
411
412
  private
412
413
 
413
414
  def count_elements(doc)
414
- return 0 unless doc.respond_to?(:children)
415
+ return 0 unless doc.is_a?(CoreModel::StructuralElement)
415
416
 
416
417
  doc.children.sum do |child|
417
- 1 + (child.respond_to?(:children) ? count_elements(child) : 0)
418
+ 1 + (child.is_a?(CoreModel::StructuralElement) ? count_elements(child) : 0)
418
419
  end
419
420
  end
420
421
 
@@ -423,11 +424,12 @@ module Coradoc
423
424
  visitor = Class.new(Visitor::Base) do
424
425
  define_method(:visit) do |element|
425
426
  if element.is_a?(CoreModel::Base)
426
- type_key = if element.respond_to?(:element_type) && element.element_type
427
+ has_element_type = element.is_a?(CoreModel::StructuralElement) || element.is_a?(CoreModel::Block)
428
+ type_key = if has_element_type && element.element_type
427
429
  element.element_type
428
430
  else
429
431
  element.class.name.split('::').last
430
- .gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
432
+ .gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
431
433
  end
432
434
  counts[type_key] += 1
433
435
  end
@@ -136,7 +136,7 @@ module Coradoc
136
136
  children_arr.map do |child|
137
137
  if child.is_a?(String)
138
138
  child
139
- elsif child.respond_to?(:to_hash)
139
+ elsif child.is_a?(Lutaml::Model::Serializable)
140
140
  child.to_hash
141
141
  else
142
142
  child.to_s
@@ -156,8 +156,8 @@ module Coradoc
156
156
 
157
157
  # Compare a single attribute between this model and another
158
158
  def compare_attribute(attr, other)
159
- self_value = send(attr)
160
- other_value = other.send(attr)
159
+ self_value = public_send(attr)
160
+ other_value = other.public_send(attr)
161
161
 
162
162
  case self_value
163
163
  when Array
@@ -45,13 +45,13 @@ module Coradoc
45
45
 
46
46
  # Delegate nested to nested_list (lutaml attribute added by list_block.rb)
47
47
  def nested
48
- nested_list if respond_to?(:nested_list)
48
+ nested_list
49
49
  end
50
50
 
51
51
  # Set nested list
52
52
  # @param value [ListBlock, nil] nested list block
53
53
  def nested=(value)
54
- self.nested_list = value if respond_to?(:nested_list=)
54
+ self.nested_list = value
55
55
  end
56
56
 
57
57
  # Convert to hash representation
@@ -62,7 +62,7 @@ module Coradoc
62
62
  marker: marker,
63
63
  content: content,
64
64
  nested_list: nested&.to_h,
65
- children: children&.map { |child| child.respond_to?(:to_h) ? child.to_h : child }
65
+ children: children&.map { |child| child.is_a?(CoreModel::Base) ? child.to_h : child }
66
66
  }.compact
67
67
  end
68
68
 
@@ -71,7 +71,7 @@ module Coradoc
71
71
  # Find all sections in the document within level range
72
72
  def find_sections(element, min_level, max_level)
73
73
  sections = []
74
- return sections unless element.respond_to?(:children)
74
+ return sections unless element.is_a?(CoreModel::StructuralElement)
75
75
 
76
76
  Array(element.children).each do |child|
77
77
  next unless child.is_a?(CoreModel::StructuralElement)
@@ -22,7 +22,7 @@ module Coradoc
22
22
  DocumentManipulator.new(filtered)
23
23
  end
24
24
 
25
- def transform_text(&block)
25
+ def transform_text
26
26
  return self unless block_given?
27
27
 
28
28
  Visitor::Transformer.new do |element|
@@ -36,13 +36,11 @@ module Coradoc
36
36
  self
37
37
  end
38
38
 
39
- def transform_headings(&block)
39
+ def transform_headings
40
40
  return self unless block_given?
41
41
 
42
42
  Visitor::Transformer.new do |element|
43
- if element.is_a?(CoreModel::StructuralElement) && element.title.is_a?(String)
44
- element.title = yield(element.title)
45
- end
43
+ element.title = yield(element.title) if element.is_a?(CoreModel::StructuralElement) && element.title.is_a?(String)
46
44
  end.visit(@document)
47
45
  self
48
46
  end
@@ -64,7 +62,7 @@ module Coradoc
64
62
 
65
63
  def remove_elements(element_type)
66
64
  Visitor::Transformer.new do |element|
67
- next unless element.respond_to?(:children) && element.children
65
+ next unless element.is_a?(CoreModel::StructuralElement) && element.children
68
66
 
69
67
  element.children.reject! do |child|
70
68
  match_element_type?(child, element_type)
@@ -128,15 +126,13 @@ module Coradoc
128
126
  end
129
127
 
130
128
  def filter_sections(element, level: nil, title: nil)
131
- if element.respond_to?(:children) && element.children
129
+ if element.is_a?(CoreModel::StructuralElement) && element.children
132
130
  element.children = element.children
133
131
  .map { |child| filter_sections(child, level: level, title: title) }
134
132
  .compact
135
133
  end
136
134
 
137
- if element.is_a?(CoreModel::StructuralElement) && element.section? && !element.document?
138
- return nil unless section_matches?(element, level: level, title: title)
139
- end
135
+ return nil if element.is_a?(CoreModel::StructuralElement) && element.section? && !element.document? && !section_matches?(element, level: level, title: title)
140
136
 
141
137
  element
142
138
  end
@@ -154,7 +150,7 @@ module Coradoc
154
150
  element_title = section.title || ''
155
151
  case title
156
152
  when String then return false unless element_title.include?(title)
157
- when Regexp then return false unless element_title =~ title
153
+ when Regexp then return false unless element_title&.match?(title)
158
154
  end
159
155
  end
160
156
 
@@ -163,7 +159,7 @@ module Coradoc
163
159
 
164
160
  def collect_sections(element, max_level: 3, current_level: 1)
165
161
  sections = []
166
- return sections unless element.respond_to?(:children)
162
+ return sections unless element.is_a?(CoreModel::StructuralElement)
167
163
 
168
164
  element.children.each do |child|
169
165
  next unless child.is_a?(CoreModel::StructuralElement) &&
@@ -186,7 +182,7 @@ module Coradoc
186
182
  when CoreModel::Base
187
183
  cloned = element.class.new
188
184
  element.class.attributes.each_key do |name|
189
- cloned.send("#{name}=", deep_clone(element.send(name)))
185
+ cloned.public_send("#{name}=", deep_clone(element.public_send(name)))
190
186
  end
191
187
  cloned
192
188
  when Array
@@ -19,17 +19,29 @@ module Coradoc
19
19
  MINIMUM_PARSE_METHODS = %i[parse_to_core parse].freeze
20
20
  REQUIRED_METHODS = %i[serialize].freeze
21
21
 
22
+ # Default implementations for optional format module methods.
23
+ # Format modules are auto-extended with this during registration.
24
+ module Interface
25
+ def handles_model?(_model)
26
+ false
27
+ end
28
+
29
+ def serialize?
30
+ true
31
+ end
32
+ end
33
+
22
34
  # Validate that a format module implements the minimum interface.
23
35
  # Warns to $stderr if methods are missing. Returns true if valid.
24
36
  def self.validate!(format_module, format_name)
25
- has_parse = MINIMUM_PARSE_METHODS.any? { |m| format_module.respond_to?(m) }
26
- has_serialize = REQUIRED_METHODS.all? { |m| format_module.respond_to?(m) }
37
+ has_parse = MINIMUM_PARSE_METHODS.any? { |m| format_module.public_methods.include?(m) }
38
+ has_serialize = REQUIRED_METHODS.all? { |m| format_module.public_methods.include?(m) }
27
39
 
28
40
  return true if has_parse && has_serialize
29
41
 
30
42
  missing = []
31
- missing << "parse_to_core or parse" unless has_parse
32
- missing << "serialize" unless has_serialize
43
+ missing << 'parse_to_core or parse' unless has_parse
44
+ missing << 'serialize' unless has_serialize
33
45
  warn "Coradoc: format :#{format_name} (#{format_module}) missing: #{missing.join(', ')}"
34
46
  false
35
47
  end
data/lib/coradoc/input.rb CHANGED
@@ -17,6 +17,6 @@ module Coradoc
17
17
  #
18
18
  module Input
19
19
  extend ProcessorRegistry
20
- self.error_label = "input processor"
20
+ self.error_label = 'input processor'
21
21
  end
22
22
  end
@@ -17,6 +17,6 @@ module Coradoc
17
17
  #
18
18
  module Output
19
19
  extend ProcessorRegistry
20
- self.error_label = "output processor"
20
+ self.error_label = 'output processor'
21
21
  end
22
22
  end