coradoc-markdown 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/lib/coradoc/markdown/model/admonition.rb +35 -0
- data/lib/coradoc/markdown/model/attribute_list.rb +5 -16
- data/lib/coradoc/markdown/model/base.rb +2 -34
- data/lib/coradoc/markdown/model/comment.rb +14 -0
- data/lib/coradoc/markdown/model/cross_reference.rb +10 -0
- data/lib/coradoc/markdown/model/definition_list.rb +0 -12
- data/lib/coradoc/markdown/model/definition_term.rb +16 -6
- data/lib/coradoc/markdown/model/document.rb +9 -0
- data/lib/coradoc/markdown/model/example_block.rb +26 -0
- data/lib/coradoc/markdown/model/extension.rb +9 -18
- data/lib/coradoc/markdown/model/footnote_reference.rb +0 -5
- data/lib/coradoc/markdown/model/hard_line_break.rb +21 -0
- data/lib/coradoc/markdown/model/highlight.rb +0 -5
- data/lib/coradoc/markdown/model/horizontal_rule.rb +1 -6
- data/lib/coradoc/markdown/model/list_item.rb +1 -1
- data/lib/coradoc/markdown/model/literal.rb +21 -0
- data/lib/coradoc/markdown/model/math.rb +0 -14
- data/lib/coradoc/markdown/model/named_value.rb +18 -0
- data/lib/coradoc/markdown/model/open_block.rb +22 -0
- data/lib/coradoc/markdown/model/paragraph.rb +2 -2
- data/lib/coradoc/markdown/model/pass.rb +21 -0
- data/lib/coradoc/markdown/model/sidebar.rb +22 -0
- data/lib/coradoc/markdown/model/strikethrough.rb +0 -5
- data/lib/coradoc/markdown/model/subscript.rb +9 -0
- data/lib/coradoc/markdown/model/superscript.rb +9 -0
- data/lib/coradoc/markdown/model/underline.rb +9 -0
- data/lib/coradoc/markdown/model/verse.rb +27 -0
- data/lib/coradoc/markdown/parser/block_parser.rb +1 -1
- data/lib/coradoc/markdown/parser/frontmatter_parser.rb +23 -0
- data/lib/coradoc/markdown/serializer/builder.rb +57 -0
- data/lib/coradoc/markdown/serializer/config.rb +77 -0
- data/lib/coradoc/markdown/serializer/context.rb +66 -0
- data/lib/coradoc/markdown/serializer/element_serializer.rb +46 -0
- data/lib/coradoc/markdown/serializer/flavor.rb +82 -0
- data/lib/coradoc/markdown/serializer/registrations.rb +111 -0
- data/lib/coradoc/markdown/serializer/registry.rb +62 -0
- data/lib/coradoc/markdown/serializer/runner.rb +84 -0
- data/lib/coradoc/markdown/serializer/serializers/abbreviation.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/admonition.rb +20 -0
- data/lib/coradoc/markdown/serializer/serializers/attribute_list.rb +25 -0
- data/lib/coradoc/markdown/serializer/serializers/blockquote.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/code.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/code_block.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/comment.rb +31 -0
- data/lib/coradoc/markdown/serializer/serializers/cross_reference.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/definition_list.rb +20 -0
- data/lib/coradoc/markdown/serializer/serializers/document.rb +22 -0
- data/lib/coradoc/markdown/serializer/serializers/emphasis.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/example_block.rb +40 -0
- data/lib/coradoc/markdown/serializer/serializers/extension.rb +30 -0
- data/lib/coradoc/markdown/serializer/serializers/footnote.rb +20 -0
- data/lib/coradoc/markdown/serializer/serializers/footnote_reference.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/hard_line_break.rb +22 -0
- data/lib/coradoc/markdown/serializer/serializers/heading.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/highlight.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/horizontal_rule.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/image.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/link.rb +29 -0
- data/lib/coradoc/markdown/serializer/serializers/list.rb +45 -0
- data/lib/coradoc/markdown/serializer/serializers/literal.rb +21 -0
- data/lib/coradoc/markdown/serializer/serializers/math.rb +23 -0
- data/lib/coradoc/markdown/serializer/serializers/open_block.rb +38 -0
- data/lib/coradoc/markdown/serializer/serializers/paragraph.rb +23 -0
- data/lib/coradoc/markdown/serializer/serializers/pass.rb +21 -0
- data/lib/coradoc/markdown/serializer/serializers/sidebar.rb +20 -0
- data/lib/coradoc/markdown/serializer/serializers/strikethrough.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/strong.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/subscript.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/superscript.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/table.rb +37 -0
- data/lib/coradoc/markdown/serializer/serializers/underline.rb +19 -0
- data/lib/coradoc/markdown/serializer/serializers/verse.rb +31 -0
- data/lib/coradoc/markdown/serializer/strategies/admonition/base.rb +30 -0
- data/lib/coradoc/markdown/serializer/strategies/admonition/container.rb +34 -0
- data/lib/coradoc/markdown/serializer/strategies/admonition/gfm_alert.rb +28 -0
- data/lib/coradoc/markdown/serializer/strategies/admonition/github.rb +29 -0
- data/lib/coradoc/markdown/serializer/strategies/admonition/html.rb +25 -0
- data/lib/coradoc/markdown/serializer/strategies/admonition/registry.rb +50 -0
- data/lib/coradoc/markdown/serializer/strategies/autolink/angle.rb +35 -0
- data/lib/coradoc/markdown/serializer/strategies/autolink/bare.rb +23 -0
- data/lib/coradoc/markdown/serializer/strategies/autolink/base.rb +33 -0
- data/lib/coradoc/markdown/serializer/strategies/autolink/none.rb +27 -0
- data/lib/coradoc/markdown/serializer/strategies/autolink/registry.rb +58 -0
- data/lib/coradoc/markdown/serializer/strategies/definition_list/base.rb +37 -0
- data/lib/coradoc/markdown/serializer/strategies/definition_list/flat.rb +48 -0
- data/lib/coradoc/markdown/serializer/strategies/definition_list/nested_html.rb +54 -0
- data/lib/coradoc/markdown/serializer/strategies/definition_list/registry.rb +37 -0
- data/lib/coradoc/markdown/serializer.rb +30 -181
- data/lib/coradoc/markdown/toc_generator.rb +2 -8
- data/lib/coradoc/markdown/transform/block_transformer.rb +163 -0
- data/lib/coradoc/markdown/transform/from_core_model.rb +205 -40
- data/lib/coradoc/markdown/transform/image_transformer.rb +20 -0
- data/lib/coradoc/markdown/transform/inline_transformer.rb +74 -0
- data/lib/coradoc/markdown/transform/list_transformer.rb +52 -0
- data/lib/coradoc/markdown/transform/structural_transformer.rb +94 -0
- data/lib/coradoc/markdown/transform/table_transformer.rb +40 -0
- data/lib/coradoc/markdown/transform/to_core_model.rb +36 -30
- data/lib/coradoc/markdown/transformer.rb +87 -2
- data/lib/coradoc/markdown/version.rb +1 -1
- data/lib/coradoc/markdown.rb +23 -20
- metadata +89 -10
|
@@ -20,6 +20,9 @@ module Coradoc
|
|
|
20
20
|
when Coradoc::CoreModel::AnnotationBlock
|
|
21
21
|
# Must be checked before Block since AnnotationBlock < Block
|
|
22
22
|
transform_annotation_block(model)
|
|
23
|
+
when Coradoc::CoreModel::CommentBlock
|
|
24
|
+
# Must be checked before Block since CommentBlock < Block
|
|
25
|
+
Coradoc::Markdown::Comment.new(text: model.content.to_s)
|
|
23
26
|
when Coradoc::CoreModel::Block
|
|
24
27
|
transform_block(model)
|
|
25
28
|
when Coradoc::CoreModel::ListBlock
|
|
@@ -48,8 +51,12 @@ module Coradoc
|
|
|
48
51
|
transform_bibliography_entry(model)
|
|
49
52
|
when Coradoc::CoreModel::TocEntry
|
|
50
53
|
Coradoc::Markdown::Text.new(content: model.title.to_s)
|
|
54
|
+
when Coradoc::CoreModel::CommentLine
|
|
55
|
+
Coradoc::Markdown::Comment.new(text: model.text.to_s)
|
|
56
|
+
when Coradoc::CoreModel::TextContent
|
|
57
|
+
model.text.to_s
|
|
51
58
|
when Array
|
|
52
|
-
model.
|
|
59
|
+
model.flat_map { |item| flatten_result(transform(item)) }
|
|
53
60
|
else
|
|
54
61
|
model
|
|
55
62
|
end
|
|
@@ -58,10 +65,10 @@ module Coradoc
|
|
|
58
65
|
private
|
|
59
66
|
|
|
60
67
|
def transform_structural_element(element)
|
|
61
|
-
case element
|
|
62
|
-
when
|
|
68
|
+
case element
|
|
69
|
+
when CoreModel::DocumentElement
|
|
63
70
|
transform_document(element)
|
|
64
|
-
when
|
|
71
|
+
when CoreModel::SectionElement
|
|
65
72
|
transform_section(element)
|
|
66
73
|
else
|
|
67
74
|
transform_generic_element(element)
|
|
@@ -69,23 +76,39 @@ module Coradoc
|
|
|
69
76
|
end
|
|
70
77
|
|
|
71
78
|
def transform_document(doc)
|
|
72
|
-
blocks = Array(doc.children)
|
|
79
|
+
blocks, frontmatter = extract_frontmatter(Array(doc.children))
|
|
80
|
+
blocks = blocks.flat_map { |child| flatten_result(transform(child)) }
|
|
73
81
|
|
|
74
82
|
Coradoc::Markdown::Document.new(
|
|
75
83
|
id: doc.id,
|
|
76
|
-
blocks: blocks
|
|
84
|
+
blocks: blocks,
|
|
85
|
+
frontmatter: frontmatter
|
|
77
86
|
)
|
|
78
87
|
end
|
|
79
88
|
|
|
89
|
+
# If the first CoreModel child is a FrontmatterBlock, serialize
|
|
90
|
+
# it to YAML text via Codec (single source of truth) and pop
|
|
91
|
+
# it from the children list. Returns [remaining_children,
|
|
92
|
+
# frontmatter_text].
|
|
93
|
+
def extract_frontmatter(children)
|
|
94
|
+
first = children.first
|
|
95
|
+
return [children, nil] unless first.is_a?(CoreModel::FrontmatterBlock)
|
|
96
|
+
|
|
97
|
+
yaml = CoreModel::FrontmatterBlock::Codec.to_yaml(first)
|
|
98
|
+
[children.drop(1), yaml.nil? || yaml.empty? ? nil : yaml]
|
|
99
|
+
end
|
|
100
|
+
|
|
80
101
|
def transform_section(section)
|
|
81
|
-
Coradoc::Markdown::Heading.new(
|
|
102
|
+
heading = Coradoc::Markdown::Heading.new(
|
|
82
103
|
level: section.level || 1,
|
|
83
104
|
text: section.title.to_s
|
|
84
105
|
)
|
|
106
|
+
child_blocks = Array(section.children).map { |child| transform(child) }
|
|
107
|
+
[heading, *child_blocks]
|
|
85
108
|
end
|
|
86
109
|
|
|
87
110
|
def transform_generic_element(element)
|
|
88
|
-
blocks = Array(element.children).
|
|
111
|
+
blocks = Array(element.children).flat_map { |child| flatten_result(transform(child)) }
|
|
89
112
|
|
|
90
113
|
Coradoc::Markdown::Document.new(
|
|
91
114
|
id: element.id,
|
|
@@ -94,11 +117,12 @@ module Coradoc
|
|
|
94
117
|
end
|
|
95
118
|
|
|
96
119
|
def transform_block(block)
|
|
97
|
-
|
|
98
|
-
|
|
120
|
+
semantic = block.resolve_semantic_type
|
|
121
|
+
case semantic
|
|
122
|
+
when :paragraph
|
|
99
123
|
transform_paragraph(block)
|
|
100
|
-
when
|
|
101
|
-
Coradoc::Markdown::
|
|
124
|
+
when :comment
|
|
125
|
+
Coradoc::Markdown::Comment.new(text: block.content.to_s)
|
|
102
126
|
else
|
|
103
127
|
transform_delimited_block(block)
|
|
104
128
|
end
|
|
@@ -106,8 +130,17 @@ module Coradoc
|
|
|
106
130
|
|
|
107
131
|
def transform_paragraph(block)
|
|
108
132
|
content = block.renderable_content
|
|
109
|
-
|
|
110
|
-
|
|
133
|
+
has_nested_blocks = content.is_a?(Array) && content.any? do |c|
|
|
134
|
+
c.is_a?(CoreModel::Block) || c.is_a?(CoreModel::StructuralElement)
|
|
135
|
+
end
|
|
136
|
+
if has_nested_blocks
|
|
137
|
+
content.filter_map do |c|
|
|
138
|
+
next c.text if c.is_a?(CoreModel::TextContent)
|
|
139
|
+
next nil if c.is_a?(String) && c.strip.empty?
|
|
140
|
+
|
|
141
|
+
transform(c)
|
|
142
|
+
end.flat_map { |c| flatten_result(c) }
|
|
143
|
+
elsif content.is_a?(Array) && content.any? { |c| !c.is_a?(CoreModel::TextContent) }
|
|
111
144
|
children = content.map { |c| transform_inline_content(c) }
|
|
112
145
|
Coradoc::Markdown::Paragraph.new(text: block.flat_text, children: children)
|
|
113
146
|
else
|
|
@@ -119,8 +152,14 @@ module Coradoc
|
|
|
119
152
|
case element
|
|
120
153
|
when Coradoc::CoreModel::InlineElement
|
|
121
154
|
transform_inline(element)
|
|
155
|
+
when CoreModel::TextContent
|
|
156
|
+
element.text
|
|
157
|
+
when CoreModel::Base
|
|
158
|
+
transform(element)
|
|
122
159
|
when String
|
|
123
160
|
element
|
|
161
|
+
when Array
|
|
162
|
+
element.map { |e| transform_inline_content(e) }
|
|
124
163
|
else
|
|
125
164
|
element.to_s
|
|
126
165
|
end
|
|
@@ -132,19 +171,97 @@ module Coradoc
|
|
|
132
171
|
case semantic
|
|
133
172
|
when :source_code, :listing
|
|
134
173
|
transform_code_block(block)
|
|
135
|
-
when :quote
|
|
174
|
+
when :quote
|
|
136
175
|
transform_blockquote(block)
|
|
176
|
+
when :verse
|
|
177
|
+
transform_verse_block(block)
|
|
137
178
|
when :horizontal_rule
|
|
138
179
|
transform_horizontal_rule(block)
|
|
139
180
|
when :pass
|
|
140
|
-
|
|
181
|
+
transform_pass_block(block)
|
|
141
182
|
when :literal
|
|
142
|
-
|
|
183
|
+
transform_literal_block(block)
|
|
184
|
+
when :example
|
|
185
|
+
transform_example_block(block)
|
|
186
|
+
when :sidebar
|
|
187
|
+
transform_sidebar_block(block)
|
|
188
|
+
when :open
|
|
189
|
+
transform_open_block(block)
|
|
190
|
+
when :reviewer
|
|
191
|
+
transform_admonition_block(block, default_type: 'reviewer')
|
|
143
192
|
else
|
|
144
193
|
transform_paragraph(block)
|
|
145
194
|
end
|
|
146
195
|
end
|
|
147
196
|
|
|
197
|
+
def transform_container_block(block)
|
|
198
|
+
rc = block.renderable_content
|
|
199
|
+
if rc.is_a?(Array) && rc.any? { |c| c.is_a?(CoreModel::Block) || c.is_a?(CoreModel::ListBlock) }
|
|
200
|
+
rc.filter_map do |c|
|
|
201
|
+
next c.text if c.is_a?(CoreModel::TextContent)
|
|
202
|
+
next nil if c.is_a?(String) && c.strip.empty?
|
|
203
|
+
|
|
204
|
+
transform(c)
|
|
205
|
+
end.flat_map { |c| flatten_result(c) }
|
|
206
|
+
else
|
|
207
|
+
Coradoc::Markdown::Blockquote.new(content: block.flat_text)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def transform_verse_block(block)
|
|
212
|
+
Coradoc::Markdown::Verse.new(
|
|
213
|
+
content: block.flat_text,
|
|
214
|
+
attribution: block.respond_to?(:attribution) ? block.attribution : nil
|
|
215
|
+
)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def transform_pass_block(block)
|
|
219
|
+
return Coradoc::Markdown::Math.block(block.content.to_s) if block.language == 'latexmath'
|
|
220
|
+
|
|
221
|
+
Coradoc::Markdown::Pass.new(content: block.content.to_s)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def transform_literal_block(block)
|
|
225
|
+
Coradoc::Markdown::Literal.new(content: block.content.to_s)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def transform_example_block(block)
|
|
229
|
+
Coradoc::Markdown::ExampleBlock.new(
|
|
230
|
+
content: block.flat_text,
|
|
231
|
+
caption: block.title.to_s
|
|
232
|
+
)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def transform_sidebar_block(block)
|
|
236
|
+
Coradoc::Markdown::Sidebar.new(
|
|
237
|
+
content: block.flat_text,
|
|
238
|
+
title: block.title.to_s
|
|
239
|
+
)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def transform_open_block(block)
|
|
243
|
+
children = Array(block.children).map { |c| transform(c) }.flat_map { |c| flatten_result(c) }
|
|
244
|
+
children = paragraphs_from_content(block.content) if children.empty?
|
|
245
|
+
Coradoc::Markdown::OpenBlock.new(
|
|
246
|
+
children: children,
|
|
247
|
+
id: block.id
|
|
248
|
+
)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def paragraphs_from_content(content)
|
|
252
|
+
content.to_s.split(/\n\s*\n/).map do |chunk|
|
|
253
|
+
Coradoc::Markdown::Paragraph.new(text: chunk.strip)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def transform_admonition_block(block, default_type: 'note')
|
|
258
|
+
Coradoc::Markdown::Admonition.new(
|
|
259
|
+
admonition_type: block.respond_to?(:annotation_type) ? (block.annotation_type || default_type) : default_type,
|
|
260
|
+
content: block.flat_text,
|
|
261
|
+
title: block.respond_to?(:annotation_label) ? block.annotation_label : nil
|
|
262
|
+
)
|
|
263
|
+
end
|
|
264
|
+
|
|
148
265
|
def resolve_markdown_semantic(block)
|
|
149
266
|
# Polymorphic dispatch: typed classes override semantic_type
|
|
150
267
|
semantic = block.resolve_semantic_type
|
|
@@ -160,15 +277,25 @@ module Coradoc
|
|
|
160
277
|
when '>' then :quote
|
|
161
278
|
when '---', '***', '___' then :horizontal_rule
|
|
162
279
|
when '++++' then :pass
|
|
163
|
-
else nil
|
|
164
280
|
end
|
|
165
281
|
end
|
|
166
282
|
|
|
167
283
|
def transform_code_block(block)
|
|
168
|
-
|
|
169
|
-
|
|
284
|
+
code = CoreModel::CalloutText.strip_markers(block.content.to_s, block.callouts)
|
|
285
|
+
code_block = Coradoc::Markdown::CodeBlock.new(
|
|
286
|
+
code: code,
|
|
170
287
|
language: block.language
|
|
171
288
|
)
|
|
289
|
+
return code_block if block.callouts.nil? || block.callouts.empty?
|
|
290
|
+
|
|
291
|
+
[code_block, transform_callout_list(block.callouts)]
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def transform_callout_list(callouts)
|
|
295
|
+
items = CoreModel::CalloutText.ordered(callouts).map do |callout|
|
|
296
|
+
Coradoc::Markdown::ListItem.new(text: callout.content.to_s)
|
|
297
|
+
end
|
|
298
|
+
Coradoc::Markdown::List.new(ordered: true, items: items)
|
|
172
299
|
end
|
|
173
300
|
|
|
174
301
|
def transform_blockquote(block)
|
|
@@ -178,18 +305,21 @@ module Coradoc
|
|
|
178
305
|
end
|
|
179
306
|
|
|
180
307
|
def transform_horizontal_rule(_block)
|
|
181
|
-
Coradoc::Markdown::HorizontalRule.new
|
|
308
|
+
Coradoc::Markdown::HorizontalRule.new(style: '---')
|
|
182
309
|
end
|
|
183
310
|
|
|
184
311
|
def transform_list(list)
|
|
185
312
|
items = Array(list.items).map do |item|
|
|
186
313
|
content = item.renderable_content
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
314
|
+
has_structured = content.is_a?(Array) && content.any? { |c| !c.is_a?(CoreModel::TextContent) }
|
|
315
|
+
md_item = if has_structured
|
|
316
|
+
children = content.map { |c| transform_inline_content(c) }
|
|
317
|
+
Coradoc::Markdown::ListItem.new(text: item.flat_text, children: children)
|
|
318
|
+
else
|
|
319
|
+
Coradoc::Markdown::ListItem.new(text: item.flat_text)
|
|
320
|
+
end
|
|
321
|
+
md_item.sublist = transform_list(item.nested_list) if item.nested_list
|
|
322
|
+
md_item
|
|
193
323
|
end
|
|
194
324
|
|
|
195
325
|
Coradoc::Markdown::List.new(
|
|
@@ -208,8 +338,8 @@ module Coradoc
|
|
|
208
338
|
first_row = table_rows.first
|
|
209
339
|
first_row_cells = Array(first_row&.cells)
|
|
210
340
|
|
|
211
|
-
# Check if first row
|
|
212
|
-
if first_row_cells.any?(&:header)
|
|
341
|
+
# Check if first row is marked as header, or if any of its cells are header cells
|
|
342
|
+
if first_row&.header || first_row_cells.any?(&:header)
|
|
213
343
|
headers = first_row_cells.map(&:flat_text)
|
|
214
344
|
table_rows = table_rows[1..] || []
|
|
215
345
|
end
|
|
@@ -234,7 +364,7 @@ module Coradoc
|
|
|
234
364
|
end
|
|
235
365
|
|
|
236
366
|
def transform_inline(element)
|
|
237
|
-
case element.
|
|
367
|
+
case element.resolve_format_type
|
|
238
368
|
when 'bold'
|
|
239
369
|
Coradoc::Markdown::Strong.new(text: element.content.to_s)
|
|
240
370
|
when 'italic'
|
|
@@ -255,13 +385,16 @@ module Coradoc
|
|
|
255
385
|
when 'strikethrough'
|
|
256
386
|
Coradoc::Markdown::Strikethrough.new(text: element.content.to_s)
|
|
257
387
|
when 'subscript'
|
|
258
|
-
|
|
388
|
+
Coradoc::Markdown::Subscript.new(text: element.content.to_s)
|
|
259
389
|
when 'superscript'
|
|
260
|
-
|
|
390
|
+
Coradoc::Markdown::Superscript.new(text: element.content.to_s)
|
|
261
391
|
when 'underline'
|
|
262
|
-
|
|
392
|
+
Coradoc::Markdown::Underline.new(text: element.content.to_s)
|
|
263
393
|
when 'xref'
|
|
264
|
-
|
|
394
|
+
Coradoc::Markdown::CrossReference.new(
|
|
395
|
+
text: element.content.to_s,
|
|
396
|
+
target: element.target.to_s
|
|
397
|
+
)
|
|
265
398
|
else
|
|
266
399
|
element.content.to_s
|
|
267
400
|
end
|
|
@@ -272,9 +405,11 @@ module Coradoc
|
|
|
272
405
|
definitions = Array(item.definitions).map do |defn|
|
|
273
406
|
Coradoc::Markdown::DefinitionItem.new(content: defn.to_s)
|
|
274
407
|
end
|
|
408
|
+
nested = item.nested ? transform_definition_list(item.nested) : nil
|
|
275
409
|
Coradoc::Markdown::DefinitionTerm.new(
|
|
276
410
|
text: item.term.to_s,
|
|
277
|
-
definitions: definitions
|
|
411
|
+
definitions: definitions,
|
|
412
|
+
nested: nested
|
|
278
413
|
)
|
|
279
414
|
end
|
|
280
415
|
|
|
@@ -301,10 +436,7 @@ module Coradoc
|
|
|
301
436
|
end
|
|
302
437
|
|
|
303
438
|
def transform_annotation_block(annotation)
|
|
304
|
-
|
|
305
|
-
Coradoc::Markdown::Paragraph.new(
|
|
306
|
-
text: "**#{annotation.annotation_type}:** #{text}"
|
|
307
|
-
)
|
|
439
|
+
transform_admonition_block(annotation, default_type: 'note')
|
|
308
440
|
end
|
|
309
441
|
|
|
310
442
|
def transform_bibliography(bib)
|
|
@@ -316,7 +448,40 @@ module Coradoc
|
|
|
316
448
|
end
|
|
317
449
|
|
|
318
450
|
def transform_bibliography_entry(entry)
|
|
319
|
-
|
|
451
|
+
text = entry.display_text.to_s
|
|
452
|
+
text = convert_asciidoc_markers_to_markdown(text)
|
|
453
|
+
Coradoc::Markdown::Paragraph.new(text: text)
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
def convert_asciidoc_markers_to_markdown(text)
|
|
457
|
+
return '' if text.nil?
|
|
458
|
+
|
|
459
|
+
result = text.dup
|
|
460
|
+
|
|
461
|
+
# footnote:[text] -> ^[text]
|
|
462
|
+
result.gsub!(/footnote:\[(.*?)\]/, '^[\1]')
|
|
463
|
+
|
|
464
|
+
# [smallcap]#text# -> text
|
|
465
|
+
result.gsub!(/\[smallcap\]#(.*?)#/, '\1')
|
|
466
|
+
|
|
467
|
+
# *text* -> **text**
|
|
468
|
+
# Use negative lookbehind and lookahead to avoid replacing **text** to ****text****
|
|
469
|
+
result.gsub!(/(?<!\*)\*(.*?)\*(?!\*)/, '**\1**')
|
|
470
|
+
|
|
471
|
+
# _text_ -> *text*
|
|
472
|
+
# Use negative lookbehind and lookahead to avoid replacing __text__ to **text**
|
|
473
|
+
result.gsub!(/(?<!_)_(.*?)_(?!_)/, '*\1*')
|
|
474
|
+
|
|
475
|
+
result
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def flatten_result(result)
|
|
479
|
+
case result
|
|
480
|
+
when Array
|
|
481
|
+
result.flat_map { |r| flatten_result(r) }
|
|
482
|
+
else
|
|
483
|
+
[result]
|
|
484
|
+
end
|
|
320
485
|
end
|
|
321
486
|
end
|
|
322
487
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
module Transform
|
|
6
|
+
module ImageTransformer
|
|
7
|
+
class << self
|
|
8
|
+
def transform_image(image)
|
|
9
|
+
Coradoc::Markdown::Image.new(
|
|
10
|
+
src: image.src,
|
|
11
|
+
alt: image.alt.to_s
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
FromCoreModel.register(CoreModel::Image, method(:transform_image))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
module Transform
|
|
6
|
+
module InlineTransformer
|
|
7
|
+
class << self
|
|
8
|
+
def transform_inline(element)
|
|
9
|
+
case element.resolve_format_type
|
|
10
|
+
when 'bold'
|
|
11
|
+
Coradoc::Markdown::Strong.new(text: element.content.to_s)
|
|
12
|
+
when 'italic'
|
|
13
|
+
Coradoc::Markdown::Emphasis.new(text: element.content.to_s)
|
|
14
|
+
when 'monospace'
|
|
15
|
+
Coradoc::Markdown::Code.new(text: element.content.to_s)
|
|
16
|
+
when 'link'
|
|
17
|
+
Coradoc::Markdown::Link.new(
|
|
18
|
+
text: element.content.to_s,
|
|
19
|
+
url: element.target.to_s
|
|
20
|
+
)
|
|
21
|
+
when 'footnote'
|
|
22
|
+
Coradoc::Markdown::FootnoteReference.new(id: element.target.to_s)
|
|
23
|
+
when 'stem'
|
|
24
|
+
Coradoc::Markdown::Math.inline(element.content.to_s)
|
|
25
|
+
when 'highlight'
|
|
26
|
+
Coradoc::Markdown::Highlight.new(text: element.content.to_s)
|
|
27
|
+
when 'strikethrough'
|
|
28
|
+
Coradoc::Markdown::Strikethrough.new(text: element.content.to_s)
|
|
29
|
+
when 'subscript'
|
|
30
|
+
Coradoc::Markdown::Subscript.new(text: element.content.to_s)
|
|
31
|
+
when 'superscript'
|
|
32
|
+
Coradoc::Markdown::Superscript.new(text: element.content.to_s)
|
|
33
|
+
when 'underline'
|
|
34
|
+
Coradoc::Markdown::Underline.new(text: element.content.to_s)
|
|
35
|
+
when 'xref'
|
|
36
|
+
Coradoc::Markdown::CrossReference.new(
|
|
37
|
+
text: element.content.to_s,
|
|
38
|
+
target: element.target.to_s
|
|
39
|
+
)
|
|
40
|
+
else
|
|
41
|
+
element.content.to_s
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def transform_footnote(fn)
|
|
46
|
+
Coradoc::Markdown::Footnote.new(
|
|
47
|
+
id: fn.id.to_s,
|
|
48
|
+
content: fn.content.to_s,
|
|
49
|
+
backlink: fn.backlink
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def transform_footnote_reference(ref)
|
|
54
|
+
Coradoc::Markdown::FootnoteReference.new(id: ref.id.to_s)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def transform_abbreviation(abbr)
|
|
58
|
+
Coradoc::Markdown::Abbreviation.new(
|
|
59
|
+
term: abbr.term.to_s,
|
|
60
|
+
definition: abbr.definition.to_s
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
FromCoreModel.register(CoreModel::InlineElement, method(:transform_inline))
|
|
66
|
+
FromCoreModel.register(CoreModel::Footnote, method(:transform_footnote))
|
|
67
|
+
FromCoreModel.register(CoreModel::FootnoteReference, method(:transform_footnote_reference))
|
|
68
|
+
FromCoreModel.register(CoreModel::Abbreviation, method(:transform_abbreviation))
|
|
69
|
+
FromCoreModel.register(CoreModel::TextContent, lambda(&:text))
|
|
70
|
+
FromCoreModel.register(CoreModel::Term, ->(m) { Coradoc::Markdown::Strong.new(text: m.text.to_s) })
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
module Transform
|
|
6
|
+
module ListTransformer
|
|
7
|
+
class << self
|
|
8
|
+
def transform_list(list)
|
|
9
|
+
items = Array(list.items).map do |item|
|
|
10
|
+
transform_list_item(item)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Coradoc::Markdown::List.new(
|
|
14
|
+
ordered: list.marker_type == 'ordered',
|
|
15
|
+
items: items
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def transform_list_item(item)
|
|
20
|
+
content = item.renderable_content
|
|
21
|
+
has_structured = content.is_a?(Array) && content.any? do |c|
|
|
22
|
+
!c.is_a?(CoreModel::TextContent)
|
|
23
|
+
end
|
|
24
|
+
if has_structured
|
|
25
|
+
children = content.map { |c| BlockTransformer.transform_content_node(c) }
|
|
26
|
+
Coradoc::Markdown::ListItem.new(text: item.flat_text, children: children)
|
|
27
|
+
else
|
|
28
|
+
Coradoc::Markdown::ListItem.new(text: item.flat_text)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def transform_definition_list(dl)
|
|
33
|
+
items = Array(dl.items).map do |item|
|
|
34
|
+
definitions = Array(item.definitions).map do |defn|
|
|
35
|
+
Coradoc::Markdown::DefinitionItem.new(content: defn.to_s)
|
|
36
|
+
end
|
|
37
|
+
Coradoc::Markdown::DefinitionTerm.new(
|
|
38
|
+
text: item.term.to_s,
|
|
39
|
+
definitions: definitions
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Coradoc::Markdown::DefinitionList.new(items: items)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
FromCoreModel.register(CoreModel::ListBlock, method(:transform_list))
|
|
48
|
+
FromCoreModel.register(CoreModel::DefinitionList, method(:transform_definition_list))
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
module Transform
|
|
6
|
+
module StructuralTransformer
|
|
7
|
+
class << self
|
|
8
|
+
def transform_structural_element(element)
|
|
9
|
+
case element
|
|
10
|
+
when CoreModel::DocumentElement
|
|
11
|
+
transform_document(element)
|
|
12
|
+
when CoreModel::SectionElement
|
|
13
|
+
transform_section(element)
|
|
14
|
+
when CoreModel::PreambleElement
|
|
15
|
+
transform_preamble(element)
|
|
16
|
+
when CoreModel::HeaderElement
|
|
17
|
+
transform_header(element)
|
|
18
|
+
else
|
|
19
|
+
transform_generic_element(element)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def transform_document(doc)
|
|
24
|
+
blocks = Array(doc.children)
|
|
25
|
+
.flat_map { |child| FromCoreModel.flatten_transform_result(FromCoreModel.transform(child)) }
|
|
26
|
+
.compact
|
|
27
|
+
|
|
28
|
+
Coradoc::Markdown::Document.new(
|
|
29
|
+
id: doc.id,
|
|
30
|
+
blocks: blocks
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def transform_section(section)
|
|
35
|
+
blocks = []
|
|
36
|
+
blocks << Coradoc::Markdown::Heading.new(
|
|
37
|
+
level: section.level || 1,
|
|
38
|
+
text: section.title.to_s
|
|
39
|
+
)
|
|
40
|
+
child_blocks = Array(section.children)
|
|
41
|
+
.flat_map { |child| FromCoreModel.flatten_transform_result(FromCoreModel.transform(child)) }
|
|
42
|
+
.compact
|
|
43
|
+
blocks.concat(child_blocks)
|
|
44
|
+
blocks
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def transform_preamble(preamble)
|
|
48
|
+
Array(preamble.children)
|
|
49
|
+
.flat_map { |child| FromCoreModel.flatten_transform_result(FromCoreModel.transform(child)) }
|
|
50
|
+
.compact
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def transform_header(header)
|
|
54
|
+
level = header.level || 1
|
|
55
|
+
Coradoc::Markdown::Heading.new(
|
|
56
|
+
level: level,
|
|
57
|
+
text: header.title.to_s
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def transform_generic_element(element)
|
|
62
|
+
blocks = Array(element.children)
|
|
63
|
+
.flat_map { |child| FromCoreModel.flatten_transform_result(FromCoreModel.transform(child)) }
|
|
64
|
+
.compact
|
|
65
|
+
|
|
66
|
+
Coradoc::Markdown::Document.new(
|
|
67
|
+
id: element.id,
|
|
68
|
+
blocks: blocks
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def transform_bibliography(bib)
|
|
73
|
+
entries = Array(bib.entries).map { |e| FromCoreModel.transform(e) }
|
|
74
|
+
blocks = []
|
|
75
|
+
blocks << Coradoc::Markdown::Heading.new(level: 2, text: bib.title.to_s) if bib.title
|
|
76
|
+
blocks.concat(entries)
|
|
77
|
+
Coradoc::Markdown::Document.new(id: bib.id, blocks: blocks)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def transform_bibliography_entry(entry)
|
|
81
|
+
FromCoreModel.transform_bibliography_entry(entry)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Register with FromCoreModel
|
|
86
|
+
FromCoreModel.register(CoreModel::StructuralElement, method(:transform_structural_element))
|
|
87
|
+
FromCoreModel.register(CoreModel::Bibliography, method(:transform_bibliography))
|
|
88
|
+
FromCoreModel.register(CoreModel::BibliographyEntry, method(:transform_bibliography_entry))
|
|
89
|
+
FromCoreModel.register(CoreModel::Toc, ->(_m) { Coradoc::Markdown::Extension.toc })
|
|
90
|
+
FromCoreModel.register(CoreModel::TocEntry, ->(m) { Coradoc::Markdown::Text.new(content: m.title.to_s) })
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
module Transform
|
|
6
|
+
module TableTransformer
|
|
7
|
+
class << self
|
|
8
|
+
def transform_table(table)
|
|
9
|
+
headers = []
|
|
10
|
+
rows = []
|
|
11
|
+
|
|
12
|
+
table_rows = Array(table.rows)
|
|
13
|
+
if table_rows.any?
|
|
14
|
+
first_row = table_rows.first
|
|
15
|
+
first_row_cells = Array(first_row&.cells)
|
|
16
|
+
|
|
17
|
+
# Check if first row has header cells
|
|
18
|
+
if first_row_cells.any?(&:header)
|
|
19
|
+
headers = first_row_cells.map(&:flat_text)
|
|
20
|
+
table_rows = table_rows[1..] || []
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Convert remaining rows to pipe-separated strings
|
|
24
|
+
rows = table_rows.map do |row|
|
|
25
|
+
Array(row.cells).map(&:flat_text).join(' | ')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Coradoc::Markdown::Table.new(
|
|
30
|
+
headers: headers,
|
|
31
|
+
rows: rows
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
FromCoreModel.register(CoreModel::Table, method(:transform_table))
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|