coradoc 2.0.1 → 2.0.2

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +55 -167
  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/rules/run_rule.rb +4 -1
  30. data/coradoc-docx/lib/coradoc/docx/transform/rules/simple_field_rule.rb +5 -1
  31. data/coradoc-docx/lib/coradoc/docx/transform/rules/table_rule.rb +0 -1
  32. data/coradoc-docx/lib/coradoc/docx.rb +6 -4
  33. data/coradoc-docx/spec/coradoc/docx/transform/from_core_model_spec.rb +5 -2
  34. data/coradoc-docx/spec/coradoc/docx/transform/rules/rule_unit_spec.rb +27 -7
  35. data/coradoc-docx/spec/coradoc/docx/transform/to_core_model_spec.rb +6 -2
  36. data/coradoc-html/lib/coradoc/html/converters/base.rb +4 -1
  37. data/coradoc-html/lib/coradoc/html.rb +1 -1
  38. data/coradoc-markdown/lib/coradoc/markdown/transform/from_core_model.rb +2 -2
  39. data/coradoc-markdown/lib/coradoc/markdown.rb +1 -1
  40. data/lib/coradoc/configurable.rb +6 -2
  41. data/lib/coradoc/coradoc.rb +18 -16
  42. data/lib/coradoc/core_model/base.rb +3 -3
  43. data/lib/coradoc/core_model/list_item.rb +3 -3
  44. data/lib/coradoc/core_model/toc_generator.rb +1 -1
  45. data/lib/coradoc/document_manipulator.rb +9 -13
  46. data/lib/coradoc/format_module.rb +16 -4
  47. data/lib/coradoc/input.rb +1 -1
  48. data/lib/coradoc/output.rb +1 -1
  49. data/lib/coradoc/query.rb +38 -186
  50. data/lib/coradoc/registry.rb +5 -7
  51. data/lib/coradoc/serializer/registry.rb +3 -5
  52. data/lib/coradoc/validation.rb +40 -21
  53. data/lib/coradoc/version.rb +1 -1
  54. metadata +1 -1
@@ -6,23 +6,12 @@ module Coradoc
6
6
  module AsciiDoc
7
7
  module Transform
8
8
  # Transforms AsciiDoc models to CoreModel equivalents
9
- #
10
- # This transformer converts the format-specific AsciiDoc model
11
- # to the canonical CoreModel representation.
12
9
  class ToCoreModel
13
- # Instance method that delegates to class method for convenience
14
10
  def transform(model)
15
11
  self.class.transform(model)
16
12
  end
17
13
 
18
14
  class << self
19
- # Transform an AsciiDoc model to CoreModel
20
- #
21
- # Dispatches to the registered transformer for the model's class.
22
- #
23
- # @param model [Coradoc::AsciiDoc::Model::Base] AsciiDoc model to transform
24
- # @return [Coradoc::CoreModel::Base] CoreModel equivalent
25
- # @raise [TransformationError] if no transformer is registered for the model type
26
15
  def transform(model)
27
16
  return model.map { |item| transform(item) } if model.is_a?(Array)
28
17
  return model unless model.is_a?(Coradoc::AsciiDoc::Model::Base)
@@ -105,8 +94,6 @@ module Coradoc
105
94
  end
106
95
  end
107
96
 
108
- private
109
-
110
97
  def transform_document(doc)
111
98
  title_text = extract_title_text(doc.header&.title)
