coradoc 2.0.2 → 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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +48 -5
  3. data/coradoc-docx/lib/coradoc/docx/transform/context.rb +1 -1
  4. data/coradoc-docx/lib/coradoc/docx/transform/from_core_model.rb +13 -6
  5. data/coradoc-docx/lib/coradoc/docx/transform/numbering_resolver.rb +9 -7
  6. data/coradoc-docx/lib/coradoc/docx/transform/ordered_content.rb +2 -2
  7. data/coradoc-docx/lib/coradoc/docx/transform/rules/image_rule.rb +4 -1
  8. data/coradoc-docx/lib/coradoc/docx/transform/rules/math_rule.rb +2 -1
  9. data/coradoc-docx/lib/coradoc/docx/transform/rules/run_rule.rb +17 -30
  10. data/coradoc-docx/lib/coradoc/docx/transform/rules/simple_field_rule.rb +3 -5
  11. data/coradoc-docx/lib/coradoc/docx/transform/rules/table_rule.rb +3 -4
  12. data/coradoc-docx/lib/coradoc/docx/transform/style_resolver.rb +19 -24
  13. data/coradoc-docx/lib/coradoc/docx/transform/to_core_model.rb +18 -11
  14. data/coradoc-html/lib/coradoc/html/base.rb +3 -7
  15. data/coradoc-html/lib/coradoc/html/converter_base.rb +5 -15
  16. data/coradoc-html/lib/coradoc/html/converters/base.rb +18 -27
  17. data/coradoc-html/lib/coradoc/html/converters/comment_line.rb +2 -2
  18. data/coradoc-html/lib/coradoc/html/converters/link.rb +1 -1
  19. data/coradoc-html/lib/coradoc/html/converters/list_item.rb +3 -3
  20. data/coradoc-html/lib/coradoc/html/converters/ordered.rb +1 -1
  21. data/coradoc-html/lib/coradoc/html/converters/span.rb +2 -2
  22. data/coradoc-html/lib/coradoc/html/converters/table.rb +3 -3
  23. data/coradoc-html/lib/coradoc/html/converters/table_cell.rb +14 -28
  24. data/coradoc-html/lib/coradoc/html/converters/table_row.rb +2 -2
  25. data/coradoc-html/lib/coradoc/html/converters/text_element.rb +1 -5
  26. data/coradoc-html/lib/coradoc/html/input/converters/a.rb +2 -2
  27. data/coradoc-html/lib/coradoc/html/input/converters/dl.rb +1 -1
  28. data/coradoc-html/lib/coradoc/html/input/converters/figure.rb +2 -2
  29. data/coradoc-html/lib/coradoc/html/input/converters/markup.rb +3 -3
  30. data/coradoc-html/lib/coradoc/html/input/converters/p.rb +1 -1
  31. data/coradoc-html/lib/coradoc/html/input/converters/td.rb +1 -1
  32. data/coradoc-html/lib/coradoc/html/input/converters.rb +1 -2
  33. data/coradoc-html/lib/coradoc/html/input/html_converter.rb +3 -3
  34. data/coradoc-html/lib/coradoc/html/input/plugin.rb +2 -2
  35. data/coradoc-html/lib/coradoc/html/renderer.rb +4 -6
  36. data/coradoc-html/lib/coradoc/html/theme/base.rb +2 -3
  37. data/coradoc-html/lib/coradoc/html/theme/classic_renderer.rb +9 -12
  38. data/coradoc-html/lib/coradoc/html/theme/modern/serializers/document_serializer.rb +3 -3
  39. data/coradoc-markdown/lib/coradoc/markdown/model/base.rb +6 -5
  40. data/coradoc-markdown/lib/coradoc/markdown/serializer.rb +2 -2
  41. data/coradoc-markdown/lib/coradoc/markdown/toc_generator.rb +4 -5
  42. data/coradoc-markdown/lib/coradoc/markdown/transformer.rb +5 -3
  43. data/lib/coradoc/version.rb +1 -1
  44. metadata +1 -1
