coradoc-markdown 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coradoc/markdown/model/admonition.rb +6 -7
  3. data/lib/coradoc/markdown/model/blockquote.rb +0 -5
  4. data/lib/coradoc/markdown/model/code_block.rb +0 -6
  5. data/lib/coradoc/markdown/model/comment.rb +1 -1
  6. data/lib/coradoc/markdown/model/definition_term.rb +0 -8
  7. data/lib/coradoc/markdown/model/example_block.rb +0 -7
  8. data/lib/coradoc/markdown/model/heading.rb +0 -6
  9. data/lib/coradoc/markdown/model/list_item.rb +1 -16
  10. data/lib/coradoc/markdown/model/literal.rb +0 -5
  11. data/lib/coradoc/markdown/model/open_block.rb +0 -5
  12. data/lib/coradoc/markdown/model/paragraph.rb +1 -14
  13. data/lib/coradoc/markdown/model/pass.rb +0 -5
  14. data/lib/coradoc/markdown/model/sidebar.rb +0 -7
  15. data/lib/coradoc/markdown/model/verse.rb +0 -7
  16. data/lib/coradoc/markdown/parser/ast_processor.rb +1 -1
  17. data/lib/coradoc/markdown/parser/block_parser.rb +13 -13
  18. data/lib/coradoc/markdown/parser/inline_parser.rb +1 -1
  19. data/lib/coradoc/markdown/parser_util.rb +2 -2
  20. data/lib/coradoc/markdown/serializer/config.rb +4 -10
  21. data/lib/coradoc/markdown/serializer/registry.rb +1 -1
  22. data/lib/coradoc/markdown/serializer/runner.rb +1 -1
  23. data/lib/coradoc/markdown/serializer/serializers/list.rb +1 -3
  24. data/lib/coradoc/markdown/serializer/strategies/definition_list/nested_html.rb +1 -1
  25. data/lib/coradoc/markdown/transform/from_core_model.rb +76 -12
  26. data/lib/coradoc/markdown/transform/list_transformer.rb +11 -5
  27. data/lib/coradoc/markdown/transform/structural_transformer.rb +1 -1
  28. data/lib/coradoc/markdown/transform/to_core_model.rb +3 -1
  29. data/lib/coradoc/markdown/version.rb +1 -1
  30. data/lib/coradoc/markdown.rb +9 -2
  31. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8787bd4fa185e797413467515c62bcd103651592e9ef33a6c6d9afe07f087c5c
4
- data.tar.gz: e63120ad791f193d3a09711da9345788482ae6076bc8a173d97b863b6273b69f
3
+ metadata.gz: 860562e968c6a646a564edac417a882d9d477ef09c7bb84c477a6ab13fcd6fd0
4
+ data.tar.gz: de5901c3b2e6eb123a718a14466d6bf688358e350ad95564abfcc17ebd62c660
5
5
  SHA512:
6
- metadata.gz: 707ffce48956d79723b12c6112ff9237f5149037f830f37b32ad2905e6ea1ad8b0456d888ce7d4cf74315d54e9e4fab37287e44cb7d38d363318bae9f13d8a25
7
- data.tar.gz: 5ef6ac646dac9047440649ad153e0bbd8300caa29633c8b41e1bcf58c09e5eee034a2aec0e63be3e4c4d5c423dca02a488d6f9912711f576f9a9d8288b3b4541
6
+ metadata.gz: 313e3f097c07329bfacd65ce3283c33087136a9e3d8f5259298c40781b76d10495b98dd89c3c3977b27e40d667d0a056ef9c012dc89165bcecc47293333e3442
7
+ data.tar.gz: 5125a17bab25bde3da034de5b898fd28214f9e18857a9ca471e03795683fd2a9f85d3d7c3bd2925d0abf1f4b36acf6e37c71ef6f4ce2aa7389a65c7e562f8bf3
@@ -27,14 +27,13 @@ module Coradoc
27
27
  # Mixed inline content (strings and inline model objects) carried
28
28
  # from the CoreModel children so serializers can preserve cross
29
29
  # references, code spans, etc. When empty, fall back to `content`.
30
- attr_reader :children
30
+ attribute :children, Coradoc::Markdown::Base, collection: true, default: []
31
31
 
