coradoc 2.0.4 → 2.0.6
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 +96 -51
- data/coradoc-adoc/lib/coradoc/asciidoc/model/break.rb +7 -0
- data/coradoc-adoc/lib/coradoc/asciidoc/model/document.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/model/include.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/model.rb +6 -4
- data/coradoc-adoc/lib/coradoc/asciidoc/parser/base.rb +1 -0
- data/coradoc-adoc/lib/coradoc/asciidoc/parser/block.rb +8 -7
- data/coradoc-adoc/lib/coradoc/asciidoc/parser/content.rb +13 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/parser/inline.rb +15 -15
- data/coradoc-adoc/lib/coradoc/asciidoc/parser/list.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/parser/section.rb +1 -0
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/document.rb +4 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model.rb +84 -13
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model.rb +106 -27
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model_registrations.rb +50 -19
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/misc_rules.rb +5 -0
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/structural_rules.rb +9 -8
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer.rb +22 -5
- data/coradoc-adoc/lib/coradoc/asciidoc.rb +7 -2
- data/coradoc-adoc/spec/coradoc/asciidoc/integration_pipeline_spec.rb +342 -0
- data/coradoc-adoc/spec/coradoc/asciidoc/list_continuation_spec.rb +1 -1
- data/coradoc-adoc/spec/coradoc/asciidoc/round_trip_spec.rb +0 -2
- data/coradoc-adoc/spec/coradoc/asciidoc/transform/from_core_model_spec.rb +3 -2
- data/coradoc-adoc/spec/coradoc/developer_experience_spec.rb +0 -2
- data/coradoc-adoc/spec/transform/from_core_model_spec.rb +3 -3
- data/coradoc-adoc/spec/transform/to_core_model_spec.rb +1 -0
- data/coradoc-html/lib/coradoc/html/converters/base.rb +41 -17
- data/coradoc-html/lib/coradoc/html/converters/example.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/listing.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/literal.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/open.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/quote.rb +2 -3
- data/coradoc-html/lib/coradoc/html/converters/sidebar.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/source.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/source_code.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/term.rb +1 -2
- data/coradoc-html/lib/coradoc/html/converters/verse.rb +2 -3
- data/coradoc-html/lib/coradoc/html/input/converters/aside.rb +1 -1
- data/coradoc-html/lib/coradoc/html/input/converters/audio.rb +1 -1
- data/coradoc-html/lib/coradoc/html/input/converters/blockquote.rb +2 -3
- data/coradoc-html/lib/coradoc/html/input/converters/div.rb +1 -2
- data/coradoc-html/lib/coradoc/html/input/converters/figure.rb +2 -3
- data/coradoc-html/lib/coradoc/html/input/converters/hr.rb +1 -1
- data/coradoc-html/lib/coradoc/html/input/converters/p.rb +2 -1
- data/coradoc-html/lib/coradoc/html/input/converters/pre.rb +14 -10
- data/coradoc-html/lib/coradoc/html/input/converters/video.rb +1 -1
- data/coradoc-html/lib/coradoc/html/renderer.rb +50 -2
- data/coradoc-html/lib/coradoc/html/spa.rb +2 -2
- data/coradoc-html/lib/coradoc/html/static.rb +2 -2
- data/coradoc-html/lib/coradoc/html/templates/core_model/definition_list.liquid +11 -0
- data/coradoc-html/lib/coradoc/html/theme/modern/javascript_generator.rb +2 -2
- data/coradoc-html/lib/coradoc/html/theme/modern/serializers/document_serializer.rb +7 -11
- data/coradoc-html/lib/coradoc/html/theme/modern_renderer.rb +6 -7
- data/coradoc-html/lib/coradoc/html.rb +5 -15
- data/coradoc-html/spec/input/converters/converters_spec.rb +6 -8
- data/coradoc-markdown/lib/coradoc/markdown/model/attribute_list.rb +0 -3
- data/coradoc-markdown/lib/coradoc/markdown/model/definition_list.rb +0 -3
- data/coradoc-markdown/lib/coradoc/markdown/model/extension.rb +0 -2
- data/coradoc-markdown/lib/coradoc/markdown/model/highlight.rb +0 -1
- data/coradoc-markdown/lib/coradoc/markdown/model/math.rb +0 -1
- data/coradoc-markdown/lib/coradoc/markdown/model/strikethrough.rb +0 -1
- data/coradoc-markdown/lib/coradoc/markdown/parser/ast_processor.rb +2 -2
- data/coradoc-markdown/lib/coradoc/markdown/parser/block_parser.rb +2 -2
- data/coradoc-markdown/lib/coradoc/markdown/parser/inline_parser.rb +3 -3
- data/coradoc-markdown/lib/coradoc/markdown/parser.rb +9 -3
- data/coradoc-markdown/lib/coradoc/markdown/toc_generator.rb +6 -4
- data/coradoc-markdown/lib/coradoc/markdown/transform/from_core_model.rb +27 -6
- data/coradoc-markdown/lib/coradoc/markdown/transform/to_core_model.rb +5 -9
- data/coradoc-markdown/lib/coradoc/markdown/transformer.rb +2 -1
- data/coradoc-markdown/spec/transform/to_core_model_spec.rb +6 -8
- data/exe/coradoc +1 -0
- data/lib/coradoc/coradoc.rb +6 -7
- data/lib/coradoc/core_model/annotation_block.rb +0 -2
- data/lib/coradoc/core_model/block.rb +92 -32
- data/lib/coradoc/core_model/builder/block_builder.rb +20 -2
- data/lib/coradoc/core_model/builder/detection.rb +0 -8
- data/lib/coradoc/core_model/builder.rb +6 -7
- data/lib/coradoc/core_model/example_block.rb +12 -0
- data/lib/coradoc/core_model/listing_block.rb +15 -0
- data/lib/coradoc/core_model/literal_block.rb +12 -0
- data/lib/coradoc/core_model/open_block.rb +12 -0
- data/lib/coradoc/core_model/pass_block.rb +12 -0
- data/lib/coradoc/core_model/quote_block.rb +14 -0
- data/lib/coradoc/core_model/reviewer_block.rb +12 -0
- data/lib/coradoc/core_model/sidebar_block.rb +12 -0
- data/lib/coradoc/core_model/source_block.rb +22 -0
- data/lib/coradoc/core_model/structural_element.rb +4 -0
- data/lib/coradoc/core_model/verse_block.rb +14 -0
- data/lib/coradoc/core_model.rb +10 -0
- data/lib/coradoc/document_manipulator.rb +3 -1
- data/lib/coradoc/processor_registry.rb +0 -2
- data/lib/coradoc/version.rb +1 -1
- metadata +13 -34
- data/coradoc-markdown/coverage/.last_run.json +0 -5
- data/coradoc-markdown/coverage/.resultset.json +0 -6322
- data/coradoc-markdown/coverage/.resultset.json.lock +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_asc.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_both.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_desc.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/application.css +0 -1
- data/coradoc-markdown/coverage/assets/0.13.2/application.js +0 -7
- data/coradoc-markdown/coverage/assets/0.13.2/colorbox/border.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/colorbox/controls.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/colorbox/loading.gif +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/colorbox/loading_background.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/favicon_green.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/favicon_red.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/favicon_yellow.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-icons_222222_256x240.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-icons_454545_256x240.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-icons_888888_256x240.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/loading.gif +0 -0
- data/coradoc-markdown/coverage/assets/0.13.2/magnify.png +0 -0
- data/coradoc-markdown/coverage/index.html +0 -66032
|
@@ -103,14 +103,15 @@ module Coradoc
|
|
|
103
103
|
def transform_block(block)
|
|
104
104
|
content = block.renderable_content
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
semantic = resolve_semantic_type(block)
|
|
107
|
+
|
|
108
|
+
case semantic
|
|
109
|
+
when :paragraph
|
|
107
110
|
return Coradoc::AsciiDoc::Model::Paragraph.new(
|
|
108
111
|
id: block.id,
|
|
109
112
|
content: create_text_elements(content)
|
|
110
113
|
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if block.element_type == 'comment'
|
|
114
|
+
when :comment
|
|
114
115
|
return Coradoc::AsciiDoc::Model::CommentBlock.new(
|
|
115
116
|
text: safe_content_to_string(content)
|
|
116
117
|
)
|
|
@@ -118,42 +119,67 @@ module Coradoc
|
|
|
118
119
|
|
|
119
120
|
content_text = safe_content_to_string(content)
|
|
120
121
|
|
|
121
|
-
case
|
|
122
|
-
when
|
|
122
|
+
case semantic
|
|
123
|
+
when :source_code
|
|
123
124
|
Coradoc::AsciiDoc::Model::Block::SourceCode.new(
|
|
124
125
|
id: block.id,
|
|
125
126
|
title: block.title,
|
|
126
127
|
lines: content_text.split("\n"),
|
|
127
128
|
attributes: build_attributes(block)
|
|
128
129
|
)
|
|
129
|
-
when
|
|
130
|
+
when :quote
|
|
130
131
|
Coradoc::AsciiDoc::Model::Block::Quote.new(
|
|
131
132
|
id: block.id,
|
|
132
133
|
title: block.title,
|
|
133
134
|
lines: content_text.split("\n")
|
|
134
135
|
)
|
|
135
|
-
when
|
|
136
|
+
when :example
|
|
136
137
|
Coradoc::AsciiDoc::Model::Block::Example.new(
|
|
137
138
|
id: block.id,
|
|
138
139
|
title: block.title,
|
|
139
140
|
lines: content_text.split("\n")
|
|
140
141
|
)
|
|
141
|
-
when
|
|
142
|
+
when :sidebar
|
|
142
143
|
Coradoc::AsciiDoc::Model::Block::Side.new(
|
|
143
144
|
id: block.id,
|
|
144
145
|
title: block.title,
|
|
145
146
|
lines: content_text.split("\n")
|
|
146
147
|
)
|
|
147
|
-
when
|
|
148
|
+
when :literal
|
|
148
149
|
Coradoc::AsciiDoc::Model::Block::Literal.new(
|
|
149
150
|
id: block.id,
|
|
150
151
|
title: block.title,
|
|
151
152
|
lines: content_text.split("\n")
|
|
152
153
|
)
|
|
153
|
-
when
|
|
154
|
-
Coradoc::AsciiDoc::Model::
|
|
154
|
+
when :open
|
|
155
|
+
Coradoc::AsciiDoc::Model::Block::Open.new(
|
|
155
156
|
id: block.id,
|
|
156
|
-
|
|
157
|
+
title: block.title,
|
|
158
|
+
lines: content_text.split("\n")
|
|
159
|
+
)
|
|
160
|
+
when :pass
|
|
161
|
+
Coradoc::AsciiDoc::Model::Block::Pass.new(
|
|
162
|
+
id: block.id,
|
|
163
|
+
title: block.title,
|
|
164
|
+
lines: content_text.split("\n")
|
|
165
|
+
)
|
|
166
|
+
when :listing
|
|
167
|
+
Coradoc::AsciiDoc::Model::Block::Listing.new(
|
|
168
|
+
id: block.id,
|
|
169
|
+
title: block.title,
|
|
170
|
+
lines: content_text.split("\n")
|
|
171
|
+
)
|
|
172
|
+
when :verse
|
|
173
|
+
Coradoc::AsciiDoc::Model::Block::Quote.new(
|
|
174
|
+
id: block.id,
|
|
175
|
+
title: block.title,
|
|
176
|
+
lines: content_text.split("\n")
|
|
177
|
+
)
|
|
178
|
+
when :reviewer
|
|
179
|
+
Coradoc::AsciiDoc::Model::Block::ReviewerComment.new(
|
|
180
|
+
id: block.id,
|
|
181
|
+
title: block.title,
|
|
182
|
+
lines: content_text.split("\n")
|
|
157
183
|
)
|
|
158
184
|
else
|
|
159
185
|
delim = block.delimiter_type.to_s
|
|
@@ -350,6 +376,51 @@ module Coradoc
|
|
|
350
376
|
|
|
351
377
|
private
|
|
352
378
|
|
|
379
|
+
# Reverse mapping: semantic type → AsciiDoc delimiter generation
|
|
380
|
+
SEMANTIC_TO_ADOC_BLOCK = {
|
|
381
|
+
source_code: :source_code,
|
|
382
|
+
quote: :quote,
|
|
383
|
+
example: :example,
|
|
384
|
+
sidebar: :sidebar,
|
|
385
|
+
literal: :literal,
|
|
386
|
+
pass: :pass,
|
|
387
|
+
open: :open,
|
|
388
|
+
verse: :open,
|
|
389
|
+
paragraph: :paragraph,
|
|
390
|
+
comment: :comment
|
|
391
|
+
}.freeze
|
|
392
|
+
|
|
393
|
+
# Map raw delimiter_type string → semantic type (backward compat)
|
|
394
|
+
DELIMITER_CHAR_TO_SEMANTIC = {
|
|
395
|
+
'-' => :source_code,
|
|
396
|
+
'=' => :example,
|
|
397
|
+
'_' => :quote,
|
|
398
|
+
'*' => :sidebar,
|
|
399
|
+
'.' => :literal,
|
|
400
|
+
'+' => :pass
|
|
401
|
+
}.freeze
|
|
402
|
+
|
|
403
|
+
def resolve_semantic_type(block)
|
|
404
|
+
# Polymorphic dispatch: typed classes override semantic_type
|
|
405
|
+
semantic = block.resolve_semantic_type
|
|
406
|
+
return semantic if semantic
|
|
407
|
+
|
|
408
|
+
# Format-specific fallback from delimiter_type
|
|
409
|
+
delim = block.delimiter_type
|
|
410
|
+
return nil unless delim && !delim.empty?
|
|
411
|
+
|
|
412
|
+
case delim
|
|
413
|
+
when 'comment' then :comment
|
|
414
|
+
when 'paragraph' then :paragraph
|
|
415
|
+
when '[verse]' then :verse
|
|
416
|
+
when '>' then :quote
|
|
417
|
+
when "'''", '---', '___', '***' then :horizontal_rule
|
|
418
|
+
else
|
|
419
|
+
char = delim[0]
|
|
420
|
+
DELIMITER_CHAR_TO_SEMANTIC[char] || nil
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
353
424
|
def safe_content_to_string(content)
|
|
354
425
|
case content
|
|
355
426
|
when String
|
|
@@ -13,7 +13,7 @@ module Coradoc
|
|
|
13
13
|
|
|
14
14
|
class << self
|
|
15
15
|
def transform(model)
|
|
16
|
-
return model.map { |item| transform(item) } if model.is_a?(Array)
|
|
16
|
+
return model.map { |item| transform(item) }.compact if model.is_a?(Array)
|
|
17
17
|
return model unless model.is_a?(Coradoc::AsciiDoc::Model::Base)
|
|
18
18
|
|
|
19
19
|
transformer = Registry.lookup(model.class)
|
|
@@ -31,21 +31,23 @@ module Coradoc
|
|
|
31
31
|
when Coradoc::AsciiDoc::Model::Paragraph
|
|
32
32
|
transform_paragraph(model)
|
|
33
33
|
when Coradoc::AsciiDoc::Model::Block::SourceCode
|
|
34
|
-
|
|
34
|
+
transform_source_block(model)
|
|
35
35
|
when Coradoc::AsciiDoc::Model::Block::Quote
|
|
36
|
-
|
|
36
|
+
transform_typed_block(model, Coradoc::CoreModel::QuoteBlock)
|
|
37
37
|
when Coradoc::AsciiDoc::Model::Block::Example
|
|
38
|
-
|
|
38
|
+
transform_typed_block(model, Coradoc::CoreModel::ExampleBlock)
|
|
39
39
|
when Coradoc::AsciiDoc::Model::Block::Side
|
|
40
|
-
|
|
40
|
+
transform_typed_block(model, Coradoc::CoreModel::SidebarBlock)
|
|
41
41
|
when Coradoc::AsciiDoc::Model::Block::Literal
|
|
42
|
-
|
|
42
|
+
transform_typed_block(model, Coradoc::CoreModel::LiteralBlock)
|
|
43
43
|
when Coradoc::AsciiDoc::Model::Block::Open
|
|
44
|
-
|
|
44
|
+
transform_typed_block(model, Coradoc::CoreModel::OpenBlock)
|
|
45
45
|
when Coradoc::AsciiDoc::Model::Block::Pass
|
|
46
|
-
|
|
46
|
+
transform_typed_block(model, Coradoc::CoreModel::PassBlock)
|
|
47
|
+
when Coradoc::AsciiDoc::Model::Block::Listing
|
|
48
|
+
transform_typed_block(model, Coradoc::CoreModel::ListingBlock)
|
|
47
49
|
when Coradoc::AsciiDoc::Model::Block::Core
|
|
48
|
-
transform_block(model, model.delimiter)
|
|
50
|
+
transform_block(model, model.delimiter.to_s)
|
|
49
51
|
when Coradoc::AsciiDoc::Model::Table
|
|
50
52
|
transform_table(model)
|
|
51
53
|
when Coradoc::AsciiDoc::Model::TableRow
|
|
@@ -96,10 +98,12 @@ module Coradoc
|
|
|
96
98
|
|
|
97
99
|
def transform_document(doc)
|
|
98
100
|
title_text = extract_title_text(doc.header&.title)
|
|
101
|
+
attributes = extract_document_attributes(doc)
|
|
99
102
|
Coradoc::CoreModel::StructuralElement.new(
|
|
100
103
|
element_type: 'document',
|
|
101
104
|
id: doc.id,
|
|
102
105
|
title: title_text,
|
|
106
|
+
attributes: attributes,
|
|
103
107
|
children: transform(doc.sections || doc.contents || [])
|
|
104
108
|
)
|
|
105
109
|
end
|
|
@@ -123,33 +127,25 @@ module Coradoc
|
|
|
123
127
|
|
|
124
128
|
Coradoc::CoreModel::Block.new(
|
|
125
129
|
element_type: 'paragraph',
|
|
130
|
+
block_semantic_type: :paragraph,
|
|
126
131
|
id: para.id,
|
|
127
132
|
content: extract_text_content(para.content),
|
|
128
133
|
children: children
|
|
129
134
|
)
|
|
130
135
|
end
|
|
131
136
|
|
|
132
|
-
def
|
|
133
|
-
content_lines = Array(block.lines).
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
extract_core_model_text(transformed)
|
|
139
|
-
else
|
|
140
|
-
transformed.to_s
|
|
141
|
-
end
|
|
142
|
-
else
|
|
143
|
-
line.to_s
|
|
144
|
-
end
|
|
137
|
+
def transform_source_block(block)
|
|
138
|
+
content_lines = Array(block.lines).reject do |line|
|
|
139
|
+
line.is_a?(Coradoc::AsciiDoc::Model::LineBreak) ||
|
|
140
|
+
line.is_a?(Coradoc::AsciiDoc::Model::Break::PageBreak)
|
|
141
|
+
end.map do |line|
|
|
142
|
+
extract_text_content(line)
|
|
145
143
|
end.join("\n")
|
|
146
144
|
|
|
147
|
-
language = block
|
|
148
|
-
block.attributes&.positional&.first
|
|
145
|
+
language = extract_block_language(block)
|
|
149
146
|
|
|
150
|
-
Coradoc::CoreModel::
|
|
147
|
+
Coradoc::CoreModel::SourceBlock.new(
|
|
151
148
|
element_type: 'block',
|
|
152
|
-
delimiter_type: delimiter_type,
|
|
153
149
|
id: block.id,
|
|
154
150
|
title: extract_title_text(block.title),
|
|
155
151
|
content: content_lines,
|
|
@@ -157,6 +153,47 @@ module Coradoc
|
|
|
157
153
|
)
|
|
158
154
|
end
|
|
159
155
|
|
|
156
|
+
def transform_block(block, semantic_type_or_delimiter)
|
|
157
|
+
content_lines = extract_block_lines(block)
|
|
158
|
+
semantic_type = if semantic_type_or_delimiter.is_a?(Symbol)
|
|
159
|
+
semantic_type_or_delimiter
|
|
160
|
+
else
|
|
161
|
+
asciidoc_delimiter_to_semantic(semantic_type_or_delimiter)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
Coradoc::CoreModel::Block.new(
|
|
165
|
+
element_type: 'block',
|
|
166
|
+
block_semantic_type: semantic_type,
|
|
167
|
+
delimiter_type: semantic_type_or_delimiter.is_a?(String) ? semantic_type_or_delimiter : nil,
|
|
168
|
+
id: block.id,
|
|
169
|
+
title: extract_title_text(block.title),
|
|
170
|
+
content: content_lines,
|
|
171
|
+
language: extract_block_language(block)
|
|
172
|
+
)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def transform_typed_block(block, klass, extra_attrs = {})
|
|
176
|
+
content_lines = extract_block_lines(block)
|
|
177
|
+
|
|
178
|
+
klass.new(
|
|
179
|
+
element_type: 'block',
|
|
180
|
+
id: block.id,
|
|
181
|
+
title: extract_title_text(block.title),
|
|
182
|
+
content: content_lines,
|
|
183
|
+
language: extract_block_language(block),
|
|
184
|
+
**extra_attrs
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def extract_block_lines(block)
|
|
189
|
+
Array(block.lines).reject do |line|
|
|
190
|
+
line.is_a?(Coradoc::AsciiDoc::Model::LineBreak) ||
|
|
191
|
+
line.is_a?(Coradoc::AsciiDoc::Model::Break::PageBreak)
|
|
192
|
+
end.map do |line|
|
|
193
|
+
extract_text_content(line)
|
|
194
|
+
end.join("\n")
|
|
195
|
+
end
|
|
196
|
+
|
|
160
197
|
def transform_table(table)
|
|
161
198
|
rows = Array(table.rows).map do |row|
|
|
162
199
|
transform_table_row(row)
|
|
@@ -173,7 +210,10 @@ module Coradoc
|
|
|
173
210
|
cells = Array(row.columns).map do |cell|
|
|
174
211
|
transform_table_cell(cell)
|
|
175
212
|
end
|
|
176
|
-
Coradoc::CoreModel::TableRow.new(
|
|
213
|
+
Coradoc::CoreModel::TableRow.new(
|
|
214
|
+
cells: cells,
|
|
215
|
+
header: row.header
|
|
216
|
+
)
|
|
177
217
|
end
|
|
178
218
|
|
|
179
219
|
def transform_table_cell(cell)
|
|
@@ -317,6 +357,45 @@ module Coradoc
|
|
|
317
357
|
|
|
318
358
|
private
|
|
319
359
|
|
|
360
|
+
# AsciiDoc delimiters are any length of the same character (4+ for most, 2+ for open).
|
|
361
|
+
# We map by the first character to handle all lengths correctly.
|
|
362
|
+
ADOC_DELIMITER_CHAR_TO_SEMANTIC = {
|
|
363
|
+
'-' => :source_code,
|
|
364
|
+
'=' => :example,
|
|
365
|
+
'_' => :quote,
|
|
366
|
+
'*' => :sidebar,
|
|
367
|
+
'.' => :literal,
|
|
368
|
+
'+' => :pass
|
|
369
|
+
}.freeze
|
|
370
|
+
|
|
371
|
+
def asciidoc_delimiter_to_semantic(delimiter)
|
|
372
|
+
return :open if delimiter && delimiter.length < 4
|
|
373
|
+
|
|
374
|
+
char = delimiter&.[](0)
|
|
375
|
+
ADOC_DELIMITER_CHAR_TO_SEMANTIC[char] || :open
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def extract_document_attributes(doc)
|
|
379
|
+
return {} unless doc.document_attributes
|
|
380
|
+
|
|
381
|
+
doc.document_attributes.to_hash
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def extract_block_language(block)
|
|
385
|
+
lang = block.lang
|
|
386
|
+
return lang if lang.is_a?(String) && !lang.empty?
|
|
387
|
+
|
|
388
|
+
attrs = block.attributes
|
|
389
|
+
return nil unless attrs.is_a?(Coradoc::AsciiDoc::Model::AttributeList)
|
|
390
|
+
|
|
391
|
+
named_lang = attrs['language']
|
|
392
|
+
return named_lang.to_s if named_lang
|
|
393
|
+
|
|
394
|
+
# For [source,yaml], the language is the second positional attribute
|
|
395
|
+
positional = attrs.positional
|
|
396
|
+
positional[1]&.value&.to_s if positional.length > 1
|
|
397
|
+
end
|
|
398
|
+
|
|
320
399
|
def transform_inline_content(content)
|
|
321
400
|
return [] if content.nil?
|
|
322
401
|
|
|
@@ -35,25 +35,30 @@ module Coradoc
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def register_block_transformers!
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
[
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
38
|
+
Registry.register_with_priority(
|
|
39
|
+
Coradoc::AsciiDoc::Model::Block::SourceCode,
|
|
40
|
+
METHOD_DISPATCH[:transform_source_block],
|
|
41
|
+
priority: 10
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
Coradoc::AsciiDoc::Model::Block::Quote => Coradoc::CoreModel::QuoteBlock,
|
|
46
|
+
Coradoc::AsciiDoc::Model::Block::Example => Coradoc::CoreModel::ExampleBlock,
|
|
47
|
+
Coradoc::AsciiDoc::Model::Block::Side => Coradoc::CoreModel::SidebarBlock,
|
|
48
|
+
Coradoc::AsciiDoc::Model::Block::Literal => Coradoc::CoreModel::LiteralBlock,
|
|
49
|
+
Coradoc::AsciiDoc::Model::Block::Open => Coradoc::CoreModel::OpenBlock,
|
|
50
|
+
Coradoc::AsciiDoc::Model::Block::Pass => Coradoc::CoreModel::PassBlock
|
|
51
|
+
}.each do |block_class, core_model_class|
|
|
47
52
|
Registry.register_with_priority(
|
|
48
53
|
block_class,
|
|
49
|
-
|
|
54
|
+
typed_block_wrapper(core_model_class),
|
|
50
55
|
priority: 10
|
|
51
56
|
)
|
|
52
57
|
end
|
|
53
58
|
|
|
54
59
|
Registry.register(
|
|
55
60
|
Coradoc::AsciiDoc::Model::Block::Core,
|
|
56
|
-
|
|
61
|
+
block_model_wrapper
|
|
57
62
|
)
|
|
58
63
|
|
|
59
64
|
Registry.register(
|
|
@@ -182,7 +187,6 @@ module Coradoc
|
|
|
182
187
|
# Passthrough types (no CoreModel equivalent)
|
|
183
188
|
[
|
|
184
189
|
Coradoc::AsciiDoc::Model::TextElement,
|
|
185
|
-
Coradoc::AsciiDoc::Model::LineBreak,
|
|
186
190
|
Coradoc::AsciiDoc::Model::Include,
|
|
187
191
|
Coradoc::AsciiDoc::Model::Audio,
|
|
188
192
|
Coradoc::AsciiDoc::Model::Video,
|
|
@@ -191,18 +195,45 @@ module Coradoc
|
|
|
191
195
|
].each do |klass|
|
|
192
196
|
Registry.register(klass, ->(model) { model })
|
|
193
197
|
end
|
|
198
|
+
|
|
199
|
+
# Filtered types (layout-only, no CoreModel representation)
|
|
200
|
+
[
|
|
201
|
+
Coradoc::AsciiDoc::Model::LineBreak,
|
|
202
|
+
Coradoc::AsciiDoc::Model::Break::PageBreak
|
|
203
|
+
].each do |klass|
|
|
204
|
+
Registry.register(klass, ->(_model) { nil })
|
|
205
|
+
end
|
|
194
206
|
end
|
|
195
207
|
|
|
208
|
+
METHOD_DISPATCH = {
|
|
209
|
+
transform_document: ->(model) { ToCoreModel.transform_document(model) },
|
|
210
|
+
transform_section: ->(model) { ToCoreModel.transform_section(model) },
|
|
211
|
+
transform_paragraph: ->(model) { ToCoreModel.transform_paragraph(model) },
|
|
212
|
+
transform_source_block: ->(model) { ToCoreModel.transform_source_block(model) },
|
|
213
|
+
transform_link: ->(model) { ToCoreModel.transform_link(model) },
|
|
214
|
+
transform_cross_reference: ->(model) { ToCoreModel.transform_cross_reference(model) },
|
|
215
|
+
transform_inline_footnote: ->(model) { ToCoreModel.transform_inline_footnote(model) },
|
|
216
|
+
transform_stem: ->(model) { ToCoreModel.transform_stem(model) },
|
|
217
|
+
transform_table: ->(model) { ToCoreModel.transform_table(model) },
|
|
218
|
+
transform_table_row: ->(model) { ToCoreModel.transform_table_row(model) },
|
|
219
|
+
transform_table_cell: ->(model) { ToCoreModel.transform_table_cell(model) },
|
|
220
|
+
transform_term: ->(model) { ToCoreModel.transform_term(model) },
|
|
221
|
+
transform_admonition: ->(model) { ToCoreModel.transform_admonition(model) },
|
|
222
|
+
transform_image: ->(model) { ToCoreModel.transform_image(model) },
|
|
223
|
+
transform_bibliography: ->(model) { ToCoreModel.transform_bibliography(model) },
|
|
224
|
+
transform_bibliography_entry: ->(model) { ToCoreModel.transform_bibliography_entry(model) }
|
|
225
|
+
}.freeze
|
|
226
|
+
|
|
196
227
|
def method_wrapper(method_name)
|
|
197
|
-
|
|
228
|
+
METHOD_DISPATCH.fetch(method_name)
|
|
198
229
|
end
|
|
199
230
|
|
|
200
|
-
def
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
231
|
+
def typed_block_wrapper(klass)
|
|
232
|
+
->(model) { ToCoreModel.transform_typed_block(model, klass) }
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def block_model_wrapper
|
|
236
|
+
->(model) { ToCoreModel.transform_block(model, model.delimiter.to_s) }
|
|
206
237
|
end
|
|
207
238
|
|
|
208
239
|
def list_wrapper(marker_type)
|
|
@@ -65,7 +65,7 @@ module Coradoc
|
|
|
65
65
|
delim_char: simple(:delim_char),
|
|
66
66
|
rows: sequence(:rows)
|
|
67
67
|
) do
|
|
68
|
-
Model::Table.new(rows: rows)
|
|
68
|
+
Model::Table.new(rows: Transformer.regroup_table_rows(rows))
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# Table with rows and title
|
|
@@ -74,7 +74,7 @@ module Coradoc
|
|
|
74
74
|
delim_char: simple(:delim_char),
|
|
75
75
|
rows: sequence(:rows)
|
|
76
76
|
) do
|
|
77
|
-
Model::Table.new(title: title.to_s, rows: rows)
|
|
77
|
+
Model::Table.new(title: title.to_s, rows: Transformer.regroup_table_rows(rows))
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
# Table with rows and id
|
|
@@ -83,7 +83,7 @@ module Coradoc
|
|
|
83
83
|
delim_char: simple(:delim_char),
|
|
84
84
|
rows: sequence(:rows)
|
|
85
85
|
) do
|
|
86
|
-
Model::Table.new(id: id.to_s, rows: rows)
|
|
86
|
+
Model::Table.new(id: id.to_s, rows: Transformer.regroup_table_rows(rows))
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
# Table with rows, id, and attributes
|
|
@@ -93,7 +93,7 @@ module Coradoc
|
|
|
93
93
|
delim_char: simple(:delim_char),
|
|
94
94
|
rows: sequence(:rows)
|
|
95
95
|
) do
|
|
96
|
-
Model::Table.new(id: id.to_s, rows: rows, attrs: attrs)
|
|
96
|
+
Model::Table.new(id: id.to_s, rows: Transformer.regroup_table_rows(rows, attrs), attrs: attrs)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
99
|
# Table with rows, title, and attributes
|
|
@@ -103,7 +103,7 @@ module Coradoc
|
|
|
103
103
|
delim_char: simple(:delim_char),
|
|
104
104
|
rows: sequence(:rows)
|
|
105
105
|
) do
|
|
106
|
-
Model::Table.new(title: title.to_s, rows: rows, attrs: attrs)
|
|
106
|
+
Model::Table.new(title: title.to_s, rows: Transformer.regroup_table_rows(rows, attrs), attrs: attrs)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
# Table with rows and attributes only
|
|
@@ -112,7 +112,7 @@ module Coradoc
|
|
|
112
112
|
delim_char: simple(:delim_char),
|
|
113
113
|
rows: sequence(:rows)
|
|
114
114
|
) do
|
|
115
|
-
Model::Table.new(rows: rows, attrs: attrs)
|
|
115
|
+
Model::Table.new(rows: Transformer.regroup_table_rows(rows, attrs), attrs: attrs)
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
# Table with rows, id, title, and attributes (full set)
|
|
@@ -123,7 +123,8 @@ module Coradoc
|
|
|
123
123
|
delim_char: simple(:delim_char),
|
|
124
124
|
rows: sequence(:rows)
|
|
125
125
|
) do
|
|
126
|
-
Model::Table.new(id: id.to_s, title: title.to_s, rows: rows, attrs
|
|
126
|
+
Model::Table.new(id: id.to_s, title: title.to_s, rows: Transformer.regroup_table_rows(rows, attrs),
|
|
127
|
+
attrs: attrs)
|
|
127
128
|
end
|
|
128
129
|
|
|
129
130
|
# Table with id and title (no attributes)
|
|
@@ -133,7 +134,7 @@ module Coradoc
|
|
|
133
134
|
delim_char: simple(:delim_char),
|
|
134
135
|
rows: sequence(:rows)
|
|
135
136
|
) do
|
|
136
|
-
Model::Table.new(id: id.to_s, title: title.to_s, rows: rows)
|
|
137
|
+
Model::Table.new(id: id.to_s, title: title.to_s, rows: Transformer.regroup_table_rows(rows))
|
|
137
138
|
end
|
|
138
139
|
|
|
139
140
|
# Title
|
|
@@ -333,11 +333,9 @@ module Coradoc
|
|
|
333
333
|
|
|
334
334
|
# Infer column count from cells
|
|
335
335
|
# Look for patterns where rows have consistent cell counts
|
|
336
|
-
# Prefers LARGER valid column counts (more likely to be correct)
|
|
337
336
|
def self.infer_column_count(cells)
|
|
338
337
|
return nil if cells.nil? || cells.empty?
|
|
339
338
|
|
|
340
|
-
# Count column slots for each cell
|
|
341
339
|
col_slots = cells.map do |cell|
|
|
342
340
|
cell.is_a?(Model::TableCell) && cell.colspan ? cell.colspan : 1
|
|
343
341
|
end
|
|
@@ -349,7 +347,6 @@ module Coradoc
|
|
|
349
347
|
next false if candidate > total_cells
|
|
350
348
|
next false if total_cells % candidate != 0
|
|
351
349
|
|
|
352
|
-
# Verify that the cells distribute evenly
|
|
353
350
|
slots_used = 0
|
|
354
351
|
valid = true
|
|
355
352
|
|
|
@@ -366,11 +363,31 @@ module Coradoc
|
|
|
366
363
|
valid && slots_used.zero?
|
|
367
364
|
end
|
|
368
365
|
|
|
369
|
-
# Return the largest valid column count
|
|
370
|
-
# (more likely to represent actual table structure)
|
|
371
366
|
possible_cols.max || col_slots.first || 1
|
|
372
367
|
end
|
|
373
368
|
|
|
369
|
+
# Regroup parser-level rows into proper AsciiDoc rows.
|
|
370
|
+
# The parser produces one "row" per line; this flattens all cells
|
|
371
|
+
# and regroups by the cols attribute, then marks the first row as header.
|
|
372
|
+
#
|
|
373
|
+
# @param rows [Array<Model::TableRow>] Parser-level rows
|
|
374
|
+
# @param attrs [Model::AttributeList, nil] Table attributes containing cols
|
|
375
|
+
# @return [Array<Model::TableRow>] Properly grouped rows with header flag
|
|
376
|
+
def self.regroup_table_rows(rows, attrs = nil)
|
|
377
|
+
return rows if rows.nil? || rows.empty?
|
|
378
|
+
|
|
379
|
+
col_count = parse_cols_attribute(attrs)
|
|
380
|
+
all_cells = rows.flat_map do |r|
|
|
381
|
+
r.is_a?(Model::TableRow) ? r.columns : []
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
return rows if all_cells.empty?
|
|
385
|
+
|
|
386
|
+
grouped = group_cells_into_rows(all_cells, col_count)
|
|
387
|
+
grouped.first.header = true unless grouped.empty?
|
|
388
|
+
grouped
|
|
389
|
+
end
|
|
390
|
+
|
|
374
391
|
# Transform a syntax tree using this transformer's rules
|
|
375
392
|
#
|
|
376
393
|
# @param syntax_tree [Hash, Array] The AST from the parser
|
|
@@ -15,9 +15,14 @@ module Coradoc
|
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
#
|
|
18
|
+
# Autoload version and parse error
|
|
19
19
|
require_relative 'asciidoc/version'
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
module Coradoc
|
|
22
|
+
module AsciiDoc
|
|
23
|
+
autoload :ParseError, "#{__dir__}/asciidoc/parse_error"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
21
26
|
|
|
22
27
|
# Autoload main components (lazy loading)
|
|
23
28
|
module Coradoc
|