@@ -118,25 +118,19 @@ module Coradoc
118
118
  # @param config [Hash, Object] Configuration options or object
119
119
  # @return [Object] Built configuration object
120
120
  def build_config(config)
121
- # If config is already a Configuration object, validate and return it
122
- if config.respond_to?(:validate!)
123
- config.validate! if config.respond_to?(:validate!)
121
+ if config.public_methods.include?(:validate!)
122
+ config.validate!
124
123
  return config
125
124
  end
126
125
 
127
- # Otherwise, build from hash (subclasses should override this)
128
126
  config
129
127
  end
130
128
 
131
- # Extract document title
132
- #
133
- # @return [String] Document title
134
129
  def extract_document_title
135
- # Handle CoreModel::StructuralElement (has title directly)
136
- if @document.respond_to?(:title) && @document.title
130
+ if @document.is_a?(Coradoc::CoreModel::StructuralElement) && @document.title
137
131
  title = @document.title
138
132
  return title if title.is_a?(String)
139
- return title.text if title.respond_to?(:text)
133
+ return title.text if title.is_a?(Coradoc::CoreModel::Base) && title.text
140
134
 
141
135
  return title.to_s
142
136
  end
@@ -144,10 +138,6 @@ module Coradoc
144
138
  'Untitled Document'
145
139
  end
146
140
 
147
- # Extract text from content (array of inline elements)
148
- #
149
- # @param content [Array] Content elements
150
- # @return [String] Extracted text
151
141
  def extract_text_from_content(content)
152
142
  case content
153
143
  when Array
@@ -157,7 +147,7 @@ module Coradoc
157
147
  when Coradoc::CoreModel::InlineElement
158
148
  content.content.to_s
159
149
  when Coradoc::CoreModel::Base
160
- if content.respond_to?(:content)
150
+ if content.content
161
151
  extract_text_from_content(content.content)
162
152
  else
163
153
  content.to_s
@@ -434,37 +434,28 @@ module Coradoc
434
434
 
435
435
  # Extract text from unknown model types as a fallback
436
436
  def extract_text_fallback(content)
437
- # Try text attribute first
438
- if content.respond_to?(:text) && content.text
439
- text_val = content.text
440
- return text_val if text_val.is_a?(String)
441
- return text_val.to_s if text_val.respond_to?(:to_s)
442
- end
437
+ if content.is_a?(Coradoc::CoreModel::Base)
438
+ if content.class.attributes.key?(:text) && content.text
439
+ text_val = content.text
440
+ return text_val if text_val.is_a?(String)
443
441
 
444
- # Try content attribute
445
- if content.respond_to?(:content) && content.content
446
- content_val = content.content
447
- if content_val.is_a?(String)
448
- return content_val
449
- elsif content_val.is_a?(Array)
450
- return content_val.map { |item| convert_content_to_html(item, {}) }.join
442
+ return text_val.to_s
451
443
  end
452
- end
453
-
454
- # Try href attribute (for cross-references)
455
- return content.href.to_s if content.respond_to?(:href) && content.href
456
444
 
457
- # Try term attribute (for term references)
458
- return content.term.to_s if content.respond_to?(:term) && content.term
459
-
460
- # Try id attribute (for references with IDs)
461
- return content.id.to_s if content.respond_to?(:id) && content.id
462
-
463
- # Try name attribute
464
- return content.name.to_s if content.respond_to?(:name) && content.name
445
+ if content.class.attributes.key?(:content) && content.content
446
+ content_val = content.content
447
+ if content_val.is_a?(String)
448
+ return content_val
449
+ elsif content_val.is_a?(Array)
450
+ return content_val.map { |item| convert_content_to_html(item, {}) }.join
451
+ end
452
+ end
465
453
 