112
99
  Coradoc::CoreModel::StructuralElement.new(
@@ -119,7 +106,6 @@ module Coradoc
119
106
 
120
107
  def transform_section(section)
121
108
  title_text = extract_title_text(section.title)
122
- # Transform both contents and nested sections
123
109
  content_children = transform(section.contents || [])
124
110
  nested_sections = transform(section.sections || [])
125
111
 
@@ -133,7 +119,6 @@ module Coradoc
133
119
  end
134
120
 
135
121
  def transform_paragraph(para)
136
- # Transform paragraph content, preserving inline elements
137
122
  children = transform_inline_content(para.content)
138
123
 
139
124
  Coradoc::CoreModel::Block.new(
@@ -144,39 +129,11 @@ module Coradoc
144
129
  )
145
130
  end
146
131
 
147
- # Transform inline content, preserving inline element structure
148
- # Returns an array of strings and CoreModel::InlineElement objects
149
- def transform_inline_content(content)
150
- return [] if content.nil?
151
-
152
- case content
153
- when Array
154
- content.flat_map { |item| transform_inline_content(item) }
155
- when Coradoc::AsciiDoc::Model::TextElement
156
- transform_inline_content(content.content)
157
- when Coradoc::AsciiDoc::Model::Term
158
- [Coradoc::CoreModel::InlineElement.new(
159
- format_type: 'term',
160
- content: content.term.to_s
161
- )]
162
- when String
163
- content.empty? ? [] : [content]
164
- when Coradoc::AsciiDoc::Model::Base
165
- [transform(content)]
166
- else
167
- text = extract_text_content(content)
168
- text.empty? ? [] : [text]
169
- end
170
- end
171
-
172
132
  def transform_block(block, delimiter_type)
173
- # Transform block content (lines) - they can contain nested elements
174
133
  content_lines = Array(block.lines).map do |line|
175
134
  case line
176
135
  when Coradoc::AsciiDoc::Model::Base
177
- # Transform nested AsciiDoc model objects to CoreModel
178
136
  transformed = transform(line)
179
- # If it's a CoreModel type, extract text representation
180
137
  if transformed.is_a?(Coradoc::CoreModel::Base)
181
138
  extract_core_model_text(transformed)
182
139
  else
@@ -187,7 +144,6 @@ module Coradoc
187
144
  end
188
145
  end.join("\n")
189
146
 
190
- # Get language from block.lang or attributes
191
147
  language = block.lang || block.attributes&.[]('language') ||
192
148
  block.attributes&.positional&.first
193
149
 
@@ -201,44 +157,6 @@ module Coradoc
201
157
  )
202
158
  end
203
159
 
204
- # Extract text representation from CoreModel objects
205
- def extract_core_model_text(model)
206
- case model
207
- when Coradoc::CoreModel::ListBlock
208
- model.items.map do |item|
209
- item.is_a?(Coradoc::CoreModel::ListItem) ? "* #{item.flat_text}" : item.to_s
210
- end.join("\n")
211
- when Coradoc::CoreModel::AnnotationBlock
212
- "#{model.annotation_type}: #{model.flat_text}"
213
- when Coradoc::CoreModel::Block
214
- model.flat_text
215
- when Coradoc::CoreModel::Image
216
- model.alt || ''
217
- when Coradoc::CoreModel::InlineElement
218
- model.content.to_s
219
- else
220
- ''
221
- end
222
- end
223
-
224
- # Extract text from a Title object
225
- def extract_title_text(title)
226
- return nil if title.nil?
227
- return title.to_s unless title.is_a?(Coradoc::AsciiDoc::Model::Title)
228
-
229
- content = title.content
230
- return '' if content.nil?
231
-
232
- # Content can be a string or an array
233
- if content.is_a?(String)
234
- content
235
- elsif content.is_a?(Array)
236
- content.map { |c| extract_text_content(c) }.join
237
- else
238
- extract_text_content(content)
239
- end
240
- end
241
-
242
160
  def transform_table(table)
243
161
  rows = Array(table.rows).map do |row|
244
162
  transform_table_row(row)
@@ -251,11 +169,30 @@ module Coradoc
251
169
  )
252
170
  end
253
171
 
172
+ def transform_table_row(row)
173
+ cells = Array(row.columns).map do |cell|
174
+ transform_table_cell(cell)
175
+ end
176
+ Coradoc::CoreModel::TableRow.new(cells: cells)
177
+ end
178
+
179
+ def transform_table_cell(cell)
180
+ children = transform_inline_content(cell.content)
181
+
182
+ Coradoc::CoreModel::TableCell.new(
183
+ content: extract_text_content(cell.content),
184
+ alignment: cell.horizontal_alignment,
185
+ vertical_alignment: cell.vertical_alignment,
186
+ colspan: cell.colspan,
187
+ rowspan: cell.rowspan,
188
+ style: cell.style_name,
189
+ children: children
190
+ )
191
+ end
192
+
254
193
  def transform_list(list, marker_type)
