coradoc 2.0.18 → 2.0.19
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/core_model/base.rb +17 -0
- data/lib/coradoc/core_model/children_content.rb +15 -1
- data/lib/coradoc/core_model/comment_line.rb +19 -0
- data/lib/coradoc/core_model/frontmatter/codec.rb +54 -0
- data/lib/coradoc/core_model/frontmatter/field_transform.rb +70 -0
- data/lib/coradoc/core_model/frontmatter/schema_resolver.rb +57 -0
- data/lib/coradoc/core_model/frontmatter/text_splitter.rb +75 -0
- data/lib/coradoc/core_model/frontmatter.rb +61 -0
- data/lib/coradoc/core_model.rb +2 -0
- data/lib/coradoc/version.rb +1 -1
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dfb7ecfe3eb593e8a88dc23950b2e75fb5bafd4ea8f31ee7840c44e1cdaadd28
|
|
4
|
+
data.tar.gz: 1835d0ac0defa944dc45d26c967d3e9ddb0d20a599f79c85657531689c67faf0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b1a73e74172ae6af0dd2a5426f520b546170c2a4f00910f91dd45211bccf448ca187d45b64ba94030549331008a50adaff283ca1ced17c39bb164d6a6cd9a032
|
|
7
|
+
data.tar.gz: 57efec479b5c118c4c18d99d7e0b0090046ef1c42ed17b265804f044467775fb82781bec4a7c3a119b24a428ff46ec50c642e4557488471447f5e96af48d4572
|
|
@@ -117,6 +117,23 @@ module Coradoc
|
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
119
|
|
|
120
|
+
def flat_text
|
|
121
|
+
""
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Flatten this element to a plain-text string.
|
|
125
|
+
#
|
|
126
|
+
# Subclasses that include ChildrenContent override this to
|
|
127
|
+
# concatenate their children's text. Block-level elements
|
|
128
|
+
# without textual content (ListBlock, Table, etc.) fall back
|
|
129
|
+
# to the empty string — they are serialized structurally,
|
|
130
|
+
# not flattened into inline text.
|
|
131
|
+
#
|
|
132
|
+
# @return [String]
|
|
133
|
+
def flat_text
|
|
134
|
+
""
|
|
135
|
+
end
|
|
136
|
+
|
|
120
137
|
# Accept a visitor to traverse this element
|
|
121
138
|
#
|
|
122
139
|
# Implements the visitor pattern for document traversal.
|
|
@@ -25,6 +25,9 @@ module Coradoc
|
|
|
25
25
|
|
|
26
26
|
CoreModel::TextContent.new(text: item.to_s)
|
|
27
27
|
end.compact
|
|
28
|
+
# Lutaml defines the setter directly on the class, so we overwrite it.
|
|
29
|
+
# We cannot use `super` because the original setter is lost.
|
|
30
|
+
# `instance_variable_set` is required here to actually store the wrapped value.
|
|
28
31
|
instance_variable_set(:@children, wrapped)
|
|
29
32
|
end
|
|
30
33
|
end
|
|
@@ -44,10 +47,21 @@ module Coradoc
|
|
|
44
47
|
rc = renderable_content
|
|
45
48
|
case rc
|
|
46
49
|
when String then rc
|
|
47
|
-
when Array then rc.map { |c| c
|
|
50
|
+
when Array then rc.map { |c| extract_child_text(c) }.join
|
|
48
51
|
else rc.to_s
|
|
49
52
|
end
|
|
50
53
|
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def extract_child_text(child)
|
|
58
|
+
case child
|
|
59
|
+
when TextContent then child.text
|
|
60
|
+
when String then child
|
|
61
|
+
when Base then child.flat_text
|
|
62
|
+
else child.to_s
|
|
63
|
+
end
|
|
64
|
+
end
|
|
51
65
|
end
|
|
52
66
|
end
|
|
53
67
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Single-line comment — editorial or hidden notes that do not render.
|
|
6
|
+
#
|
|
7
|
+
# Distinct from {CommentBlock} (multi-line). Round-trip fidelity for the
|
|
8
|
+
# single-line vs. block distinction is preserved across formats that have
|
|
9
|
+
# a single-line comment syntax (AsciiDoc `//`); formats without one (e.g.
|
|
10
|
+
# Markdown) collapse both to `<!-- ... -->`.
|
|
11
|
+
class CommentLine < Base
|
|
12
|
+
def self.semantic_type
|
|
13
|
+
:comment_line
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attribute :text, :string
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module CoreModel
|
|
7
|
+
class FrontmatterBlock
|
|
8
|
+
# Single source of truth for YAML ↔ FrontmatterBlock translation.
|
|
9
|
+
#
|
|
10
|
+
# No other code in any gem may call YAML directly for frontmatter.
|
|
11
|
+
# This isolates permitted-classes configuration and error handling
|
|
12
|
+
# in one MECE location (DRY).
|
|
13
|
+
module Codec
|
|
14
|
+
PERMITTED_CLASSES = [Date, Time, DateTime, Symbol].freeze
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
# Parse a YAML string into a FrontmatterBlock.
|
|
18
|
+
# Returns an empty FrontmatterBlock on malformed YAML (graceful
|
|
19
|
+
# degradation — body parsing continues).
|
|
20
|
+
def from_yaml(yaml_text)
|
|
21
|
+
return FrontmatterBlock.new if yaml_text.nil? || yaml_text.strip.empty?
|
|
22
|
+
|
|
23
|
+
parsed = YAML.safe_load(
|
|
24
|
+
yaml_text,
|
|
25
|
+
permitted_classes: PERMITTED_CLASSES,
|
|
26
|
+
aliases: true
|
|
27
|
+
)
|
|
28
|
+
return FrontmatterBlock.new unless parsed.is_a?(Hash)
|
|
29
|
+
|
|
30
|
+
schema = parsed['$schema']
|
|
31
|
+
data = parsed.except('$schema')
|
|
32
|
+
FrontmatterBlock.new(schema: schema&.to_s, data: data)
|
|
33
|
+
rescue YAML::SyntaxError, Psych::DisallowedClass
|
|
34
|
+
FrontmatterBlock.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Serialize a FrontmatterBlock to canonical YAML text.
|
|
38
|
+
# Does NOT include leading/trailing `---` delimiters; the caller
|
|
39
|
+
# wraps the output.
|
|
40
|
+
def to_yaml(block)
|
|
41
|
+
return '' unless block.is_a?(FrontmatterBlock)
|
|
42
|
+
|
|
43
|
+
tree = {}
|
|
44
|
+
tree['$schema'] = block.schema if block.schema
|
|
45
|
+
tree.merge!(block.data || {})
|
|
46
|
+
return '' if tree.empty?
|
|
47
|
+
|
|
48
|
+
YAML.dump(tree).delete_prefix("---\n").delete_suffix("\n...")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
class FrontmatterBlock
|
|
6
|
+
# OCP registry for semantic field transforms applied during
|
|
7
|
+
# format conversion (e.g., `authors` array → `author` string when
|
|
8
|
+
# emitting Markdown for Jekyll).
|
|
9
|
+
#
|
|
10
|
+
# Transforms are directional + format-specific. Each transform
|
|
11
|
+
# declares when it applies and how it rewrites the block's data
|
|
12
|
+
# hash. Never mutates the input — always returns a new block.
|
|
13
|
+
module FieldTransform
|
|
14
|
+
# Base class. Override #applies? and #apply in subclasses.
|
|
15
|
+
class Base
|
|
16
|
+
# Override: return true if this transform should fire for the
|
|
17
|
+
# given direction (:to_format or :from_format) and format
|
|
18
|
+
# (:markdown, :asciidoc, etc.).
|
|
19
|
+
def applies?(direction:, format:) # rubocop:disable Lint/UnusedMethodArgument
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Override: receive a FrontmatterBlock, return a (possibly new)
|
|
24
|
+
# FrontmatterBlock. Never mutate the input.
|
|
25
|
+
def apply(block)
|
|
26
|
+
block
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
protected
|
|
30
|
+
|
|
31
|
+
# Helper: produce a new FrontmatterBlock with transformed data.
|
|
32
|
+
def rebuild(block, data:)
|
|
33
|
+
FrontmatterBlock.new(schema: block.schema, data: data)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class Registry
|
|
38
|
+
DEFAULT = new
|
|
39
|
+
|
|
40
|
+
def initialize
|
|
41
|
+
@transforms = []
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def register(transform_class)
|
|
45
|
+
@transforms << transform_class unless @transforms.include?(transform_class)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def count
|
|
49
|
+
@transforms.size
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Apply all registered transforms whose #applies? returns true.
|
|
53
|
+
# Returns a FrontmatterBlock (possibly the same one).
|
|
54
|
+
def apply_all(block, direction:, format:)
|
|
55
|
+
return block unless block.is_a?(FrontmatterBlock)
|
|
56
|
+
|
|
57
|
+
@transforms.reduce(block) do |current, klass|
|
|
58
|
+
transform = klass.new
|
|
59
|
+
if transform.applies?(direction: direction, format: format)
|
|
60
|
+
transform.apply(current)
|
|
61
|
+
else
|
|
62
|
+
current
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
class FrontmatterBlock
|
|
6
|
+
# OCP registry mapping `$schema` URLs to validator classes.
|
|
7
|
+
#
|
|
8
|
+
# Core ships with NO built-in validators. Downstream gems (e.g.,
|
|
9
|
+
# a future `coradoc-jsonschema`) register resolvers without
|
|
10
|
+
# modifying core code.
|
|
11
|
+
module SchemaResolver
|
|
12
|
+
# Structured validation error. Typed — never a hash bag.
|
|
13
|
+
ValidationError = Struct.new(:field, :message, keyword_init: true)
|
|
14
|
+
|
|
15
|
+
# Base class for schema resolvers. Override #validate in subclasses.
|
|
16
|
+
class Base
|
|
17
|
+
def validate(_block)
|
|
18
|
+
[]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Registry of URL → resolver class.
|
|
23
|
+
class Registry
|
|
24
|
+
DEFAULT = new
|
|
25
|
+
|
|
26
|
+
def initialize
|
|
27
|
+
@resolvers = {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def register(schema_url, resolver_class)
|
|
31
|
+
@resolvers[schema_url.to_s] = resolver_class
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def lookup(schema_url)
|
|
35
|
+
@resolvers[schema_url.to_s]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def registered?(schema_url)
|
|
39
|
+
@resolvers.key?(schema_url.to_s)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Returns array of ValidationError structs. Empty if no schema,
|
|
43
|
+
# no resolver, or validation passes.
|
|
44
|
+
def validate(block)
|
|
45
|
+
return [] unless block.is_a?(FrontmatterBlock)
|
|
46
|
+
return [] if block.schema.nil?
|
|
47
|
+
|
|
48
|
+
resolver_class = lookup(block.schema)
|
|
49
|
+
return [] unless resolver_class
|
|
50
|
+
|
|
51
|
+
resolver_class.new.validate(block)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
class FrontmatterBlock
|
|
6
|
+
# Format-agnostic text splitter for the YAML frontmatter block
|
|
7
|
+
# convention (`---\n...\n---\n` at the very start of a document).
|
|
8
|
+
#
|
|
9
|
+
# Lives under FrontmatterBlock alongside Codec, SchemaResolver,
|
|
10
|
+
# and FieldTransform — together they form the complete frontmatter
|
|
11
|
+
# machinery (MECE):
|
|
12
|
+
#
|
|
13
|
+
# TextSplitter — text → (frontmatter_text, body_text)
|
|
14
|
+
# Codec — frontmatter_text ↔ typed FrontmatterBlock
|
|
15
|
+
# SchemaResolver — typed FrontmatterBlock → validation errors
|
|
16
|
+
# FieldTransform — typed FrontmatterBlock → transformed block
|
|
17
|
+
#
|
|
18
|
+
# Format gems (Markdown, AsciiDoc, ...) call this splitter at the
|
|
19
|
+
# top of their parse pipeline so frontmatter never reaches the
|
|
20
|
+
# format's block parser. Single source of truth (DRY).
|
|
21
|
+
module TextSplitter
|
|
22
|
+
OPEN_DELIMITER = '---'
|
|
23
|
+
CLOSE_DELIMITERS = %w[--- ...].freeze
|
|
24
|
+
|
|
25
|
+
# Result of splitting source text. +frontmatter+ is the raw YAML
|
|
26
|
+
# body (without delimiters), nil if no frontmatter was present.
|
|
27
|
+
# +body+ is the remaining document text.
|
|
28
|
+
Result = Struct.new(:frontmatter, :body, keyword_init: true) do
|
|
29
|
+
def frontmatter?
|
|
30
|
+
!frontmatter.nil? && !frontmatter.empty?
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class << self
|
|
35
|
+
# @param text [String, nil] Source document text.
|
|
36
|
+
# @return [Result]
|
|
37
|
+
def call(text)
|
|
38
|
+
return Result.new(frontmatter: nil, body: '') if text.nil? || text.empty?
|
|
39
|
+
|
|
40
|
+
lines = text.lines
|
|
41
|
+
return empty_with(text) unless opens_frontmatter?(lines.first)
|
|
42
|
+
|
|
43
|
+
close_index = find_close_line(lines, 1)
|
|
44
|
+
return empty_with(text) if close_index.nil?
|
|
45
|
+
|
|
46
|
+
frontmatter = lines[1...close_index].join
|
|
47
|
+
body = lines[(close_index + 1)..].join
|
|
48
|
+
body = body.sub(/\A\n+/, '') if body.start_with?("\n")
|
|
49
|
+
|
|
50
|
+
Result.new(frontmatter: frontmatter, body: body)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def opens_frontmatter?(first_line)
|
|
56
|
+
return false unless first_line
|
|
57
|
+
|
|
58
|
+
first_line.strip == OPEN_DELIMITER
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def find_close_line(lines, start_at)
|
|
62
|
+
start_at.upto(lines.size - 1) do |i|
|
|
63
|
+
return i if CLOSE_DELIMITERS.include?(lines[i].strip)
|
|
64
|
+
end
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def empty_with(text)
|
|
69
|
+
Result.new(frontmatter: nil, body: text)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# First-class block representing YAML frontmatter attached to a
|
|
6
|
+
# document.
|
|
7
|
+
#
|
|
8
|
+
# Frontmatter is modeled as a Block (not a side-attribute on
|
|
9
|
+
# DocumentElement) so it flows through the standard block pipeline:
|
|
10
|
+
# parsers produce it, transformers dispatch on its class, serializers
|
|
11
|
+
# emit it. No special-casing anywhere.
|
|
12
|
+
#
|
|
13
|
+
# The +data+ hash stores the entire parsed YAML frontmatter (minus
|
|
14
|
+
# +$schema+, which is promoted to the +schema+ attribute). Using a
|
|
15
|
+
# hash — rather than a typed value tree — lets coradoc accept any
|
|
16
|
+
# frontmatter shape without code changes. Type handling is delegated
|
|
17
|
+
# to Ruby's native YAML/JSON, which already preserve Date, Integer,
|
|
18
|
+
# Float, Boolean, nil, Array, and Hash correctly for YAML round-trips.
|
|
19
|
+
#
|
|
20
|
+
# The +$schema+ key, if present in source YAML, is promoted to the
|
|
21
|
+
# +schema+ attribute (single source of truth — DRY); SchemaResolver
|
|
22
|
+
# reads it to find validators.
|
|
23
|
+
class FrontmatterBlock < Block
|
|
24
|
+
def self.semantic_type
|
|
25
|
+
:frontmatter
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.element_type_name
|
|
29
|
+
'frontmatter'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# `$schema` URL, nil-safe. Consumed by SchemaResolver registry.
|
|
33
|
+
attribute :schema, :string
|
|
34
|
+
|
|
35
|
+
# Entire parsed YAML frontmatter (minus `$schema`). Values are
|
|
36
|
+
# native Ruby types from YAML.safe_load (String, Integer, Date,
|
|
37
|
+
# Array, Hash, etc.). Order is preserved for round-trip fidelity.
|
|
38
|
+
attribute :data, :hash, default: {}
|
|
39
|
+
|
|
40
|
+
# Convenience accessor — read a single entry by key.
|
|
41
|
+
def entry(key)
|
|
42
|
+
data[key.to_s]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def has_entry?(key)
|
|
46
|
+
data.key?(key.to_s)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def empty?
|
|
50
|
+
schema.nil? && (data.nil? || data.empty?)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Sub-namespaces (Codec, SchemaResolver, FieldTransform, TextSplitter)
|
|
54
|
+
# live under FrontmatterBlock and autoload lazily.
|
|
55
|
+
autoload :Codec, "#{__dir__}/frontmatter/codec"
|
|
56
|
+
autoload :SchemaResolver, "#{__dir__}/frontmatter/schema_resolver"
|
|
57
|
+
autoload :FieldTransform, "#{__dir__}/frontmatter/field_transform"
|
|
58
|
+
autoload :TextSplitter, "#{__dir__}/frontmatter/text_splitter"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
data/lib/coradoc/core_model.rb
CHANGED
|
@@ -49,6 +49,7 @@ module Coradoc
|
|
|
49
49
|
autoload :ElementAttribute, "#{__dir__}/core_model/element_attribute"
|
|
50
50
|
autoload :Metadata, "#{__dir__}/core_model/metadata"
|
|
51
51
|
autoload :MetadataEntry, "#{__dir__}/core_model/metadata"
|
|
52
|
+
autoload :FrontmatterBlock, "#{__dir__}/core_model/frontmatter"
|
|
52
53
|
autoload :Footnote, "#{__dir__}/core_model/footnote"
|
|
53
54
|
autoload :FootnoteReference, "#{__dir__}/core_model/footnote"
|
|
54
55
|
autoload :Abbreviation, "#{__dir__}/core_model/footnote"
|
|
@@ -71,6 +72,7 @@ module Coradoc
|
|
|
71
72
|
autoload :ReviewerBlock, "#{__dir__}/core_model/reviewer_block"
|
|
72
73
|
autoload :ParagraphBlock, "#{__dir__}/core_model/paragraph_block"
|
|
73
74
|
autoload :CommentBlock, "#{__dir__}/core_model/comment_block"
|
|
75
|
+
autoload :CommentLine, "#{__dir__}/core_model/comment_line"
|
|
74
76
|
autoload :HorizontalRuleBlock, "#{__dir__}/core_model/horizontal_rule_block"
|
|
75
77
|
autoload :IdGenerator, "#{__dir__}/core_model/id_generator"
|
|
76
78
|
end
|
data/lib/coradoc/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coradoc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -62,11 +62,17 @@ files:
|
|
|
62
62
|
- lib/coradoc/core_model/block.rb
|
|
63
63
|
- lib/coradoc/core_model/children_content.rb
|
|
64
64
|
- lib/coradoc/core_model/comment_block.rb
|
|
65
|
+
- lib/coradoc/core_model/comment_line.rb
|
|
65
66
|
- lib/coradoc/core_model/definition_item.rb
|
|
66
67
|
- lib/coradoc/core_model/definition_list.rb
|
|
67
68
|
- lib/coradoc/core_model/element_attribute.rb
|
|
68
69
|
- lib/coradoc/core_model/example_block.rb
|
|
69
70
|
- lib/coradoc/core_model/footnote.rb
|
|
71
|
+
- lib/coradoc/core_model/frontmatter.rb
|
|
72
|
+
- lib/coradoc/core_model/frontmatter/codec.rb
|
|
73
|
+
- lib/coradoc/core_model/frontmatter/field_transform.rb
|
|
74
|
+
- lib/coradoc/core_model/frontmatter/schema_resolver.rb
|
|
75
|
+
- lib/coradoc/core_model/frontmatter/text_splitter.rb
|
|
70
76
|
- lib/coradoc/core_model/horizontal_rule_block.rb
|
|
71
77
|
- lib/coradoc/core_model/id_generator.rb
|
|
72
78
|
- lib/coradoc/core_model/image.rb
|