466
- # Try to_adoc if available (for AsciiDoc models)
467
- return content.to_adoc.to_s if content.respond_to?(:to_adoc)
454
+ return content.href.to_s if content.class.attributes.key?(:href) && content.href
455
+ return content.term.to_s if content.class.attributes.key?(:term) && content.term
456
+ return content.id.to_s if content.class.attributes.key?(:id) && content.id
457
+ return content.name.to_s if content.class.attributes.key?(:name) && content.name
458
+ end
468
459
 
469
460
  ''
470
461
  end
@@ -12,9 +12,9 @@ module Coradoc
12
12
  return '' unless options[:preserve_comments]
13
13
 
14
14
  # Get comment text - check for content or text attribute
15
- text = if comment.respond_to?(:content) && comment.content
15
+ text = if comment.content
16
16
  comment.content
17
- elsif comment.respond_to?(:text) && comment.text
17
+ elsif comment.text
18
18
  comment.text
19
19
  else
20
20
  ''
@@ -11,7 +11,7 @@ module Coradoc
11
11
  attrs[:id] = model.id if model.id
12
12
 
13
13
  # Get title from metadata
14
- if model.respond_to?(:metadata) && model.metadata && model.metadata[:title]
14
+ if model.metadata && model.metadata[:title]
15
15
  attrs[:title] =
16
16
  model.metadata[:title]
17
17
  end
@@ -50,18 +50,18 @@ module Coradoc
50
50
  parts = []
51
51
 
52
52
  # Convert main content - check children first (mixed content), then content
53
- content_to_render = model.respond_to?(:children) && model.children&.any? ? model.children : model.content
53
+ content_to_render = model.children&.any? ? model.children : model.content
54
54
  parts << convert_content_to_html(content_to_render, state) if content_to_render
55
55
 
56
56
  # Convert attached content
57
- if model.respond_to?(:attached) && model.attached && !model.attached.empty?
57
+ if model.attached && !model.attached.empty?
58
58
  model.attached.each do |attached_item|
59
59
  parts << convert_content_to_html(attached_item, state)
60
60
  end
61
61
  end
62
62
 
63
63
  # Convert nested list
64
- parts << convert_content_to_html(model.nested, state) if model.respond_to?(:nested) && model.nested
64
+ parts << convert_content_to_html(model.nested, state) if model.nested
65
65
 
66
66
  attrs = {}
67
67
  attrs[:id] = model.id if model.id
@@ -42,7 +42,7 @@ module Coradoc
42
42
  attrs[:id] = model.id if model.id
43
43
 
44
44
  # Add start attribute if not starting from 1
45
- attrs[:start] = model.start if model.respond_to?(:start) && model.start && model.start != 1
45
+ attrs[:start] = model.start if model.start && model.start != 1
46
46
 
47
47
  build_element('ol', "\n#{items_html}\n", attrs)
48
48
  end
@@ -39,7 +39,7 @@ module Coradoc
39
39
  # @return [String] HTML string
40
40
  def to_html(model, state = {})
41
41
  # Prefer children for mixed content, fall back to content
42
- content = if model.respond_to?(:children) && model.children&.any?
42
+ content = if model.children&.any?
43
43
  model.children.map { |c| convert_content_to_html(c, state) }.join
44
44
  else
45
45
  escape_html(model.content || '')
@@ -47,7 +47,7 @@ module Coradoc
47
47
 
48
48
  # Build attributes from metadata
49
49
  attrs = {}
50
- if model.respond_to?(:metadata) && model.metadata && model.metadata[:class]
50
+ if model.metadata && model.metadata[:class]
51
51
  attrs[:class] =
52
52
  model.metadata[:class]
53
53
  end
@@ -48,16 +48,16 @@ module Coradoc
48
48
  attrs = []
49
49
 
50
50
  # Add ID if present
51
- attrs << %( id="#{escape_attribute(table.id)}") if table.respond_to?(:id) && table.id
51
+ attrs << %( id="#{escape_attribute(table.id)}") if table.id
52
52
 
