coradoc-markdown 1.0.2 → 1.0.4
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 +41 -0
- data/lib/coradoc/markdown/model/comment.rb +14 -0
- 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/hard_line_break.rb +21 -0
- 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/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/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 +41 -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 +27 -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 +29 -243
- data/lib/coradoc/markdown/toc_generator.rb +2 -2
- data/lib/coradoc/markdown/transform/block_transformer.rb +163 -0
- data/lib/coradoc/markdown/transform/from_core_model.rb +195 -28
- 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 +24 -3
- data/lib/coradoc/markdown/transformer.rb +87 -2
- data/lib/coradoc/markdown/version.rb +1 -1
- data/lib/coradoc/markdown.rb +16 -2
- metadata +75 -1
|
@@ -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
|
|
@@ -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,
|
|
@@ -99,7 +122,7 @@ module Coradoc
|
|
|
99
122
|
when :paragraph
|
|
100
123
|
transform_paragraph(block)
|
|
101
124
|
when :comment
|
|
102
|
-
Coradoc::Markdown::
|
|
125
|
+
Coradoc::Markdown::Comment.new(text: block.content.to_s)
|
|
103
126
|
else
|
|
104
127
|
transform_delimited_block(block)
|
|
105
128
|
end
|
|
@@ -107,8 +130,17 @@ module Coradoc
|
|
|
107
130
|
|
|
108
131
|
def transform_paragraph(block)
|
|
109
132
|
content = block.renderable_content
|
|
110
|
-
|
|
111
|
-
|
|
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) }
|
|
112
144
|
children = content.map { |c| transform_inline_content(c) }
|
|
113
145
|
Coradoc::Markdown::Paragraph.new(text: block.flat_text, children: children)
|
|
114
146
|
else
|
|
@@ -122,32 +154,122 @@ module Coradoc
|
|
|
122
154
|
transform_inline(element)
|
|
123
155
|
when CoreModel::TextContent
|
|
124
156
|
element.text
|
|
157
|
+
when CoreModel::Base
|
|
158
|
+
transform(element)
|
|
125
159
|
when String
|
|
126
160
|
element
|
|
161
|
+
when Array
|
|
162
|
+
element.map { |e| transform_inline_content(e) }
|
|
127
163
|
else
|
|
128
164
|
element.to_s
|
|
129
165
|
end
|
|
130
166
|
end
|
|
131
167
|
|
|
168
|
+
def transform_inline_array(renderable)
|
|
169
|
+
return [] unless renderable.is_a?(Array)
|
|
170
|
+
|
|
171
|
+
renderable.map { |c| transform_inline_content(c) }
|
|
172
|
+
end
|
|
173
|
+
|
|
132
174
|
def transform_delimited_block(block)
|
|
133
175
|
semantic = resolve_markdown_semantic(block)
|
|
134
176
|
|
|
135
177
|
case semantic
|
|
136
178
|
when :source_code, :listing
|
|
137
179
|
transform_code_block(block)
|
|
138
|
-
when :quote
|
|
180
|
+
when :quote
|
|
139
181
|
transform_blockquote(block)
|
|
182
|
+
when :verse
|
|
183
|
+
transform_verse_block(block)
|
|
140
184
|
when :horizontal_rule
|
|
141
185
|
transform_horizontal_rule(block)
|
|
142
186
|
when :pass
|
|
143
|
-
|
|
187
|
+
transform_pass_block(block)
|
|
144
188
|
when :literal
|
|
145
|
-
|
|
189
|
+
transform_literal_block(block)
|
|
190
|
+
when :example
|
|
191
|
+
transform_example_block(block)
|
|
192
|
+
when :sidebar
|
|
193
|
+
transform_sidebar_block(block)
|
|
194
|
+
when :open
|
|
195
|
+
transform_open_block(block)
|
|
196
|
+
when :reviewer
|
|
197
|
+
transform_admonition_block(block, default_type: 'reviewer')
|
|
146
198
|
else
|
|
147
199
|
transform_paragraph(block)
|
|
148
200
|
end
|
|
149
201
|
end
|
|
150
202
|
|
|
203
|
+
def transform_container_block(block)
|
|
204
|
+
rc = block.renderable_content
|
|
205
|
+
if rc.is_a?(Array) && rc.any? { |c| c.is_a?(CoreModel::Block) || c.is_a?(CoreModel::ListBlock) }
|
|
206
|
+
rc.filter_map do |c|
|
|
207
|
+
next c.text if c.is_a?(CoreModel::TextContent)
|
|
208
|
+
next nil if c.is_a?(String) && c.strip.empty?
|
|
209
|
+
|
|
210
|
+
transform(c)
|
|
211
|
+
end.flat_map { |c| flatten_result(c) }
|
|
212
|
+
else
|
|
213
|
+
Coradoc::Markdown::Blockquote.new(content: block.flat_text)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def transform_verse_block(block)
|
|
218
|
+
Coradoc::Markdown::Verse.new(
|
|
219
|
+
content: block.flat_text,
|
|
220
|
+
attribution: block.respond_to?(:attribution) ? block.attribution : nil
|
|
221
|
+
)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def transform_pass_block(block)
|
|
225
|
+
return Coradoc::Markdown::Math.block(block.content.to_s) if block.language == 'latexmath'
|
|
226
|
+
|
|
227
|
+
Coradoc::Markdown::Pass.new(content: block.content.to_s)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def transform_literal_block(block)
|
|
231
|
+
Coradoc::Markdown::Literal.new(content: block.content.to_s)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def transform_example_block(block)
|
|
235
|
+
Coradoc::Markdown::ExampleBlock.new(
|
|
236
|
+
content: block.flat_text,
|
|
237
|
+
caption: block.title.to_s
|
|
238
|
+
)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def transform_sidebar_block(block)
|
|
242
|
+
Coradoc::Markdown::Sidebar.new(
|
|
243
|
+
content: block.flat_text,
|
|
244
|
+
title: block.title.to_s
|
|
245
|
+
)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def transform_open_block(block)
|
|
249
|
+
children = Array(block.children).map { |c| transform(c) }.flat_map { |c| flatten_result(c) }
|
|
250
|
+
children = paragraphs_from_content(block.content) if children.empty?
|
|
251
|
+
Coradoc::Markdown::OpenBlock.new(
|
|
252
|
+
children: children,
|
|
253
|
+
id: block.id
|
|
254
|
+
)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def paragraphs_from_content(content)
|
|
258
|
+
content.to_s.split(/\n\s*\n/).map do |chunk|
|
|
259
|
+
Coradoc::Markdown::Paragraph.new(text: chunk.strip)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def transform_admonition_block(block, default_type: 'note')
|
|
264
|
+
children = transform_inline_array(block.renderable_content)
|
|
265
|
+
Coradoc::Markdown::Admonition.new(
|
|
266
|
+
admonition_type: block.respond_to?(:annotation_type) ? (block.annotation_type || default_type) : default_type,
|
|
267
|
+
content: block.flat_text,
|
|
268
|
+
title: block.respond_to?(:annotation_label) ? block.annotation_label : nil,
|
|
269
|
+
children: children
|
|
270
|
+
)
|
|
271
|
+
end
|
|
272
|
+
|
|
151
273
|
def resolve_markdown_semantic(block)
|
|
152
274
|
# Polymorphic dispatch: typed classes override semantic_type
|
|
153
275
|
semantic = block.resolve_semantic_type
|
|
@@ -167,10 +289,21 @@ module Coradoc
|
|
|
167
289
|
end
|
|
168
290
|
|
|
169
291
|
def transform_code_block(block)
|
|
170
|
-
|
|
171
|
-
|
|
292
|
+
code = CoreModel::CalloutText.strip_markers(block.content.to_s, block.callouts)
|
|
293
|
+
code_block = Coradoc::Markdown::CodeBlock.new(
|
|
294
|
+
code: code,
|
|
172
295
|
language: block.language
|
|
173
296
|
)
|
|
297
|
+
return code_block if block.callouts.nil? || block.callouts.empty?
|
|
298
|
+
|
|
299
|
+
[code_block, transform_callout_list(block.callouts)]
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def transform_callout_list(callouts)
|
|
303
|
+
items = CoreModel::CalloutText.ordered(callouts).map do |callout|
|
|
304
|
+
Coradoc::Markdown::ListItem.new(text: callout.content.to_s)
|
|
305
|
+
end
|
|
306
|
+
Coradoc::Markdown::List.new(ordered: true, items: items)
|
|
174
307
|
end
|
|
175
308
|
|
|
176
309
|
def transform_blockquote(block)
|
|
@@ -180,19 +313,21 @@ module Coradoc
|
|
|
180
313
|
end
|
|
181
314
|
|
|
182
315
|
def transform_horizontal_rule(_block)
|
|
183
|
-
Coradoc::Markdown::HorizontalRule.new
|
|
316
|
+
Coradoc::Markdown::HorizontalRule.new(style: '---')
|
|
184
317
|
end
|
|
185
318
|
|
|
186
319
|
def transform_list(list)
|
|
187
320
|
items = Array(list.items).map do |item|
|
|
188
321
|
content = item.renderable_content
|
|
189
322
|
has_structured = content.is_a?(Array) && content.any? { |c| !c.is_a?(CoreModel::TextContent) }
|
|
190
|
-
if has_structured
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
323
|
+
md_item = if has_structured
|
|
324
|
+
children = content.map { |c| transform_inline_content(c) }
|
|
325
|
+
Coradoc::Markdown::ListItem.new(text: item.flat_text, children: children)
|
|
326
|
+
else
|
|
327
|
+
Coradoc::Markdown::ListItem.new(text: item.flat_text)
|
|
328
|
+
end
|
|
329
|
+
md_item.sublist = transform_list(item.nested_list) if item.nested_list
|
|
330
|
+
md_item
|
|
196
331
|
end
|
|
197
332
|
|
|
198
333
|
Coradoc::Markdown::List.new(
|
|
@@ -211,8 +346,8 @@ module Coradoc
|
|
|
211
346
|
first_row = table_rows.first
|
|
212
347
|
first_row_cells = Array(first_row&.cells)
|
|
213
348
|
|
|
214
|
-
# Check if first row
|
|
215
|
-
if first_row_cells.any?(&:header)
|
|
349
|
+
# Check if first row is marked as header, or if any of its cells are header cells
|
|
350
|
+
if first_row&.header || first_row_cells.any?(&:header)
|
|
216
351
|
headers = first_row_cells.map(&:flat_text)
|
|
217
352
|
table_rows = table_rows[1..] || []
|
|
218
353
|
end
|
|
@@ -278,9 +413,11 @@ module Coradoc
|
|
|
278
413
|
definitions = Array(item.definitions).map do |defn|
|
|
279
414
|
Coradoc::Markdown::DefinitionItem.new(content: defn.to_s)
|
|
280
415
|
end
|
|
416
|
+
nested = item.nested ? transform_definition_list(item.nested) : nil
|
|
281
417
|
Coradoc::Markdown::DefinitionTerm.new(
|
|
282
418
|
text: item.term.to_s,
|
|
283
|
-
definitions: definitions
|
|
419
|
+
definitions: definitions,
|
|
420
|
+
nested: nested
|
|
284
421
|
)
|
|
285
422
|
end
|
|
286
423
|
|
|
@@ -307,10 +444,7 @@ module Coradoc
|
|
|
307
444
|
end
|
|
308
445
|
|
|
309
446
|
def transform_annotation_block(annotation)
|
|
310
|
-
|
|
311
|
-
Coradoc::Markdown::Paragraph.new(
|
|
312
|
-
text: "**#{annotation.annotation_type}:** #{text}"
|
|
313
|
-
)
|
|
447
|
+
transform_admonition_block(annotation, default_type: 'note')
|
|
314
448
|
end
|
|
315
449
|
|
|
316
450
|
def transform_bibliography(bib)
|
|
@@ -322,7 +456,40 @@ module Coradoc
|
|
|
322
456
|
end
|
|
323
457
|
|
|
324
458
|
def transform_bibliography_entry(entry)
|
|
325
|
-
|
|
459
|
+
text = entry.display_text.to_s
|
|
460
|
+
text = convert_asciidoc_markers_to_markdown(text)
|
|
461
|
+
Coradoc::Markdown::Paragraph.new(text: text)
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
def convert_asciidoc_markers_to_markdown(text)
|
|
465
|
+
return '' if text.nil?
|
|
466
|
+
|
|
467
|
+
result = text.dup
|
|
468
|
+
|
|
469
|
+
# footnote:[text] -> ^[text]
|
|
470
|
+
result.gsub!(/footnote:\[(.*?)\]/, '^[\1]')
|
|
471
|
+
|
|
472
|
+
# [smallcap]#text# -> text
|
|
473
|
+
result.gsub!(/\[smallcap\]#(.*?)#/, '\1')
|
|
474
|
+
|
|
475
|
+
# *text* -> **text**
|
|
476
|
+
# Use negative lookbehind and lookahead to avoid replacing **text** to ****text****
|
|
477
|
+
result.gsub!(/(?<!\*)\*(.*?)\*(?!\*)/, '**\1**')
|
|
478
|
+
|
|
479
|
+
# _text_ -> *text*
|
|
480
|
+
# Use negative lookbehind and lookahead to avoid replacing __text__ to **text**
|
|
481
|
+
result.gsub!(/(?<!_)_(.*?)_(?!_)/, '*\1*')
|
|
482
|
+
|
|
483
|
+
result
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def flatten_result(result)
|
|
487
|
+
case result
|
|
488
|
+
when Array
|
|
489
|
+
result.flat_map { |r| flatten_result(r) }
|
|
490
|
+
else
|
|
491
|
+
[result]
|
|
492
|
+
end
|
|
326
493
|
end
|
|
327
494
|
end
|
|
328
495
|
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
|