32
- def initialize(admonition_type:, content:, title: nil, children: [], **rest)
33
- super
34
- @admonition_type = admonition_type.to_s.downcase
35
- @content = content
36
- @title = title
37
- @children = Array(children)
32
+ # Normalize type on assignment. Callers can pass "NOTE", "Note",
33
+ # or "note" — storage is always lowercase so downstream comparison
34
+ # and CSS class generation don't need to repeat the normalization.
35
+ def admonition_type=(value)
36
+ super(value.to_s.downcase)
38
37
  end
39
38
  end
40
39
  end
@@ -11,11 +11,6 @@ module Coradoc
11
11
  #
12
12
  class Blockquote < Base
13
13
  attribute :content, :string
14
-
15
- def initialize(content: '')
16
- super()
17
- @content = content
18
- end
19
14
  end
20
15
  end
21
16
  end
@@ -13,12 +13,6 @@ module Coradoc
13
13
  class CodeBlock < Base
14
14
  attribute :language, :string
15
15
  attribute :code, :string
16
-
17
- def initialize(language: nil, code: '')
18
- super()
19
- @language = language
20
- @code = code
21
- end
22
16
  end
23
17
  end
24
18
  end
@@ -11,4 +11,4 @@ module Coradoc
11
11
  attribute :text, :string
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -24,14 +24,6 @@ module Coradoc
24
24
  # When present, the flat-PHP-Markdown-Extra syntax is no longer
25
25
  # sufficient and the serializer falls back to HTML <dl>/<dt>/<dd>.
26
26
  attribute :nested, Coradoc::Markdown::DefinitionList
27
-
28
- def initialize(text: '', definitions: [], nested: nil, text_children: [], **rest)
29
- super
30
- @text = text
31
- @definitions = definitions
32
- @nested = nested
33
- @text_children = Array(text_children)
34
- end
35
27
  end
36
28
  end
37
29
  end
@@ -16,13 +16,6 @@ module Coradoc
16
16
  attribute :content, :string
17
17
  attribute :caption, :string
18
18
  attribute :children, Coradoc::Markdown::Base, collection: true, default: []
19
-
20
- def initialize(content:, caption: nil, children: [], **rest)
21
- super
22
- @content = content
23
- @caption = caption
24
- @children = Array(children)
25
- end
26
19
  end
27
20
  end
28
21
  end
@@ -11,12 +11,6 @@ module Coradoc
11
11
  attribute :level, :integer, default: 1
12
12
  attribute :text, :string
13
13
 
14
- def initialize(level: 1, text: '')
15
- super()
16
- @level = level
17
- @text = text
18
- end
19
-
20
14
  # Generate an auto ID from the heading text
21
15
  #
22
16
  # @return [String] A slugified version of the text suitable for use as an ID
@@ -8,22 +8,7 @@ module Coradoc
8
8
  attribute :text, :string
9
9
  attribute :checked, :boolean # For task lists (- [ ] or - [x])
10
10
  attribute :sublist, Coradoc::Markdown::List # Nested list
11
-
12
- # Mixed content (strings and inline model objects)
13
- # @return [Array] mixed content array
14
- attr_reader :children
15
-
16
- def initialize(args = {})
17
- super()
18
- @text = args[:text] || ''
19
- @checked = args[:checked]
20
- @sublist = args[:sublist]
21
- @children = args.fetch(:children, [])
22
- end
23
-
24
- def children=(value)
25
- @children = value || []
26
- end
11
+ attribute :children, Coradoc::Markdown::Base, collection: true, default: []
27
12
  end
28
13
  end
29
14
  end
@@ -11,11 +11,6 @@ module Coradoc
11
11
  # Markdown: indented code block (4 leading spaces per line).
12
12
  class Literal < Base
13
13
  attribute :content, :string
14
-
15
- def initialize(content:, **rest)
16
- super
17
- @content = content
18
- end
19
14
  end
20
15
  end
21
16
  end
@@ -12,11 +12,6 @@ module Coradoc
12
12
  # - With id/classes → emit `<div id="...">...</div>` wrapper
13
13
  class OpenBlock < Base
14
14
  attribute :children, Coradoc::Markdown::Base, collection: true, default: []
15
-
16
- def initialize(children: [], **rest)
17
- super
18
- @children = Array(children)
19
- end
20
15
  end