53
53
  # CoreModel::Table with frame attribute
54
- attrs << %( class="frame-#{escape_attribute(table.frame)}") if table.respond_to?(:frame) && table.frame
54
+ attrs << %( class="frame-#{escape_attribute(table.frame)}") if table.frame
55
55
 
56
56
  attrs.join
57
57
  end
58
58
 
59
59
  def self.build_caption(table)
60
- return nil unless table.respond_to?(:title) && table.title
60
+ return nil unless table.title
61
61
 
62
62
  caption_text = table.title.to_s
63
63
  return nil if caption_text.empty?
@@ -13,7 +13,7 @@ module Coradoc
13
13
  return '' unless cell
14
14
 
15
15
  # Check if this is a header cell
16
- is_header = cell.respond_to?(:header) && cell.header == true
16
+ is_header = cell.header == true
17
17
  tag = is_header ? 'th' : 'td'
18
18
 
19
19
  # Build cell attributes
@@ -52,33 +52,19 @@ module Coradoc
52
52
  def self.build_attributes(cell)
53
53
  attrs = []
54
54
 
55
- # Add ID if present
56
- attrs << %( id="#{escape_attribute(cell.id)}") if cell.respond_to?(:id) && cell.id
55
+ attrs << %( id="#{escape_attribute(cell.id)}") if cell.id
57
56
 
58
- # Colspan and rowspan
59
- attrs << %( colspan="#{cell.colspan}") if cell.respond_to?(:colspan) && cell.colspan
60
- attrs << %( rowspan="#{cell.rowspan}") if cell.respond_to?(:rowspan) && cell.rowspan
57
+ attrs << %( colspan="#{cell.colspan}") if cell.colspan
58
+ attrs << %( rowspan="#{cell.rowspan}") if cell.rowspan
61
59
 
62
- # Build style attribute for alignment, colors, etc.
63
60
  style_parts = []
64
61
 
65
- # Horizontal alignment
66
- style_parts << "text-align: #{escape_attribute(cell.alignment)}" if cell.respond_to?(:alignment) && cell.alignment
67
-
68
- # Vertical alignment
69
- style_parts << "vertical-align: #{escape_attribute(cell.vertical_alignment)}" if cell.respond_to?(:vertical_alignment) && cell.vertical_alignment
70
-
71
- # Background color
72
- style_parts << "background-color: #{escape_attribute(cell.bgcolor)}" if cell.respond_to?(:bgcolor) && cell.bgcolor
73
-
74
- # Text color
75
- style_parts << "color: #{escape_attribute(cell.color)}" if cell.respond_to?(:color) && cell.color
76
-
77
- # Width
78
- style_parts << "width: #{escape_attribute(cell.width)}" if cell.respond_to?(:width) && cell.width
79
-
80
- # Height
81
- style_parts << "height: #{escape_attribute(cell.height)}" if cell.respond_to?(:height) && cell.height
62
+ style_parts << "text-align: #{escape_attribute(cell.alignment)}" if cell.alignment
63
+ style_parts << "vertical-align: #{escape_attribute(cell.vertical_alignment)}" if cell.vertical_alignment
64
+ style_parts << "background-color: #{escape_attribute(cell.bgcolor)}" if cell.bgcolor
65
+ style_parts << "color: #{escape_attribute(cell.color)}" if cell.color
66
+ style_parts << "width: #{escape_attribute(cell.width)}" if cell.width
67
+ style_parts << "height: #{escape_attribute(cell.height)}" if cell.height
82
68
 
83
69
  # Add style attribute if we have any styles
84
70
  attrs << %( style="#{style_parts.join('; ')}") if style_parts.any?
@@ -88,7 +74,7 @@ module Coradoc
88
74
 
89
75
  # Wrap content with style tags based on cell style