255
194
  items = Array(list.items).map do |item|
256
- # Handle both ListItem (content) and ListItemDefinition (contents, terms)
257
195
  if item.is_a?(Coradoc::AsciiDoc::Model::List::DefinitionItem)
258
- # Definition list item
259
196
  term_content = item.terms
260
197
  def_content = item.contents
261
198
 
@@ -264,8 +201,7 @@ module Coradoc
264
201
  definitions: [extract_text_content(def_content)]
265
202
  )
266
203
  else
267
- # Regular list item - preserve inline elements
268
- content_val = item.respond_to?(:content) ? item.content : item.contents
204
+ content_val = item.content
269
205
  children = transform_inline_content(content_val)
270
206
 
271
207
  li = Coradoc::CoreModel::ListItem.new(
@@ -333,37 +269,6 @@ module Coradoc
333
269
  )
334
270
  end
335
271
 
336
- def transform_image(image)
337
- Coradoc::CoreModel::Image.new(
338
- src: image.src,
339
- alt: image.title&.to_s,
340
- width: image.attributes&.[]('width'),
341
- height: image.attributes&.[]('height')
342
- )
343
- end
344
-
345
- def transform_table_row(row)
346
- cells = Array(row.columns).map do |cell|
347
- transform_table_cell(cell)
348
- end
349
- Coradoc::CoreModel::TableRow.new(cells: cells)
350
- end
351
-
352
- def transform_table_cell(cell)
353
- # Transform cell content, preserving inline elements
354
- children = transform_inline_content(cell.content)
355
-
356
- Coradoc::CoreModel::TableCell.new(
357
- content: extract_text_content(cell.content),
358
- alignment: cell.horizontal_alignment,
359
- vertical_alignment: cell.vertical_alignment,
360
- colspan: cell.colspan,
361
- rowspan: cell.rowspan,
362
- style: cell.style_name,
363
- children: children
364
- )
365
- end
366
-
367
272
  def transform_cross_reference(xref)
368
273
  Coradoc::CoreModel::InlineElement.new(
369
274
  format_type: 'xref',
@@ -380,6 +285,15 @@ module Coradoc
380
285
  )
381
286
  end
382
287
 
288
+ def transform_image(image)
289
+ Coradoc::CoreModel::Image.new(
290
+ src: image.src,
291
+ alt: image.title&.to_s,
292
+ width: image.attributes&.[]('width'),
293
+ height: image.attributes&.[]('height')
294
+ )
295
+ end
296
+
383
297
  def transform_bibliography(bib)
384
298
  entries = Array(bib.entries).map do |entry|
385
299
  transform_bibliography_entry(entry)
@@ -388,7 +302,7 @@ module Coradoc
388
302
  Coradoc::CoreModel::Bibliography.new(
389
303
  id: bib.id,
390
304
  title: bib.title.to_s,
391
- level: bib.respond_to?(:level) ? bib.level : nil,
305
+ level: nil,
392
306
  entries: entries
393
307
  )
394
308
  end
@@ -401,6 +315,66 @@ module Coradoc
401
315
  )
402
316
  end
403
317
 