21
16
  end
22
17
  end
@@ -9,20 +9,7 @@ module Coradoc
9
9
  #
10
10
  class Paragraph < Base
11
11
  attribute :text, :string
12
-
13
- # Mixed content (strings and inline model objects)
14
- # @return [Array] mixed content array
15
- attr_reader :children
16
-
17
- def initialize(text: '', children: [])
18
- super()
19
- @text = text
20
- @children = children
21
- end
22
-
23
- def children=(value)
24
- @children = value || []
25
- end
12
+ attribute :children, Base, collection: true, default: []
26
13
  end
27
14
  end
28
15
  end
@@ -11,11 +11,6 @@ module Coradoc
11
11
  # inside a `nomarkdown` kramdown extension or raw HTML passthrough.
12
12
  class Pass < Base
13
13
  attribute :content, :string
14
-
15
- def initialize(content:, **rest)
16
- super
17
- @content = content
18
- end
19
14
  end
20
15
  end
21
16
  end
@@ -13,13 +13,6 @@ module Coradoc
13
13
  attribute :content, :string
14
14
  attribute :title, :string
15
15
  attribute :children, Coradoc::Markdown::Base, collection: true, default: []
16
-
17
- def initialize(content:, title: nil, children: [], **rest)
18
- super
19
- @content = content
20
- @title = title
21
- @children = Array(children)
22
- end
23
16
  end
24
17
  end
25
18
  end
@@ -15,13 +15,6 @@ module Coradoc
15
15
  attribute :content, :string
16
16
  attribute :attribution, :string
17
17
  attribute :citetitle, :string
18
-
19
- def initialize(content:, attribution: nil, citetitle: nil, **rest)
20
- super
21
- @content = content
22
- @attribution = attribution
23
- @citetitle = citetitle
24
- end
25
18
  end
26
19
  end
27
20
  end
@@ -390,7 +390,7 @@ module Coradoc
390
390
 
391
391
  # Pattern to match HTML tags with markdown attribute
392
392
  # Captures: tag name, markdown value, content, closing tag