90
76
  def self.wrap_with_style(content, cell)
91
- return content unless cell.respond_to?(:style) && cell.style
77
+ return content unless cell.style
92
78
 
93
79
  case cell.style.to_s.downcase
94
80
  when 'strong', 's'
@@ -112,11 +98,11 @@ module Coradoc
112
98
  return '' if cell.nil?
113
99
 
114
100
  # Use renderable_content if available (prefers children over content)
115
- content = if cell.respond_to?(:renderable_content)
101
+ content = if cell.renderable_content
116
102
  cell.renderable_content
117
- elsif cell.respond_to?(:children) && cell.children.any?
103
+ elsif cell.children.any?
118
104
  cell.children
119
- elsif cell.respond_to?(:content)
105
+ elsif cell.content
120
106
  cell.content
121
107
  else
122
108
  cell
@@ -9,7 +9,7 @@ module Coradoc
9
9
  return '' unless row
10
10
 
11
11
  # CoreModel::TableRow uses cells
12
- cells = row.respond_to?(:cells) ? row.cells : []
12
+ cells = row.cells || []
13
13
  columns_html = cells.map do |cell|
14
14
  TableCell.to_html(cell)
15
15
  end.join("\n")
@@ -35,7 +35,7 @@ module Coradoc
35
35
  attrs = []
36
36
 
37
37
  # Add ID if present
38
- attrs << %( id="#{escape_attribute(row.id)}") if row.respond_to?(:id) && row.id
38
+ attrs << %( id="#{escape_attribute(row.id)}") if row.id
39
39
 
40
40
  attrs.join
41
41
  end
@@ -23,11 +23,7 @@ module Coradoc
23
23
  # @return [String] Plain text (escaped)
24
24
  def to_html(model, state = {})
25
25
  # Handle both string and model with content attribute
26
- content = if model.respond_to?(:content)
27
- model.content
28
- else
29
- model
30
- end
26
+ content = model.content || model
31
27
 
32
28
  return '' if content.nil?
33
29
 