318
+ private
319
+
320
+ def transform_inline_content(content)
321
+ return [] if content.nil?
322
+
323
+ case content
324
+ when Array
325
+ content.flat_map { |item| transform_inline_content(item) }
326
+ when Coradoc::AsciiDoc::Model::TextElement
327
+ transform_inline_content(content.content)
328
+ when Coradoc::AsciiDoc::Model::Term
329
+ [Coradoc::CoreModel::InlineElement.new(
330
+ format_type: 'term',
331
+ content: content.term.to_s
332
+ )]
333
+ when String
334
+ content.empty? ? [] : [content]
335
+ when Coradoc::AsciiDoc::Model::Base
336
+ [transform(content)]
337
+ else
338
+ text = extract_text_content(content)
339
+ text.empty? ? [] : [text]
340
+ end
341
+ end
342
+
343
+ def extract_core_model_text(model)
344
+ case model
345
+ when Coradoc::CoreModel::ListBlock
346
+ model.items.map do |item|
347
+ item.is_a?(Coradoc::CoreModel::ListItem) ? "* #{item.flat_text}" : item.to_s
348
+ end.join("\n")
349
+ when Coradoc::CoreModel::AnnotationBlock
350
+ "#{model.annotation_type}: #{model.flat_text}"
351
+ when Coradoc::CoreModel::Block
352
+ model.flat_text
353
+ when Coradoc::CoreModel::Image
354
+ model.alt || ''
355
+ when Coradoc::CoreModel::InlineElement
356
+ model.content.to_s
357
+ else
358
+ ''
359
+ end
360
+ end
361
+
362
+ def extract_title_text(title)
363
+ return nil if title.nil?
364
+ return title.to_s unless title.is_a?(Coradoc::AsciiDoc::Model::Title)
365
+
366
+ content = title.content
367
+ return '' if content.nil?
368
+
369
+ if content.is_a?(String)
370
+ content
371
+ elsif content.is_a?(Array)
372
+ content.map { |c| extract_text_content(c) }.join
373
+ else
374
+ extract_text_content(content)
375
+ end
376
+ end
377
+
404
378
  def extract_text_content(content)
405
379
  case content
406
380
  when nil
@@ -408,7 +382,6 @@ module Coradoc
408
382
  when String
409
383
  content
410
384
  when Array
411
- # Join text elements with spaces (paragraph normalization)
412
385
  result = []
413
386
  content.each_with_index do |item, idx|
414
387
  text = extract_text_content(item)
@@ -441,7 +414,7 @@ module Coradoc
441
414
  when Coradoc::AsciiDoc::Model::Inline::Stem
442
415
  content.content.to_s
443
416
  when Coradoc::AsciiDoc::Model::Inline::Footnote
444
- if content.respond_to?(:content) && content.content
417
+ if content.content
445
418
  extract_text_content(content.content)
446
419
  else
447
420
  ''
@@ -453,14 +426,14 @@ module Coradoc
453
426
  when Coradoc::CoreModel::Image
454
427
  content.alt || content.src || ''
455
428
  when Coradoc::AsciiDoc::Model::Base
456
- if content.respond_to?(:content)
429
+ if content.content
457
430
  extract_text_content(content.content)
458
431
  else
459
432
  ''
460
433
  end
461
434
  else
462
- if content.respond_to?(:to_str)
463
- content.to_s
435
+ if content.is_a?(String)
436
+ content
464
437
  elsif content.class.name.start_with?('Parslet::')
465
438
  content.to_s
466
439
  else
@@ -53,7 +53,7 @@ module Coradoc
53
53
 
54
54
  Registry.register(
55
55
  Coradoc::AsciiDoc::Model::Block::Core,
56
- ->(model) { ToCoreModel.send(:transform_block, model, model.delimiter) }
56
+ block_wrapper(nil) # uses model.delimiter at call time
57
57
  )
58
58
 
59
59
  Registry.register(
@@ -194,23 +194,27 @@ module Coradoc
194
194
  end
195
195
 
196
196
  def method_wrapper(method_name)
197
- ->(model) { ToCoreModel.send(method_name, model) }
197
+ ->(model) { ToCoreModel.public_send(method_name, model) }
198
198
  end
199
199
 
200
200
  def block_wrapper(delimiter_type)
201
- ->(model) { ToCoreModel.send(:transform_block, model, delimiter_type) }
201
+ if delimiter_type
202
+ ->(model) { ToCoreModel.transform_block(model, delimiter_type) }
203
+ else
204
+ ->(model) { ToCoreModel.transform_block(model, model.delimiter) }
205
+ end
202
206
  end
203
207
 
204
208
  def list_wrapper(marker_type)
205
- ->(model) { ToCoreModel.send(:transform_list, model, marker_type) }
209
+ ->(model) { ToCoreModel.transform_list(model, marker_type) }
206
210
  end
207
211
 
208
212
  def inline_wrapper(format_type)
209
- ->(model) { ToCoreModel.send(:transform_inline, model, format_type) }
213
+ ->(model) { ToCoreModel.transform_inline(model, format_type) }
210
214
  end
211
215
 
212
216
  def inline_text_wrapper(format_type)
213
- ->(model) { ToCoreModel.send(:transform_inline_text, model, format_type) }
217
+ ->(model) { ToCoreModel.transform_inline_text(model, format_type) }
214
218
  end
215
219
  end
216
220
  end
@@ -13,7 +13,7 @@ module Coradoc
13
13
  author: simple(:author),
14
14
  revision: simple(:revision)
15
15
  ) do
