coradoc-markdown 1.0.2 → 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/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 +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 +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 +187 -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
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
class Serializer
|
|
6
|
+
# Named Markdown flavor profiles.
|
|
7
|
+
#
|
|
8
|
+
# Each flavor bundles sensible defaults for the 5 spec options.
|
|
9
|
+
# Callers can override any option via `Serializer.build`.
|
|
10
|
+
#
|
|
11
|
+
# Adding a new flavor = adding one entry here. No serializer code
|
|
12
|
+
# needs to change — Open/Closed.
|
|
13
|
+
module Flavor
|
|
14
|
+
PROFILES = {
|
|
15
|
+
commonmark: {
|
|
16
|
+
markdown_flavor: :commonmark,
|
|
17
|
+
admonition_style: :html,
|
|
18
|
+
definition_list_nested: :html,
|
|
19
|
+
suppress_comments: true,
|
|
20
|
+
autolinks: true
|
|
21
|
+
},
|
|
22
|
+
gfm: {
|
|
23
|
+
markdown_flavor: :gfm,
|
|
24
|
+
admonition_style: :github,
|
|
25
|
+
definition_list_nested: :html,
|
|
26
|
+
suppress_comments: true,
|
|
27
|
+
autolinks: true
|
|
28
|
+
},
|
|
29
|
+
kramdown: {
|
|
30
|
+
markdown_flavor: :kramdown,
|
|
31
|
+
admonition_style: :html,
|
|
32
|
+
definition_list_nested: :html,
|
|
33
|
+
suppress_comments: true,
|
|
34
|
+
autolinks: true
|
|
35
|
+
},
|
|
36
|
+
pandoc: {
|
|
37
|
+
markdown_flavor: :pandoc,
|
|
38
|
+
admonition_style: :html,
|
|
39
|
+
definition_list_nested: :html,
|
|
40
|
+
suppress_comments: true,
|
|
41
|
+
autolinks: true
|
|
42
|
+
},
|
|
43
|
+
vitepress: {
|
|
44
|
+
markdown_flavor: :vitepress,
|
|
45
|
+
admonition_style: :container,
|
|
46
|
+
definition_list_nested: :html,
|
|
47
|
+
suppress_comments: true,
|
|
48
|
+
autolinks: true
|
|
49
|
+
},
|
|
50
|
+
php_markdown_extra: {
|
|
51
|
+
markdown_flavor: :php_markdown_extra,
|
|
52
|
+
admonition_style: :html,
|
|
53
|
+
definition_list_nested: :html,
|
|
54
|
+
suppress_comments: true,
|
|
55
|
+
autolinks: true
|
|
56
|
+
}
|
|
57
|
+
}.freeze
|
|
58
|
+
|
|
59
|
+
DEFAULT_FLAVOR = :gfm
|
|
60
|
+
|
|
61
|
+
class << self
|
|
62
|
+
def names
|
|
63
|
+
PROFILES.keys
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def known?(name)
|
|
67
|
+
PROFILES.key?(name.to_sym)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def resolve(name)
|
|
71
|
+
profile = PROFILES[name.to_sym] || PROFILES[DEFAULT_FLAVOR]
|
|
72
|
+
profile.dup
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def default
|
|
76
|
+
PROFILES[DEFAULT_FLAVOR]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'registry'
|
|
4
|
+
require_relative 'serializers/document'
|
|
5
|
+
require_relative 'serializers/heading'
|
|
6
|
+
require_relative 'serializers/paragraph'
|
|
7
|
+
require_relative 'serializers/list'
|
|
8
|
+
require_relative 'serializers/code_block'
|
|
9
|
+
require_relative 'serializers/blockquote'
|
|
10
|
+
require_relative 'serializers/link'
|
|
11
|
+
require_relative 'serializers/image'
|
|
12
|
+
require_relative 'serializers/horizontal_rule'
|
|
13
|
+
require_relative 'serializers/table'
|
|
14
|
+
require_relative 'serializers/emphasis'
|
|
15
|
+
require_relative 'serializers/strong'
|
|
16
|
+
require_relative 'serializers/code'
|
|
17
|
+
require_relative 'serializers/strikethrough'
|
|
18
|
+
require_relative 'serializers/highlight'
|
|
19
|
+
require_relative 'serializers/subscript'
|
|
20
|
+
require_relative 'serializers/superscript'
|
|
21
|
+
require_relative 'serializers/underline'
|
|
22
|
+
require_relative 'serializers/cross_reference'
|
|
23
|
+
require_relative 'serializers/attribute_list'
|
|
24
|
+
require_relative 'serializers/math'
|
|
25
|
+
require_relative 'serializers/extension'
|
|
26
|
+
require_relative 'serializers/definition_list'
|
|
27
|
+
require_relative 'serializers/footnote'
|
|
28
|
+
require_relative 'serializers/footnote_reference'
|
|
29
|
+
require_relative 'serializers/abbreviation'
|
|
30
|
+
require_relative 'serializers/comment'
|
|
31
|
+
require_relative 'serializers/admonition'
|
|
32
|
+
require_relative 'serializers/example_block'
|
|
33
|
+
require_relative 'serializers/open_block'
|
|
34
|
+
require_relative 'serializers/sidebar'
|
|
35
|
+
require_relative 'serializers/verse'
|
|
36
|
+
require_relative 'serializers/pass'
|
|
37
|
+
require_relative 'serializers/literal'
|
|
38
|
+
require_relative 'serializers/hard_line_break'
|
|
39
|
+
|
|
40
|
+
module Coradoc
|
|
41
|
+
module Markdown
|
|
42
|
+
class Serializer
|
|
43
|
+
# Auto-registers all built-in element serializers into a fresh
|
|
44
|
+
# Registry. Called once per Runner (cached via `default_registry`).
|
|
45
|
+
#
|
|
46
|
+
# Adding a new element serializer = appending one entry here. No
|
|
47
|
+
# lookup code changes — Open/Closed.
|
|
48
|
+
module Registrations
|
|
49
|
+
SERIALIZEABLE = [
|
|
50
|
+
Serializers::Document,
|
|
51
|
+
Serializers::Heading,
|
|
52
|
+
Serializers::Paragraph,
|
|
53
|
+
Serializers::List,
|
|
54
|
+
Serializers::CodeBlock,
|
|
55
|
+
Serializers::Blockquote,
|
|
56
|
+
Serializers::Link,
|
|
57
|
+
Serializers::Image,
|
|
58
|
+
Serializers::HorizontalRule,
|
|
59
|
+
Serializers::Table,
|
|
60
|
+
Serializers::Emphasis,
|
|
61
|
+
Serializers::Strong,
|
|
62
|
+
Serializers::Code,
|
|
63
|
+
Serializers::Strikethrough,
|
|
64
|
+
Serializers::Highlight,
|
|
65
|
+
Serializers::Subscript,
|
|
66
|
+
Serializers::Superscript,
|
|
67
|
+
Serializers::Underline,
|
|
68
|
+
Serializers::CrossReference,
|
|
69
|
+
Serializers::AttributeList,
|
|
70
|
+
Serializers::Math,
|
|
71
|
+
Serializers::Extension,
|
|
72
|
+
Serializers::DefinitionList,
|
|
73
|
+
Serializers::Footnote,
|
|
74
|
+
Serializers::FootnoteReference,
|
|
75
|
+
Serializers::Abbreviation,
|
|
76
|
+
Serializers::Comment,
|
|
77
|
+
Serializers::Admonition,
|
|
78
|
+
Serializers::ExampleBlock,
|
|
79
|
+
Serializers::OpenBlock,
|
|
80
|
+
Serializers::Sidebar,
|
|
81
|
+
Serializers::Verse,
|
|
82
|
+
Serializers::Pass,
|
|
83
|
+
Serializers::Literal,
|
|
84
|
+
Serializers::HardLineBreak
|
|
85
|
+
].freeze
|
|
86
|
+
|
|
87
|
+
@mutex = Mutex.new
|
|
88
|
+
@default = nil
|
|
89
|
+
|
|
90
|
+
class << self
|
|
91
|
+
def default_registry
|
|
92
|
+
@mutex.synchronize do
|
|
93
|
+
@default ||= register_all(Registry.new)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def fresh_registry
|
|
98
|
+
register_all(Registry.new)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def register_all(registry)
|
|
104
|
+
SERIALIZEABLE.each { |klass| registry.register(klass.new) }
|
|
105
|
+
registry
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Markdown
|
|
5
|
+
class Serializer
|
|
6
|
+
# Type-keyed dispatch table for element serializers.
|
|
7
|
+
#
|
|
8
|
+
# Each entry is a tuple of (serializer_instance, priority). Dispatch
|
|
9
|
+
# resolves the highest-priority entry whose declared `handles?` predicate
|
|
10
|
+
# accepts the element. This lets specialized serializers (e.g. one that
|
|
11
|
+
# targets a specific CoreModel subclass) override generic ones without
|
|
12
|
+
# modifying the registry lookup logic — Open/Closed.
|
|
13
|
+
class Registry
|
|
14
|
+
class Entry < Struct.new(:serializer, :priority)
|
|
15
|
+
include Comparable
|
|
16
|
+
|
|
17
|
+
def <=>(other)
|
|
18
|
+
priority <=> other.priority
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize
|
|
23
|
+
@entries = Hash.new { |h, k| h[k] = [] }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def register(serializer, priority: 0)
|
|
27
|
+
klass = serializer.handles_type
|
|
28
|
+
raise ArgumentError, "Serializer #{serializer.class} declares no handles_type" unless klass
|
|
29
|
+
|
|
30
|
+
@entries[klass] << Entry.new(serializer, priority)
|
|
31
|
+
@entries[klass].sort!
|
|
32
|
+
serializer
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def lookup(element)
|
|
36
|
+
each_candidate(element).first&.serializer
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def lookup!(element)
|
|
40
|
+
lookup(element) || raise(ArgumentError,
|
|
41
|
+
"Unknown element type for serialization: #{element.class}. " \
|
|
42
|
+
'Expected a known Markdown model type.')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def each_candidate(element)
|
|
48
|
+
return enum_for(:each_candidate, element) unless block_given?
|
|
49
|
+
|
|
50
|
+
walked = element.class.ancestors
|
|
51
|
+
walked.each do |klass|
|
|
52
|
+
@entries[klass].sort_by { |e| -e.priority }.each do |entry|
|
|
53
|
+
next unless entry.serializer.handles?(element)
|
|
54
|
+
|
|
55
|
+
yield entry
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'context'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
# Stateful runner: holds a frozen Config + Registry, exposes `#call`.
|
|
9
|
+
# Each top-level `call` creates a fresh Context (per-document mutable
|
|
10
|
+
# state) so the same runner can serialize multiple documents without
|
|
11
|
+
# cross-document leakage.
|
|
12
|
+
class Runner
|
|
13
|
+
attr_reader :config, :registry
|
|
14
|
+
|
|
15
|
+
def initialize(config:, registry:)
|
|
16
|
+
@config = config
|
|
17
|
+
@registry = registry
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def call(element)
|
|
21
|
+
ctx = Context.new(config: config, registry: registry, runner: self)
|
|
22
|
+
result = serialize(element, ctx)
|
|
23
|
+
result = append_link_refs(result, ctx)
|
|
24
|
+
append_footnote_defs(result, ctx).to_s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def serialize(element, ctx = nil)
|
|
28
|
+
ctx ||= Context.new(config: config, registry: registry, runner: self)
|
|
29
|
+
case element
|
|
30
|
+
when String
|
|
31
|
+
element
|
|
32
|
+
when nil
|
|
33
|
+
''
|
|
34
|
+
when Array
|
|
35
|
+
element.map { |e| serialize(e, ctx) }.join
|
|
36
|
+
else
|
|
37
|
+
serializer = registry.lookup(element)
|
|
38
|
+
if serializer
|
|
39
|
+
serializer.call(element, ctx)
|
|
40
|
+
else
|
|
41
|
+
raise ArgumentError,
|
|
42
|
+
"Unknown element type for serialization: #{element.class}. " \
|
|
43
|
+
'Expected a known Markdown model type.'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def serialize_inline(element, ctx)
|
|
49
|
+
case element
|
|
50
|
+
when String
|
|
51
|
+
element
|
|
52
|
+
when nil
|
|
53
|
+
''
|
|
54
|
+
when ::Coradoc::Markdown::Base, ::Coradoc::Markdown::Document
|
|
55
|
+
serialize(element, ctx)
|
|
56
|
+
when Array
|
|
57
|
+
element.map { |e| serialize_inline(e, ctx) }.join
|
|
58
|
+
else
|
|
59
|
+
raise ArgumentError,
|
|
60
|
+
"Cannot serialize inline content of type #{element.class}. " \
|
|
61
|
+
'Expected String, known inline model, or Base subclass.'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def append_link_refs(result, ctx)
|
|
68
|
+
return result if ctx.link_refs.empty?
|
|
69
|
+
|
|
70
|
+
refs = ctx.link_refs.map do |ref|
|
|
71
|
+
"[#{ref.id}]: #{ref.url}#{ref.title ? " \"#{ref.title}\"" : ''}"
|
|
72
|
+
end.join("\n")
|
|
73
|
+
"#{result}\n\n#{refs}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def append_footnote_defs(result, ctx)
|
|
77
|
+
return result if ctx.footnote_defs.empty?
|
|
78
|
+
|
|
79
|
+
"#{result}\n\n#{ctx.footnote_defs.join("\n")}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Abbreviation < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Abbreviation
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
"*[#{element.term}]: #{element.definition}"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
require_relative '../strategies/admonition/registry'
|
|
5
|
+
|
|
6
|
+
module Coradoc
|
|
7
|
+
module Markdown
|
|
8
|
+
class Serializer
|
|
9
|
+
module Serializers
|
|
10
|
+
class Admonition < ElementSerializer
|
|
11
|
+
handles_type ::Coradoc::Markdown::Admonition
|
|
12
|
+
|
|
13
|
+
def call(element, ctx)
|
|
14
|
+
Strategies::Admonition::Registry.render(element, ctx: ctx)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class AttributeList < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::AttributeList
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
return '' if element.empty?
|
|
14
|
+
|
|
15
|
+
parts = []
|
|
16
|
+
parts << "##{element.id}" if element.id
|
|
17
|
+
parts += element.classes.map { |c| ".#{c}" }
|
|
18
|
+
parts += element.attributes.map { |nv| %(#{nv.name}="#{nv.value}") }
|
|
19
|
+
"{:#{parts.join(' ')}}"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Blockquote < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Blockquote
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
element.content.to_s.lines.map { |line| "> #{line}" }.join
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Code < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Code
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
"`#{element.text}`"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class CodeBlock < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::CodeBlock
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
"```#{element.language}\n#{element.code}\n```"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
# Comments are editorial annotations, not document content. The
|
|
10
|
+
# Markdown Serialization Spec (§Comments) requires that comments
|
|
11
|
+
# be suppressed by default.
|
|
12
|
+
#
|
|
13
|
+
# Behavior:
|
|
14
|
+
# suppress_comments == true → '' (no output)
|
|
15
|
+
# suppress_comments == false → '<!-- text -->'
|
|
16
|
+
class Comment < ElementSerializer
|
|
17
|
+
handles_type ::Coradoc::Markdown::Comment
|
|
18
|
+
|
|
19
|
+
def call(element, ctx)
|
|
20
|
+
return '' if ctx.config.suppress_comments
|
|
21
|
+
|
|
22
|
+
text = element.text.to_s.strip
|
|
23
|
+
return '<!---->' if text.empty?
|
|
24
|
+
|
|
25
|
+
"<!-- #{text} -->"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class CrossReference < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::CrossReference
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
"[#{element.text}](##{element.target})"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
require_relative '../strategies/definition_list/registry'
|
|
5
|
+
|
|
6
|
+
module Coradoc
|
|
7
|
+
module Markdown
|
|
8
|
+
class Serializer
|
|
9
|
+
module Serializers
|
|
10
|
+
class DefinitionList < ElementSerializer
|
|
11
|
+
handles_type ::Coradoc::Markdown::DefinitionList
|
|
12
|
+
|
|
13
|
+
def call(element, ctx)
|
|
14
|
+
Strategies::DefinitionList::Registry.render(element, ctx)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Document < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Document
|
|
11
|
+
|
|
12
|
+
def call(element, ctx)
|
|
13
|
+
body = element.blocks.map { |block| ctx.serialize(block) }.join("\n\n")
|
|
14
|
+
return body unless element.frontmatter && !element.frontmatter.empty?
|
|
15
|
+
|
|
16
|
+
"---\n#{element.frontmatter}---\n\n#{body}".strip
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Emphasis < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Emphasis
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
"*#{element.text}*"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
# Example blocks emit an HTML fallback that preserves the caption
|
|
10
|
+
# as a heading inside `<div class="example">`.
|
|
11
|
+
#
|
|
12
|
+
# When `admonition_style == :container` (VitePress), emits
|
|
13
|
+
# `:::details Caption\n... \n:::` instead.
|
|
14
|
+
class ExampleBlock < ElementSerializer
|
|
15
|
+
handles_type ::Coradoc::Markdown::ExampleBlock
|
|
16
|
+
|
|
17
|
+
def call(element, ctx)
|
|
18
|
+
if ctx.config.admonition_style == :container
|
|
19
|
+
render_container(element)
|
|
20
|
+
else
|
|
21
|
+
render_html(element)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def render_html(element)
|
|
28
|
+
caption_html = element.caption ? %(<h4>Example: #{element.caption}</h4>\n) : ''
|
|
29
|
+
%(<div class="example">\n#{caption_html}<p>#{element.content.to_s}</p>\n</div>)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def render_container(element)
|
|
33
|
+
title = element.caption ? " Example: #{element.caption}" : ''
|
|
34
|
+
":::details#{title}\n#{element.content.to_s}\n:::"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Extension < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Extension
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
opts = element.options.empty? ? '' : " #{extension_options_to_s(element.options)}"
|
|
14
|
+
if element.self_closing?
|
|
15
|
+
"{::#{element.name}#{opts} /}"
|
|
16
|
+
else
|
|
17
|
+
"{::#{element.name}#{opts}}#{element.content}{:/}"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def extension_options_to_s(options)
|
|
24
|
+
options.map { |nv| %(#{nv.name}="#{nv.value}") }.join(' ')
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../element_serializer'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Markdown
|
|
7
|
+
class Serializer
|
|
8
|
+
module Serializers
|
|
9
|
+
class Footnote < ElementSerializer
|
|
10
|
+
handles_type ::Coradoc::Markdown::Footnote
|
|
11
|
+
|
|
12
|
+
def call(element, _ctx)
|
|
13
|
+
content = element.content.to_s
|
|
14
|
+
"[^#{element.id}]: #{content}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|