@@ -33,7 +33,7 @@ module Coradoc
33
33
  ref_id = href.sub(/^#/, '').gsub(/\s/, '').gsub(/__+/, '_')
34
34
  # Convert content to string
35
35
  content_str = if content.is_a?(Array)
36
- content.map { |c| c.respond_to?(:content) ? c.content : c.to_s }.join
36
+ content.map { |c| c.is_a?(Coradoc::CoreModel::Base) ? c.content : c.to_s }.join
37
37
  else
38
38
  content.to_s
39
39
  end
@@ -52,7 +52,7 @@ module Coradoc
52
52
 
53
53
  # Convert content to string for the link
54
54
  content_str = if content.is_a?(Array)
55
- content.map { |c| c.respond_to?(:content) ? c.content : c.to_s }.join
55
+ content.map { |c| c.is_a?(Coradoc::CoreModel::Base) && c.content ? c.content : c.to_s }.join
56
56
  else
57
57
  content.to_s
58
58
  end
@@ -87,7 +87,7 @@ module Coradoc
87
87
  when Coradoc::CoreModel::InlineElement
88
88
  item.content.to_s
89
89
  when Coradoc::CoreModel::Base
90
- if item.respond_to?(:content)
90
+ if item.content
91
91
  item.content.to_s
92
92
  else
93
93
  ''
@@ -38,9 +38,9 @@ module Coradoc
38
38
  when Coradoc::CoreModel::InlineElement
39
39
  item.content.to_s
40
40
  when Coradoc::CoreModel::Base
41
- if item.respond_to?(:content)
41
+ if item.content
42
42
  item.content.to_s
43
- elsif item.respond_to?(:title)
43
+ elsif item.title
44
44
  item.title.to_s
45
45
  else
46
46
  ''
@@ -85,11 +85,11 @@ module Coradoc
85
85
  def extract_text_from_model(model)
86
86
  return '' if model.nil?
87
87
 
88
- if model.respond_to?(:content) && model.content.is_a?(String)
88
+ if model.is_a?(Coradoc::CoreModel::Base) && model.content.is_a?(String)
89
89
  model.content
90
- elsif model.respond_to?(:children) && model.children.is_a?(Array)
90
+ elsif model.is_a?(Coradoc::CoreModel::StructuralElement) && model.children.is_a?(Array)
91
91
  model.children.map { |c| extract_text_from_model(c) }.join
92
- elsif model.respond_to?(:title) && model.title.is_a?(String)
92
+ elsif model.is_a?(Coradoc::CoreModel::Base) && model.title.is_a?(String)
93
93
  model.title
94
94
  else
95
95
  model.to_s
@@ -66,7 +66,7 @@ module Coradoc
66
66
 
67
67
  # Check if InlineElement has meaningful nested content
68
68
  def item_has_nested_content?(item)
69
- return false unless item.respond_to?(:nested_elements)
69
+ return false unless item.is_a?(Coradoc::CoreModel::InlineElement)
70
70
  return false if item.nested_elements.nil? || item.nested_elements.empty?
71
71
 
72
72
  true
@@ -50,7 +50,7 @@ module Coradoc
50
50
  when Coradoc::CoreModel::InlineElement
51
51
  item.content.to_s
52
52
  when Coradoc::CoreModel::Base
53
- if item.respond_to?(:content)
53
+ if item.content
54
54
  item.content.to_s
55
55
  else
56
56
  ''
@@ -74,8 +74,7 @@ module Coradoc
74
74
  def self.lookup(tag_name)
75
75
  ensure_converters_loaded
76
76
  converter = @@converters[tag_name.to_sym] || default_converter(tag_name)
77
- converter = converter.new if converter.respond_to? :new
78
- converter
77
+ converter.is_a?(Class) ? converter.new : converter
79
78
  end
80
79
 
81
80
  # NOTE: process won't run plugin hooks
@@ -41,7 +41,7 @@ module Coradoc
41
41
 
42
42
  plugin_instances.each do |plugin|
43
43
  plugin.html_tree = root
44
- if plugin.respond_to?(:preprocess_html_tree)
44
+ if plugin.public_methods.include?(:preprocess_html_tree)
45
45
  track_time "Preprocessing document with #{plugin.name} plugin" do
46
46
  plugin.preprocess_html_tree
47
47
  end
@@ -61,7 +61,7 @@ module Coradoc
61
61
  end
62
62
 
63
63
  plugin_instances.each do |plugin|
64
- next unless plugin.respond_to?(:postprocess_coremodel_tree)
64
+ next unless plugin.public_methods.include?(:postprocess_coremodel_tree)
65
65
 
66
66
  plugin.coremodel_tree = coremodel
67
67
  track_time "Postprocessing CoreModel tree with #{plugin.name} plugin" do
@@ -131,7 +131,7 @@ module Coradoc
131
131
  end
132
132
 
133
133
  plugin_instances.each do |plugin|
134
- next unless plugin.respond_to?(:postprocess_output_string)
134
+ next unless plugin.public_methods.include?(:postprocess_output_string)
135
135
 
136
136
  plugin.output_string = result
137
137
  track_time "Postprocessing output string with #{plugin.name} plugin" do
@@ -150,7 +150,7 @@ module Coradoc
150
150
  # @deprecated Use postprocess_coremodel_tree instead. Will be removed in v2.0.
151
151
  def postprocess_coradoc_tree
152
152
  warn '[DEPRECATION] `postprocess_coradoc_tree` is deprecated. Use `postprocess_coremodel_tree` instead.'
153
- postprocess_coremodel_tree if respond_to?(:postprocess_coremodel_tree)
153
+ postprocess_coremodel_tree if public_methods.include?(:postprocess_coremodel_tree)
154
154
  end
155
155
 
156
156
  #### Output string functionalities
@@ -161,7 +161,7 @@ module Coradoc
161
161
  # @deprecated Use postprocess_output_string instead. Will be removed in v2.0.
162
162
  def postprocess_asciidoc_string
163
163
  warn '[DEPRECATION] `postprocess_asciidoc_string` is deprecated. Use `postprocess_output_string` instead.'
164
- postprocess_output_string if respond_to?(:postprocess_output_string)
164
+ postprocess_output_string if public_methods.include?(:postprocess_output_string)
165
165
  end
166
166
  end
167
167
  end
@@ -179,22 +179,20 @@ module Coradoc
179
179
  # (lutaml-model may not create drops if Liquid was loaded after the model class)
180
180
  def ensure_drop_class(element)
181
181
  klass = element.class
182
- if klass.respond_to?(:register_class_if_liquid_defined) &&
183
- klass.respond_to?(:base_drop_class) && !klass.base_drop_class
182
+ if klass.public_methods.include?(:register_class_if_liquid_defined) &&
183
+ klass.public_methods.include?(:base_drop_class) && !klass.base_drop_class
184
184
  klass.register_class_if_liquid_defined
185
185
  end
186
186
  end
187
187
 
188
- # Ensure all CoreModel drop classes are registered
189
- # (lutaml-model only creates drops when Liquid is already loaded at class definition time)
190
188
  def ensure_core_model_drops
191
189
  return unless defined?(Coradoc::CoreModel)
192
190
 
193
191
  CoreModel.constants(false).each do |const_name|
194
192
  klass = CoreModel.const_get(const_name)
195
193
  next unless klass.is_a?(Class)
196
- next unless klass.respond_to?(:register_class_if_liquid_defined)
197
- next if klass.respond_to?(:base_drop_class) && klass.base_drop_class
194
+ next unless klass.public_methods.include?(:register_class_if_liquid_defined)
195
+ next if klass.public_methods.include?(:base_drop_class) && klass.base_drop_class
198
196
 
199
197
  klass.register_class_if_liquid_defined
200
198
  rescue StandardError
@@ -158,11 +158,10 @@ module Coradoc
158
158
  #
159
159
  # @return [String] Document title
160
160
  def extract_document_title
161
- # Handle CoreModel::StructuralElement (has title directly)
162
- if @document.respond_to?(:title) && @document.title
161
+ if @document.is_a?(Coradoc::CoreModel::StructuralElement) && @document.title
163
162
  title = @document.title
164
163
  return title if title.is_a?(String)
165
- return title.text if title.respond_to?(:text)
164
+ return title.text if title.is_a?(Coradoc::CoreModel::Base) && title.text
166
165
 
167
166
  return title.to_s
168
167
  end
@@ -235,9 +235,9 @@ module Coradoc
235
235
  # @return [Array] Array of section objects
236
236
  def extract_sections(doc)
237
237
  sections = []
238
- return sections unless doc.respond_to?(:sections)
238
+ return sections unless doc.is_a?(Coradoc::CoreModel::StructuralElement)
239
239
 
240
- collect_sections(doc.sections, sections, 1)
240
+ collect_sections(doc.children, sections, 1)
241
241
  sections
242
242
  end
243
243
 
@@ -260,10 +260,7 @@ module Coradoc
260
260
  }