16
- id = title.respond_to?(:id) ? title.id : nil
16
+ id = title.is_a?(Model::Title) ? title.id : nil
17
17
  Model::Header.new(id:, title:, author:, revision:)
18
18
  end
19
19
 
@@ -22,7 +22,7 @@ module Coradoc
22
22
  title: simple(:title),
23
23
  author: simple(:author)
24
24
  ) do
25
- id = title.respond_to?(:id) ? title.id : nil
25
+ id = title.is_a?(Model::Title) ? title.id : nil
26
26
  Model::Header.new(id:, title:, author:, revision: nil)
27
27
  end
28
28
 
@@ -31,7 +31,7 @@ module Coradoc
31
31
  title: simple(:title),
32
32
  revision: simple(:revision)
33
33
  ) do
34
- id = title.respond_to?(:id) ? title.id : nil
34
+ id = title.is_a?(Model::Title) ? title.id : nil
35
35
  Model::Header.new(id:, title:, author: nil, revision:)
36
36
  end
37
37
 
@@ -39,7 +39,7 @@ module Coradoc
39
39
  rule(
40
40
  title: simple(:title)
41
41
  ) do
42
- id = title.respond_to?(:id) ? title.id : nil
42
+ id = title.is_a?(Model::Title) ? title.id : nil
43
43
  Model::Header.new(id:, title:, author: nil, revision: nil)
44
44
  end
45
45
 
@@ -72,7 +72,7 @@ module Coradoc
72
72
  author = header[:author]
73
73
  revision = header[:revision]
74
74
 
75
- id = title.id if title.respond_to?(:id) && title.id && !id
75
+ id = title.id if title.is_a?(Model::Title) && title.id && !id
76
76
 
77
77
  Model::Header.new(id:, title:, author:, revision:)
78
78
  else
@@ -19,8 +19,8 @@ module Coradoc
19
19
 
20
20
  # Convert nested array to proper List object if needed
21
21
  if nested.is_a?(Array) && nested.any?
22
- first_marker = nested.first.respond_to?(:marker) ? nested.first.marker : marker
23
- nested = if first_marker&.start_with?('.', '1', 'a', 'A', 'i', 'I')
22
+ first_marker = nested.first.is_a?(Model::List::Item) ? nested.first.marker : marker
23
+ nested = if first_marker.to_s.start_with?('.', '1', 'a', 'A', 'i', 'I')
24
24
  Model::List::Ordered.new(items: nested)
25
25
  else
26
26
  Model::List::Unordered.new(items: nested)
@@ -168,7 +168,7 @@ module Coradoc
168
168
  id = section[:id] || nil
169
169
  title = section[:title] || nil
170
170
 
171
- id = title.id if title.respond_to?(:id) && title.id && !id
171
+ id = title.id if title.is_a?(Model::Title) && title.id && !id
172
172
 
173
173
  attribute_list = section[:attribute_list] || nil
174
174
  contents = section[:contents] || []
@@ -47,7 +47,7 @@ module Coradoc
47
47
  data.map do |item|
48
48
  if item.is_a?(Hash) && item.key?(:text)
49
49
  text = item[:text]
50
- if text.respond_to?(:content)
50
+ if text.is_a?(Model::Base) && text.class.attributes.key?(:content)
51
51
  text.content
