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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +55 -167
- data/coradoc-adoc/lib/coradoc/asciidoc/model/base.rb +4 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/model/document.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/model/include.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/model/resolver.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/model/serialization/asciidoc_transform.rb +3 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/model/table_row.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/model/text_element.rb +4 -8
- data/coradoc-adoc/lib/coradoc/asciidoc/parse_error.rb +6 -6
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/adoc_serializer.rb +5 -10
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/formatter.rb +4 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/base.rb +8 -20
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/block/core.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/document.rb +3 -6
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/inline/strikethrough.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/list/item.rb +5 -9
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model.rb +26 -34
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model_registrations.rb +18 -18
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model.rb +96 -123
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model_registrations.rb +10 -6
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/header_rules.rb +5 -5
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/list_rules.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/structural_rules.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer.rb +5 -5
- data/coradoc-adoc/lib/coradoc/asciidoc.rb +1 -1
- data/coradoc-adoc/lib/coradoc/util/asciidoc.rb +4 -3
- data/coradoc-adoc/spec/coradoc/asciidoc/transform/from_core_model_spec.rb +4 -2
- data/coradoc-docx/lib/coradoc/docx/transform/rules/run_rule.rb +4 -1
- data/coradoc-docx/lib/coradoc/docx/transform/rules/simple_field_rule.rb +5 -1
- data/coradoc-docx/lib/coradoc/docx/transform/rules/table_rule.rb +0 -1
- data/coradoc-docx/lib/coradoc/docx.rb +6 -4
- data/coradoc-docx/spec/coradoc/docx/transform/from_core_model_spec.rb +5 -2
- data/coradoc-docx/spec/coradoc/docx/transform/rules/rule_unit_spec.rb +27 -7
- data/coradoc-docx/spec/coradoc/docx/transform/to_core_model_spec.rb +6 -2
- data/coradoc-html/lib/coradoc/html/converters/base.rb +4 -1
- data/coradoc-html/lib/coradoc/html.rb +1 -1
- data/coradoc-markdown/lib/coradoc/markdown/transform/from_core_model.rb +2 -2
- data/coradoc-markdown/lib/coradoc/markdown.rb +1 -1
- data/lib/coradoc/configurable.rb +6 -2
- data/lib/coradoc/coradoc.rb +18 -16
- data/lib/coradoc/core_model/base.rb +3 -3
- data/lib/coradoc/core_model/list_item.rb +3 -3
- data/lib/coradoc/core_model/toc_generator.rb +1 -1
- data/lib/coradoc/document_manipulator.rb +9 -13
- data/lib/coradoc/format_module.rb +16 -4
- data/lib/coradoc/input.rb +1 -1
- data/lib/coradoc/output.rb +1 -1
- data/lib/coradoc/query.rb +38 -186
- data/lib/coradoc/registry.rb +5 -7
- data/lib/coradoc/serializer/registry.rb +3 -5
- data/lib/coradoc/validation.rb +40 -21
- data/lib/coradoc/version.rb +1 -1
- 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
|
-
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
463
|
-
content
|
|
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
|
-
|
|
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.
|
|
197
|
+
->(model) { ToCoreModel.public_send(method_name, model) }
|
|
198
198
|
end
|
|
199
199
|
|
|
200
200
|
def block_wrapper(delimiter_type)
|
|
201
|
-
|
|
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.
|
|
209
|
+
->(model) { ToCoreModel.transform_list(model, marker_type) }
|
|
206
210
|
end
|
|
207
211
|
|
|
208
212
|
def inline_wrapper(format_type)
|
|
209
|
-
->(model) { ToCoreModel.
|
|
213
|
+
->(model) { ToCoreModel.transform_inline(model, format_type) }
|
|
210
214
|
end
|
|
211
215
|
|
|
212
216
|
def inline_text_wrapper(format_type)
|
|
213
|
-
->(model) { ToCoreModel.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
23
|
-
nested = if first_marker
|
|
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.
|
|
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.
|
|
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)
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
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])
|
|
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
|
-
|
|
19
|
+
case model
|
|
20
|
+
when Coradoc::AsciiDoc::Model::Base
|
|
20
21
|
model.to_adoc
|
|
21
|
-
|
|
22
|
+
when Array
|
|
22
23
|
model.map { |item| serialize(item) }.join("\n")
|
|
23
|
-
|
|
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',
|
|
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',
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
@@ -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.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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)
|
|
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,
|
|
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
|
|