261
261
 
262
262
  # Recursively collect subsections
263
- if item.respond_to?(:sections) && item.sections
264
- collect_sections(item.sections, section_data[:children],
265
- level + 1)
266
- end
263
+ collect_sections(item.children, section_data[:children], level + 1)
267
264
 
268
265
  sections << section_data
269
266
  end
@@ -274,14 +271,14 @@ module Coradoc
274
271
  # @param section [Coradoc::CoreModel::StructuralElement] Section to extract title from
275
272
  # @return [String] Section title
276
273
  def extract_section_title(section)
277
- if section.respond_to?(:title)
278
- title = section.title
279
- if title.respond_to?(:text)
274
+ title = section.title
275
+ if title
276
+ if title.is_a?(Coradoc::CoreModel::Base) && title.text
280
277
  title.text
281
- elsif title.respond_to?(:content)
278
+ elsif title.is_a?(Coradoc::CoreModel::Base) && title.content
282
279
  Coradoc::Html::Converters::Base.get_text_content(title)
283
280
  elsif title.is_a?(Array)
284
- title.map { |t| t.respond_to?(:text) ? t.text : t.to_s }.join
281
+ title.map { |t| t.is_a?(Coradoc::CoreModel::Base) && t.text ? t.text : t.to_s }.join
285
282
  else