52
52
  elsif text.is_a?(Model::Base)
53
53
  text
@@ -197,7 +197,7 @@ module Coradoc
197
197
 
198
198
  # Repeat marker
199
199
  cell_opts[:repeat] = true if format[:repeat]
200
- elsif format.is_a?(String) || format.respond_to?(:to_s)
200
+ elsif format.is_a?(String)
201
201
  # Parse format string like ".2+^.^" or "4+^" or ".3+a"
202
202
  # Format: [colspan][.rowspan][halign][valign][style][*]
203
203
  format_str = format.to_s
@@ -237,7 +237,7 @@ module Coradoc
237
237
  return nil if attrs.nil?
238
238
 
239
239
  # Get the cols value from named attributes
240
- cols_value = if attrs.respond_to?(:named)
240
+ cols_value = if attrs.is_a?(Model::AttributeList)
241
241
  attrs.named.find { |n| n.name.to_s == 'cols' }&.value
242
242
  elsif attrs.is_a?(Hash)
243
243
  attrs['cols'] || attrs[:cols]
@@ -312,7 +312,7 @@ module Coradoc
312
312
 
313
313
  normalized_cells.each do |cell|
314
314
  # Get colspan (default 1)
315
- colspan = (cell.respond_to?(:colspan) && cell.colspan) || 1
315
+ colspan = cell.is_a?(Model::TableCell) && cell.colspan ? cell.colspan : 1
316
316
 
317
317
  current_row_cells << cell
318
318
  current_col_slots += colspan
@@ -339,7 +339,7 @@ module Coradoc
339
339
 
340
340
  # Count column slots for each cell
341
341
  col_slots = cells.map do |cell|
342
- (cell.respond_to?(:colspan) && cell.colspan) || 1
342
+ cell.is_a?(Model::TableCell) && cell.colspan ? cell.colspan : 1
343
343
  end
344
344
 
345
345
  total_cells = col_slots.sum
@@ -136,7 +136,7 @@ end
136
136
  # Use conditional registration to handle load order issues
137
137
  Coradoc.register_format(:asciidoc, Coradoc::AsciiDoc,
138
138
  aliases: %w[adoc asciidoc],
139
- extensions: %w[.adoc .asciidoc]) if Coradoc.respond_to?(:register_format)
139
+ extensions: %w[.adoc .asciidoc])
140
140
 
141
141
  # Backward-compatibility: Coradoc::Model is now Coradoc::AsciiDoc::Model
142
142
  # This alias is provided for legacy code that hasn't been updated
@@ -16,11 +16,12 @@ module Coradoc
16
16
  return '' if model.nil?
17
17
  return model if model.is_a?(String)
18
18
 
19
- if model.respond_to?(:to_adoc)
19
+ case model
20
+ when Coradoc::AsciiDoc::Model::Base
20
21
  model.to_adoc
21
- elsif model.is_a?(Array)
22
+ when Array
22
23
  model.map { |item| serialize(item) }.join("\n")
23
- elsif model.is_a?(Hash)
24
+ when Hash
24
25
  model.map { |k, v| "#{k}: #{serialize(v)}" }.join("\n")
25
26
  else
26
27
  model.to_s
@@ -189,12 +189,14 @@ RSpec.describe Coradoc::AsciiDoc::Transform::FromCoreModel do
189
189
  end
190
190
 
191
191
  it 'transforms xref InlineElement to AsciiDoc CrossReference' do
192
- core_inline = Coradoc::CoreModel::InlineElement.new(format_type: 'xref', target: 'section1', content: 'Section 1')
192
+ core_inline = Coradoc::CoreModel::InlineElement.new(format_type: 'xref', target: 'section1',
193
+ content: 'Section 1')
193
194
  expect(described_class.transform(core_inline)).to be_a(Coradoc::AsciiDoc::Model::Inline::CrossReference)
194
195
  end
195
196
 
196
197
  it 'transforms footnote InlineElement to AsciiDoc Footnote' do