393
- pattern = %r{<(#{HTML_TAG_PATTERN})\s+([^>]*?)markdown\s*=\s*["']([^"']+)["']([^>]*)>(.*?)</\1>}im
393
+ pattern = %r{<(#{HTML_TAG_PATTERN})\s+([^>]*?)markdown\s*=\s*["']([^"']+)["']([^>]*)>(.*?)</\1>}imo
394
394
 
395
395
  text.gsub(pattern) do |_match|
396
396
  tag_name = ::Regexp.last_match(1)
@@ -23,9 +23,9 @@ module Coradoc
23
23
 
24
24
  rule(:whitespace) { match[" \t"] }
25
25
  # NOTE: repeat(1) before EOF (any.absent?) because infinite loop otherwise
26
- rule(:blank_line) { (whitespace.repeat(1) >> any.absent? | whitespace.repeat >> line_ending).ignore }
26
+ rule(:blank_line) { ((whitespace.repeat(1) >> any.absent?) | (whitespace.repeat >> line_ending)).ignore }
27
27
  rule(:blank_line_verbatim) do
28
- whitespace.repeat(1).as(:ln) >> any.absent? | whitespace.repeat.as(:ln) >> line_ending
28
+ (whitespace.repeat(1).as(:ln) >> any.absent?) | (whitespace.repeat.as(:ln) >> line_ending)
29
29
  end
30
30
  rule(:line_char) { match["^\r\n"] }
31
31
  rule(:line_verbatim) { line_char.repeat(1).as(:ln) >> line_ending_or_eof }
@@ -222,7 +222,7 @@ module Coradoc
222
222
  end
223
223
 
224
224
  rule(:paragraph_line) do
225
- line_char.repeat(1).as(:ln) >> any.absent? | line_char.repeat.as(:ln) >> line_ending
225
+ (line_char.repeat(1).as(:ln) >> any.absent?) | (line_char.repeat.as(:ln) >> line_ending)
226
226
  end
227
227
 
228
228
  rule(:paragraph_continued_line) do
@@ -286,8 +286,8 @@ module Coradoc
286
286
  rule(:ial_key_value) do
287
287
  match['\\w\\-'].repeat(1) >> str('=') >>
288
288
  (
289
- str('"') >> match['^"'].repeat(0) >> str('"') |
290
- str("'") >> match["^'"].repeat(0) >> str("'") |
289
+ (str('"') >> match['^"'].repeat(0) >> str('"')) |
290
+ (str("'") >> match["^'"].repeat(0) >> str("'")) |
291
291
  match['^\\s\\}'].repeat(1)
292
292
  )
293
293
  end
@@ -322,8 +322,8 @@ module Coradoc
322
322
  rule(:extension_option) do
323
323
  match['\\w\\-'].repeat(1) >> str('=') >>
324
324
  (
325
- str('"') >> match['^"'].repeat(0) >> str('"') |
326
- str("'") >> match["^'"].repeat(0) >> str("'") |
325
+ (str('"') >> match['^"'].repeat(0) >> str('"')) |
326
+ (str("'") >> match["^'"].repeat(0) >> str("'")) |
327
327
  match['^\\s/\\}'].repeat(1)
328
328
  )
329
329
  end
@@ -466,11 +466,11 @@ module Coradoc
466
466
  # List item continuation line (indented content that's not a block)
467
467
  # Excludes lines that look like nested list markers
468
468
  rule(:list_continuation_line) do
469
- (str(' ') | str("\t")) >>
470
- nested_list_marker.absent? >>
471
- line_verbatim |
469
+ ((str(' ') | str("\t")) >>
472
470
  nested_list_marker.absent? >>
473
- line_verbatim
471
+ line_verbatim) |
472
+ (nested_list_marker.absent? >>
473
+ line_verbatim)
474
474
  end
475
475
 
476
476
  # Nested list marker detection (for 4-space indented lists)
@@ -513,8 +513,8 @@ module Coradoc
513
513
 
514
514
  # Nested block (indented list, etc.)
515
515
  rule(:nested_block) do
516
- (str(' ') | str("\t")) >> nested_unordered_list |
517
- (str(' ') | str("\t")) >> nested_ordered_list
516
+ ((str(' ') | str("\t")) >> nested_unordered_list) |
517
+ ((str(' ') | str("\t")) >> nested_ordered_list)
518
518
  end
519
519
 
520
520
  # Nested unordered list (4-space indented)
@@ -266,7 +266,7 @@ module Coradoc
266
266
  end
267
267
 
268
268
  def parse(io, options = {})
269
- process_emphasis(super(io, options))
269
+ process_emphasis(super)
270
270
  end
271
271
  end
272
272
  end
@@ -71,11 +71,11 @@ module Coradoc
71
71
  def self.extract_quoted_value(scanner, handle_escapes: false)
72
72
  if scanner.scan(/"([^"\\]*(?:\\.[^"\\]*)*)"/)
73
73
  value = scanner[1]
74
- value = value.gsub(/\\"/, '"') if handle_escapes
74
+ value = value.gsub('\"', '"') if handle_escapes
75
75
  value
76
76
  elsif scanner.scan(/'([^'\\]*(?:\\.[^'\\]*)*)'/)
77
77
  value = scanner[1]
78
- value = value.gsub(/\\'/, "'") if handle_escapes
78
+ value = value.gsub('\\\'', "'") if handle_escapes
79
79
  value
80
80
  elsif scanner.scan(/(\S+)/)
81
81
  scanner[1]
@@ -48,7 +48,7 @@ module Coradoc
48
48
  end
49
49
 
50
50
  def with(overrides)
51
- self.class.new(**to_h.merge(symbolize(overrides)))
51
+ self.class.new(**to_h, **symbolize(overrides))
52
52
  end
53
53
 
54
54
  private
@@ -58,15 +58,9 @@ module Coradoc
58
58
  end
59
59
 
60
60
  def validate_options!(resolved)
61
- unless %i[github container html gfm_alert].include?(resolved.fetch(:admonition_style))
62
- raise ArgumentError, "Unknown admonition_style: #{resolved[:admonition_style].inspect}"
63
- end
64
- unless %i[html flatten].include?(resolved.fetch(:definition_list_nested))
65
- raise ArgumentError, "Unknown definition_list_nested: #{resolved[:definition_list_nested].inspect}"
66
- end
67
- unless [true, false].include?(resolved.fetch(:suppress_comments))
68
- raise ArgumentError, 'suppress_comments must be boolean'
69
- end
61
+ raise ArgumentError, "Unknown admonition_style: #{resolved[:admonition_style].inspect}" unless %i[github container html gfm_alert].include?(resolved.fetch(:admonition_style))
62
+ raise ArgumentError, "Unknown definition_list_nested: #{resolved[:definition_list_nested].inspect}" unless %i[html flatten].include?(resolved.fetch(:definition_list_nested))
63
+ raise ArgumentError, 'suppress_comments must be boolean' unless [true, false].include?(resolved.fetch(:suppress_comments))
70
64
  return if [true, false].include?(resolved.fetch(:autolinks))
71
65
 
72
66
  raise ArgumentError, 'autolinks must be boolean'
@@ -39,7 +39,7 @@ module Coradoc
39
39
  def lookup!(element)
40
40
  lookup(element) || raise(ArgumentError,
41
41
  "Unknown element type for serialization: #{element.class}. " \
42
- 'Expected a known Markdown model type.')
42
+ 'Expected a known Markdown model type.')
43
43
  end
44
44
 
45
45
  private
@@ -40,7 +40,7 @@ module Coradoc
40
40
  else
41
41
  raise ArgumentError,
42
42
  "Unknown element type for serialization: #{element.class}. " \
43
- 'Expected a known Markdown model type.'
43
+ 'Expected a known Markdown model type.'
44
44
  end
45
45
  end
46
46
  end
@@ -13,9 +13,7 @@ module Coradoc
13
13
  marker = element.ordered ? '1.' : '-'
14
14
  element.items.flat_map do |item|
15
15
  lines = [render_item(item, marker, _ctx)]
16
- if item.sublist
17
- lines += call(item.sublist, _ctx).split("\n").map { |l| " #{l}" }
18
- end
16
+ lines += call(item.sublist, _ctx).split("\n").map { |l| " #{l}" } if item.sublist
19
17
  lines
20
18
  end.join("\n")
21
19
  end
@@ -35,7 +35,7 @@ module Coradoc
35
35
  end
36
36
 
37
37
  def render_term(term)
38
- dt = "<dt>#{term.text.to_s}</dt>"
38
+ dt = "<dt>#{term.text}</dt>"
39
39
  dds = term.definitions.map { |d| render_dd(d) }.join
40
40
  nested = term.nested ? "\n #{render_dl(term.nested)}" : ''
41
41
  "#{dt}\n#{dds}#{nested unless nested.empty?}"
@@ -55,6 +55,8 @@ module Coradoc
55
55
  Coradoc::Markdown::Text.new(content: model.title.to_s)
56
56
  when Coradoc::CoreModel::CommentLine
57
57
  Coradoc::Markdown::Comment.new(text: model.text.to_s)
58
+ when Coradoc::CoreModel::Include
59
+ transform_include(model)
58
60
  when Coradoc::CoreModel::TextContent
59
61
  model.text.to_s
60
62
  when Array
@@ -66,6 +68,17 @@ module Coradoc
66
68
 
67
69
  private
68
70
 
71
+ # Markdown has no transclusion — an unresolved include edge is
72
+ # preserved as an HTML comment so no information is lost and
73
+ # serialization never crashes on graph-mode documents.
74
+ def transform_include(element)
75
+ Coradoc::Markdown::Comment.new(text: include_directive_text(element))
76
+ end
77
+
78
+ def include_directive_text(element)
79
+ "include::#{element.target}[#{element.raw_options}]"
80
+ end
81
+
69
82
  def transform_structural_element(element)
70
83
  case element
71
84
  when CoreModel::DocumentElement
@@ -219,7 +232,7 @@ module Coradoc
219
232
  def transform_verse_block(block)
220
233
  Coradoc::Markdown::Verse.new(
221
234
  content: block.flat_text,
222
- attribution: block.respond_to?(:attribution) ? block.attribution : nil
235
+ attribution: block.is_a?(Coradoc::CoreModel::VerseBlock) ? block.attribution : nil
223
236
  )
224
237
  end
225
238
 
@@ -272,10 +285,17 @@ module Coradoc
272
285
 
273
286
  def transform_admonition_block(block, default_type: 'note')
274
287
  children = transform_inline_array(block.renderable_content)
288
+ if block.is_a?(Coradoc::CoreModel::AnnotationBlock)
289
+ adm_type = block.annotation_type || default_type
290
+ adm_label = block.annotation_label
291
+ else
292
+ adm_type = default_type
293
+ adm_label = nil
294
+ end
275
295
  Coradoc::Markdown::Admonition.new(
276
- admonition_type: block.respond_to?(:annotation_type) ? (block.annotation_type || default_type) : default_type,
296
+ admonition_type: adm_type,
277
297
  content: block.flat_text,
278
- title: block.respond_to?(:annotation_label) ? block.annotation_label : nil,
298
+ title: adm_label,
279
299
  children: children
280
300
  )
281
301
  end
@@ -374,7 +394,7 @@ module Coradoc
374
394
  )
375
395
  end
376
396
 
377
- CALLOUT_MARKER_IN_CELL = /\s*<\d+>(?=\s|\z)/.freeze
397
+ CALLOUT_MARKER_IN_CELL = /\s*<\d+>(?=\s|\z)/
378
398
 
379
399
  def strip_cell_callouts(text)
380
400
  text.to_s.gsub(CALLOUT_MARKER_IN_CELL, '')
@@ -428,21 +448,52 @@ module Coradoc
428
448
  end
429
449
 
430
450
  def transform_definition_list(dl)
431
- items = Array(dl.items).map do |item|
432
- definition = build_definition_item(item)
451
+ # flat_map because each CoreModel DefinitionItem may emit
452
+ # multiple Markdown DefinitionTerms (multi-term `<dt>`).
453
+ items = Array(dl.items).flat_map do |item|
454
+ definitions = [build_definition_item(item)]
455
+ # `+`-continuation blocks attached to the dd become
456
+ # additional definitions in Markdown (each renders as
457
+ # `: line` in the Flat serializer). One DefinitionItem
458
+ # per attached block, preserving their distinct content
459
+ # without jamming them into the primary definition's text.
460
+ definitions.concat(Array(item.attached_children).map { |b| build_attached_definition_item(b) })
433
461
  nested = item.nested ? transform_definition_list(item.nested) : nil
434
462
  term_children = Array(item.term_children).map { |c| transform_inline_content(c) }
435
- Coradoc::Markdown::DefinitionTerm.new(
436
- text: item.term.to_s,
437
- text_children: term_children,
438
- definitions: [definition],
439
- nested: nested
440
- )
463
+ # Multi-term `<dt>`: emit one Markdown DefinitionTerm per
464
+ # term string. Inline children map 1:1 to the FIRST term
465
+ # (matches the mirror handler's behaviour; multi-term
466
+ # with inline markup on later terms is rare and the
467
+ # parser doesn't capture per-term children today).
468
+ terms = terms_for(item)
469
+ if terms.empty?
470
+ # Defensive: term and terms both empty — emit nothing.
471
+ next
472
+ end
473
+
474
+ terms.each_with_index.map do |term_text, idx|
475
+ Coradoc::Markdown::DefinitionTerm.new(
476
+ text: term_text.to_s,
477
+ text_children: idx.zero? ? term_children : [],
478
+ definitions: definitions,
479
+ nested: nested
480
+ )
481
+ end
441
482
  end
442
483
 
443
484
  Coradoc::Markdown::DefinitionList.new(items: items)
444
485
  end
445
486
 
487
+ # Source of truth for "the terms on this <dt>": the `terms`
488
+ # collection when populated, else `[term]` for legacy callers.
489
+ def terms_for(item)
490
+ collection = item.terms if item.is_a?(Coradoc::CoreModel::DefinitionItem)
491
+ return Array(collection) unless collection.nil? || collection.empty?
492
+
493
+ primary = item.term
494
+ primary.to_s.empty? ? [] : [primary.to_s]
495
+ end
496
+
446
497
  def build_definition_item(item)
447
498
  children = Array(item.definition_children)
448
499
  if children.empty?
@@ -457,6 +508,19 @@ module Coradoc
457
508
  )
458
509
  end
459
510
 
511
+ # Build a DefinitionItem from a single attached block (e.g.
512
+ # paragraph from a `+`-continuation). Flat-text extraction
513
+ # via ChildrenContent is the single source of truth — every
514
+ # attached block in CoreModel includes ChildrenContent.
515
+ def build_attached_definition_item(block)
516
+ content = if block.is_a?(Coradoc::CoreModel::ChildrenContent)
517
+ block.flat_text
518
+ else
519
+ block.to_s
520
+ end
521
+ Coradoc::Markdown::DefinitionItem.new(content: content)
522
+ end
523
+
460
524
  def transform_footnote(fn)
461
525
  Coradoc::Markdown::Footnote.new(
462
526
  id: fn.id.to_s,
@@ -30,14 +30,20 @@ module Coradoc
30
30
  end
31
31
 
32
32
  def transform_definition_list(dl)
33
- items = Array(dl.items).map do |item|
33
+ # flat_map because multi-term `<dt>`'s emit multiple
34
+ # DefinitionTerms per CoreModel DefinitionItem.
35
+ items = Array(dl.items).flat_map do |item|
34
36
  definitions = Array(item.definitions).map do |defn|
35
37
  Coradoc::Markdown::DefinitionItem.new(content: defn.to_s)
36
38
  end
37
- Coradoc::Markdown::DefinitionTerm.new(
38
- text: item.term.to_s,
39
- definitions: definitions
40
- )
39
+ terms = item.terms
40
+ term_strings = terms.nil? || terms.empty? ? [item.term.to_s] : terms.map(&:to_s)
41
+ term_strings.map do |term_text|
42
+ Coradoc::Markdown::DefinitionTerm.new(
43
+ text: term_text,
44
+ definitions: definitions
45
+ )
46
+ end
41
47
  end
42
48
 
43
49
  Coradoc::Markdown::DefinitionList.new(items: items)
@@ -80,7 +80,7 @@ module Coradoc
80
80
  def transform_bibliography_entry(entry)
81
81
  FromCoreModel.transform_bibliography_entry(entry)
82
82
  end
83
- end
83
+ end
84
84
 
85
85
  # Register with FromCoreModel
86
86
  FromCoreModel.register(CoreModel::StructuralElement, method(:transform_structural_element))
@@ -165,7 +165,9 @@ module Coradoc
165
165
  cells = if row.is_a?(Array)
166
166
  row.map { |c| Coradoc::CoreModel::TableCell.new(content: c.to_s, header: false) }
167
167
  else
168
- row.to_s.split(' | ').map { |c| Coradoc::CoreModel::TableCell.new(content: c.to_s, header: false) }
168
+ row.to_s.split(' | ').map do |c|
169
+ Coradoc::CoreModel::TableCell.new(content: c.to_s, header: false)
170
+ end
169
171
  end
170
172
  rows << Coradoc::CoreModel::TableRow.new(cells: cells)
171
173
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Coradoc
4
4
  module Markdown
5
- VERSION = '1.0.9'
5
+ VERSION = '1.0.11'
6
6
  end
7
7
  end
@@ -127,9 +127,9 @@ module Coradoc
127
127
  # @param filename [String] Path to the Markdown file
128
128
  # @param options [Hash] Parsing options (see #parse)
129
129
  # @return [Array] The parsed AST
130
- def from_file(filename, **options)
130
+ def from_file(filename, **)
131
131
  content = File.read(filename)
132
- parse(content, **options)
132
+ parse(content, **)
133
133
  end
134
134
 
135
135
  # Parse inline Markdown content
@@ -150,6 +150,13 @@ module Coradoc
150
150
  Serializer.serialize(document, options)
151
151
  end
152
152
 
153
+ # Markdown preserves unresolved include edges as HTML comments
154
+ # (Transform::FromCoreModel#transform_include) — lossy formatting,
155
+ # but never silent content loss.
156
+ def preserves_unresolved_includes?
157
+ true
158
+ end
159
+
153
160
  # Check if this format can transform the given model to CoreModel
154
161
  #
155
162
  # @param model [Object] The model to check
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coradoc-markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -232,6 +232,7 @@ metadata:
232
232
  homepage_uri: https://github.com/metanorma/coradoc
233
233
  source_code_uri: https://github.com/metanorma/coradoc
234
234
  changelog_uri: https://github.com/metanorma/coradoc/releases
235
+ rubygems_mfa_required: 'true'
235
236
  rdoc_options: []
236
237
  require_paths:
237
238
  - lib