286
283
  title.to_s
287
284
  end
@@ -295,7 +292,7 @@ module Coradoc
295
292
  # @param section [Coradoc::CoreModel::StructuralElement] Section to extract ID from
296
293
  # @return [String] Section ID
297
294
  def extract_section_id(section)
298
- if section.respond_to?(:id) && section.id
295
+ if section.id
299
296
  section.id
300
297
  else
301
298
  # Generate ID from title
@@ -235,7 +235,7 @@ module Coradoc
235
235
  def serialize_table_row(row)
236
236
  {
237
237
  type: 'table_row',
238
- header: row.respond_to?(:header) && row.header,
238
+ header: row.is_a?(Coradoc::CoreModel::TableRow) && row.header,
239
239
  cells: (row.cells || []).map do |cell|
240
240
  serialize_table_cell(cell)
241
241
  end
@@ -318,10 +318,10 @@ module Coradoc
318
318
  }
319
319
 
320
320
  # Add link-specific attributes
321
- result[:href] = element.target if element.inline_type == 'link' && element.respond_to?(:target)
321
+ result[:href] = element.target if element.inline_type == 'link' && element.target
322
322
 
323
323
  # Add cross-ref specific attributes
324
- result[:target] = element.target if element.inline_type == 'xref' && element.respond_to?(:target)
324
+ result[:target] = element.target if element.inline_type == 'xref' && element.target
325
325
 
326
326
  result
327
327
  end
@@ -26,11 +26,12 @@ module Coradoc
26
26
  return element if element.nil?
27
27
 
28
28
  element = yield element, :pre
29
- element = if element.respond_to?(:visit)
29
+ element = case element
30
+ when self
30
31
  element.visit(&block)
31
- elsif element.is_a?(Array)
32
+ when Array
32
33
  element.map { |child| visit(child, &block) }.flatten.compact
33
- elsif element.is_a?(Hash)
34
+ when Hash
34
35
  result = {}
35
36
  element.each { |k, v| result[k] = visit(v, &block) }
36
37
  result
@@ -59,12 +60,12 @@ module Coradoc
59
60
  when nil
60
61
  ''
61
62
  else
62
- if content.respond_to?(:to_md)
63
+ if content.is_a?(Base)
63
64
  content.to_md
64
65
  else
65
66
  raise ArgumentError,
66
67
  "Cannot serialize #{content.class.name} to Markdown. " \
67
- 'Expected String or object responding to #to_md.'
68
+ 'Expected String or Base subclass.'
68
69
  end
69
70
  end
70
71
  end
@@ -102,12 +102,12 @@ module Coradoc
102
102
  when Emphasis, Strong, Code, Link, Image, FootnoteReference, Math, Extension, Strikethrough, Highlight
103
103
  serialize(element)
104
104
  else
105
- if element.respond_to?(:to_md)
105
+ if element.is_a?(Base)
106
106
  element.to_md
107
107
  else
108
108
  raise ArgumentError,
109
109
  "Cannot serialize inline content of type #{element.class}. " \
110
- 'Expected String, known inline model, or object responding to #to_md.'
110
+ 'Expected String, known inline model, or Base subclass.'
111
111
  end
112
112
  end
113
113
  end