197
- core_inline = Coradoc::CoreModel::InlineElement.new(format_type: 'footnote', target: 'fn1', content: 'note text')
198
+ core_inline = Coradoc::CoreModel::InlineElement.new(format_type: 'footnote', target: 'fn1',
199
+ content: 'note text')
198
200
  expect(described_class.transform(core_inline)).to be_a(Coradoc::AsciiDoc::Model::Inline::Footnote)
199
201
  end
200
202
 
@@ -100,7 +100,10 @@ module Coradoc
100
100
  result << CoreModel::InlineElement.new(format_type: 'hard_line_break') if run.respond_to?(:carriage_return) && run.carriage_return
101
101
 
102
102
  # Alternate content — extract preferred/fallback content
103
- result << extract_alternate_content(run.alternate_content, context) if run.respond_to?(:alternate_content) && run.alternate_content
103
+ if run.respond_to?(:alternate_content) && run.alternate_content
104
+ result << extract_alternate_content(run.alternate_content,
105
+ context)
106
+ end
104
107
 
105
108
  result.compact
106
109
  end
@@ -63,7 +63,11 @@ module Coradoc
63
63
 
64
64
  def field_text(field)
65
65
  # SimpleField may have runs with resolved text
66
- return field.runs.map { |r| r.text&.content.to_s }.join if field.respond_to?(:runs) && field.runs && !field.runs.empty?
66
+ if field.respond_to?(:runs) && field.runs && !field.runs.empty?
67
+ return field.runs.map do |r|
68
+ r.text&.content.to_s
69
+ end.join
70
+ end
67
71
 
68
72
  # Fall back to text attribute
69
73
  field.respond_to?(:text) ? field.text.to_s : nil
@@ -79,7 +79,6 @@ module Coradoc
79
79
  vm = cell.properties.v_merge
80
80
  vm.respond_to?(:value) ? vm.value.to_s == 'restart' : false
81
81
  end
82
-
83
82
  end
84
83
  end
85
84
  end
@@ -91,7 +91,9 @@ module Coradoc
91
91
  end
92
92
 
93
93
  # Auto-register :docx format with Coradoc when both gems are loaded
94
- Coradoc.register_format(:docx, Coradoc::Docx,
95
- aliases: %w[docx],
96
- extensions: %w[.docx],
97
- binary: true) unless Coradoc.registered_formats.include?(:docx)
94
+ unless Coradoc.registered_formats.include?(:docx)
95
+ Coradoc.register_format(:docx, Coradoc::Docx,
96
+ aliases: %w[docx],
97
+ extensions: %w[.docx],
98
+ binary: true)
99
+ end
@@ -120,7 +120,9 @@ RSpec.describe Coradoc::Docx::Transform::FromCoreModel do
120
120
  end
121
121
 
122
122
  context 'with Abbreviation' do
123
- let(:core_model) { Coradoc::CoreModel::Abbreviation.new(term: 'API', definition: 'Application Programming Interface') }
123
+ let(:core_model) do
124
+ Coradoc::CoreModel::Abbreviation.new(term: 'API', definition: 'Application Programming Interface')
125
+ end
124
126
 
125
127
  it 'produces a Paragraph with term and definition' do
126
128
  expect(result).to be_a(Uniword::Wordprocessingml::Paragraph)
@@ -245,7 +247,8 @@ RSpec.describe Coradoc::Docx::Transform::FromCoreModel do
245
247
  @tmpdir = Dir.mktmpdir
246
248
  img_path = File.join(@tmpdir, 'test.png')
247
249
  # Minimal 1x1 PNG
248
- File.binwrite(img_path, "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDATx\x9cc\xf8\x0f\x00\x00\x01\x01\x00\x05\x18\xd8N\x00\x00\x00\x00IEND\xAEB`\x82".b)
250
+ File.binwrite(img_path,
251
+ "\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDATx\x9cc\xf8\x0f\x00\x00\x01\x01\x00\x05\x18\xd8N\x00\x00\x00\x00IEND\xAEB`\x82".b)
249
252
  Coradoc::CoreModel::Image.new(src: img_path, alt: 'Test image')
250
253
  end
251
254