coradoc-adoc 2.0.0
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 +7 -0
- data/.rspec +3 -0
- data/lib/coradoc/asciidoc/model/admonition.rb +37 -0
- data/lib/coradoc/asciidoc/model/anchorable.rb +64 -0
- data/lib/coradoc/asciidoc/model/attached.rb +26 -0
- data/lib/coradoc/asciidoc/model/attribute.rb +22 -0
- data/lib/coradoc/asciidoc/model/attribute_list/matchers.rb +45 -0
- data/lib/coradoc/asciidoc/model/attribute_list.rb +230 -0
- data/lib/coradoc/asciidoc/model/attribute_list_attribute.rb +11 -0
- data/lib/coradoc/asciidoc/model/audio.rb +44 -0
- data/lib/coradoc/asciidoc/model/author.rb +36 -0
- data/lib/coradoc/asciidoc/model/base.rb +141 -0
- data/lib/coradoc/asciidoc/model/bibliography.rb +37 -0
- data/lib/coradoc/asciidoc/model/bibliography_entry.rb +38 -0
- data/lib/coradoc/asciidoc/model/block/core.rb +139 -0
- data/lib/coradoc/asciidoc/model/block/example.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/listing.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/literal.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/open.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/pass.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/quote.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/reviewer_comment.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/side.rb +14 -0
- data/lib/coradoc/asciidoc/model/block/source_code.rb +14 -0
- data/lib/coradoc/asciidoc/model/block.rb +21 -0
- data/lib/coradoc/asciidoc/model/break.rb +33 -0
- data/lib/coradoc/asciidoc/model/comment_block.rb +33 -0
- data/lib/coradoc/asciidoc/model/comment_line.rb +30 -0
- data/lib/coradoc/asciidoc/model/content_list.rb +334 -0
- data/lib/coradoc/asciidoc/model/document.rb +197 -0
- data/lib/coradoc/asciidoc/model/document_attributes.rb +43 -0
- data/lib/coradoc/asciidoc/model/glossaries.rb +11 -0
- data/lib/coradoc/asciidoc/model/header.rb +57 -0
- data/lib/coradoc/asciidoc/model/highlight.rb +11 -0
- data/lib/coradoc/asciidoc/model/image/block_image/attribute_list.rb +23 -0
- data/lib/coradoc/asciidoc/model/image/block_image.rb +25 -0
- data/lib/coradoc/asciidoc/model/image/core/attribute_list.rb +43 -0
- data/lib/coradoc/asciidoc/model/image/core.rb +72 -0
- data/lib/coradoc/asciidoc/model/image/inline_image.rb +17 -0
- data/lib/coradoc/asciidoc/model/image.rb +14 -0
- data/lib/coradoc/asciidoc/model/include.rb +66 -0
- data/lib/coradoc/asciidoc/model/inline/anchor.rb +41 -0
- data/lib/coradoc/asciidoc/model/inline/attribute_reference.rb +25 -0
- data/lib/coradoc/asciidoc/model/inline/base.rb +15 -0
- data/lib/coradoc/asciidoc/model/inline/bold.rb +38 -0
- data/lib/coradoc/asciidoc/model/inline/cross_reference.rb +29 -0
- data/lib/coradoc/asciidoc/model/inline/cross_reference_arg.rb +15 -0
- data/lib/coradoc/asciidoc/model/inline/footnote.rb +34 -0
- data/lib/coradoc/asciidoc/model/inline/hard_line_break.rb +24 -0
- data/lib/coradoc/asciidoc/model/inline/highlight.rb +36 -0
- data/lib/coradoc/asciidoc/model/inline/italic.rb +38 -0
- data/lib/coradoc/asciidoc/model/inline/link.rb +46 -0
- data/lib/coradoc/asciidoc/model/inline/monospace.rb +39 -0
- data/lib/coradoc/asciidoc/model/inline/quotation.rb +25 -0
- data/lib/coradoc/asciidoc/model/inline/small.rb +25 -0
- data/lib/coradoc/asciidoc/model/inline/span.rb +38 -0
- data/lib/coradoc/asciidoc/model/inline/stem.rb +24 -0
- data/lib/coradoc/asciidoc/model/inline/strikethrough.rb +39 -0
- data/lib/coradoc/asciidoc/model/inline/subscript.rb +33 -0
- data/lib/coradoc/asciidoc/model/inline/superscript.rb +33 -0
- data/lib/coradoc/asciidoc/model/inline/underline.rb +25 -0
- data/lib/coradoc/asciidoc/model/inline.rb +31 -0
- data/lib/coradoc/asciidoc/model/line_break.rb +11 -0
- data/lib/coradoc/asciidoc/model/list/core.rb +61 -0
- data/lib/coradoc/asciidoc/model/list/definition.rb +27 -0
- data/lib/coradoc/asciidoc/model/list/definition_item.rb +43 -0
- data/lib/coradoc/asciidoc/model/list/item.rb +72 -0
- data/lib/coradoc/asciidoc/model/list/nestable.rb +14 -0
- data/lib/coradoc/asciidoc/model/list/ordered.rb +34 -0
- data/lib/coradoc/asciidoc/model/list/unordered.rb +34 -0
- data/lib/coradoc/asciidoc/model/list.rb +29 -0
- data/lib/coradoc/asciidoc/model/named_attribute.rb +12 -0
- data/lib/coradoc/asciidoc/model/paragraph.rb +59 -0
- data/lib/coradoc/asciidoc/model/rejected_positional_attribute.rb +12 -0
- data/lib/coradoc/asciidoc/model/resolvable.rb +71 -0
- data/lib/coradoc/asciidoc/model/resolver.rb +430 -0
- data/lib/coradoc/asciidoc/model/reviewer_note.rb +54 -0
- data/lib/coradoc/asciidoc/model/revision.rb +47 -0
- data/lib/coradoc/asciidoc/model/section.rb +109 -0
- data/lib/coradoc/asciidoc/model/serialization/asciidoc_adapter.rb +28 -0
- data/lib/coradoc/asciidoc/model/serialization/asciidoc_mapping.rb +42 -0
- data/lib/coradoc/asciidoc/model/serialization/asciidoc_mapping_rule.rb +41 -0
- data/lib/coradoc/asciidoc/model/serialization/asciidoc_transform.rb +211 -0
- data/lib/coradoc/asciidoc/model/serialization/errors.rb +57 -0
- data/lib/coradoc/asciidoc/model/serialization.rb +39 -0
- data/lib/coradoc/asciidoc/model/spacing.rb +282 -0
- data/lib/coradoc/asciidoc/model/table.rb +44 -0
- data/lib/coradoc/asciidoc/model/table_cell.rb +122 -0
- data/lib/coradoc/asciidoc/model/table_row.rb +26 -0
- data/lib/coradoc/asciidoc/model/tag.rb +36 -0
- data/lib/coradoc/asciidoc/model/term.rb +48 -0
- data/lib/coradoc/asciidoc/model/text_element.rb +66 -0
- data/lib/coradoc/asciidoc/model/title.rb +85 -0
- data/lib/coradoc/asciidoc/model/video/attribute_list.rb +43 -0
- data/lib/coradoc/asciidoc/model/video.rb +49 -0
- data/lib/coradoc/asciidoc/model.rb +75 -0
- data/lib/coradoc/asciidoc/parse_error.rb +161 -0
- data/lib/coradoc/asciidoc/parser/admonition.rb +26 -0
- data/lib/coradoc/asciidoc/parser/attribute_list.rb +110 -0
- data/lib/coradoc/asciidoc/parser/base.rb +159 -0
- data/lib/coradoc/asciidoc/parser/bibliography.rb +31 -0
- data/lib/coradoc/asciidoc/parser/block.rb +186 -0
- data/lib/coradoc/asciidoc/parser/block_assembler.rb +183 -0
- data/lib/coradoc/asciidoc/parser/cache.rb +155 -0
- data/lib/coradoc/asciidoc/parser/citation.rb +32 -0
- data/lib/coradoc/asciidoc/parser/content.rb +76 -0
- data/lib/coradoc/asciidoc/parser/document_attributes.rb +27 -0
- data/lib/coradoc/asciidoc/parser/fix_files.rb +76 -0
- data/lib/coradoc/asciidoc/parser/header.rb +31 -0
- data/lib/coradoc/asciidoc/parser/inline.rb +199 -0
- data/lib/coradoc/asciidoc/parser/list.rb +130 -0
- data/lib/coradoc/asciidoc/parser/metadata_detector.rb +164 -0
- data/lib/coradoc/asciidoc/parser/paragraph.rb +64 -0
- data/lib/coradoc/asciidoc/parser/section.rb +62 -0
- data/lib/coradoc/asciidoc/parser/stem.rb +19 -0
- data/lib/coradoc/asciidoc/parser/table.rb +166 -0
- data/lib/coradoc/asciidoc/parser/term.rb +70 -0
- data/lib/coradoc/asciidoc/parser/text.rb +156 -0
- data/lib/coradoc/asciidoc/parser.rb +10 -0
- data/lib/coradoc/asciidoc/serializer/adoc_serializer.rb +86 -0
- data/lib/coradoc/asciidoc/serializer/element_registry.rb +95 -0
- data/lib/coradoc/asciidoc/serializer/fallback_serializer.rb +21 -0
- data/lib/coradoc/asciidoc/serializer/formatter.rb +144 -0
- data/lib/coradoc/asciidoc/serializer/registrations.rb +108 -0
- data/lib/coradoc/asciidoc/serializer/serialization_context.rb +238 -0
- data/lib/coradoc/asciidoc/serializer/serializers/admonition.rb +19 -0
- data/lib/coradoc/asciidoc/serializer/serializers/attribute.rb +23 -0
- data/lib/coradoc/asciidoc/serializer/serializers/attribute_list.rb +40 -0
- data/lib/coradoc/asciidoc/serializer/serializers/attribute_list_attribute.rb +18 -0
- data/lib/coradoc/asciidoc/serializer/serializers/audio.rb +33 -0
- data/lib/coradoc/asciidoc/serializer/serializers/author.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/base.rb +152 -0
- data/lib/coradoc/asciidoc/serializer/serializers/bibliography.rb +35 -0
- data/lib/coradoc/asciidoc/serializer/serializers/bibliography_entry.rb +24 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/core.rb +70 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/example.rb +17 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/listing.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/literal.rb +17 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/open.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/pass.rb +17 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/quote.rb +17 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/reviewer_comment.rb +17 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/side.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block/source_code.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/block.rb +23 -0
- data/lib/coradoc/asciidoc/serializer/serializers/break.rb +18 -0
- data/lib/coradoc/asciidoc/serializer/serializers/comment_block.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/comment_line.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/document.rb +65 -0
- data/lib/coradoc/asciidoc/serializer/serializers/document_attributes.rb +21 -0
- data/lib/coradoc/asciidoc/serializer/serializers/header.rb +24 -0
- data/lib/coradoc/asciidoc/serializer/serializers/highlight.rb +23 -0
- data/lib/coradoc/asciidoc/serializer/serializers/image/core.rb +30 -0
- data/lib/coradoc/asciidoc/serializer/serializers/image.rb +14 -0
- data/lib/coradoc/asciidoc/serializer/serializers/include.rb +19 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/anchor.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/attribute_reference.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/bold.rb +26 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/cross_reference.rb +30 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/cross_reference_arg.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/footnote.rb +24 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/hard_line_break.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/highlight.rb +26 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/italic.rb +26 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/link.rb +38 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/monospace.rb +26 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/quotation.rb +21 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/small.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/span.rb +35 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/stem.rb +23 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/strikethrough.rb +29 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/subscript.rb +29 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/superscript.rb +26 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline/underline.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/inline.rb +32 -0
- data/lib/coradoc/asciidoc/serializer/serializers/line_break.rb +18 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list/core.rb +47 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list/definition.rb +35 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list/definition_item.rb +38 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list/item.rb +120 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list/ordered.rb +24 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list/unordered.rb +29 -0
- data/lib/coradoc/asciidoc/serializer/serializers/list.rb +19 -0
- data/lib/coradoc/asciidoc/serializer/serializers/named_attribute.rb +22 -0
- data/lib/coradoc/asciidoc/serializer/serializers/paragraph.rb +65 -0
- data/lib/coradoc/asciidoc/serializer/serializers/reviewer_note.rb +28 -0
- data/lib/coradoc/asciidoc/serializer/serializers/revision.rb +26 -0
- data/lib/coradoc/asciidoc/serializer/serializers/section.rb +37 -0
- data/lib/coradoc/asciidoc/serializer/serializers/table.rb +24 -0
- data/lib/coradoc/asciidoc/serializer/serializers/table_cell.rb +75 -0
- data/lib/coradoc/asciidoc/serializer/serializers/table_row.rb +24 -0
- data/lib/coradoc/asciidoc/serializer/serializers/tag.rb +19 -0
- data/lib/coradoc/asciidoc/serializer/serializers/term.rb +20 -0
- data/lib/coradoc/asciidoc/serializer/serializers/text_element.rb +23 -0
- data/lib/coradoc/asciidoc/serializer/serializers/title.rb +55 -0
- data/lib/coradoc/asciidoc/serializer/serializers/video.rb +33 -0
- data/lib/coradoc/asciidoc/serializer/spacing_strategy.rb +70 -0
- data/lib/coradoc/asciidoc/serializer.rb +75 -0
- data/lib/coradoc/asciidoc/transform/from_core_model.rb +502 -0
- data/lib/coradoc/asciidoc/transform/from_core_model_registrations.rb +126 -0
- data/lib/coradoc/asciidoc/transform/registry.rb +146 -0
- data/lib/coradoc/asciidoc/transform/to_core_model.rb +564 -0
- data/lib/coradoc/asciidoc/transform/to_core_model_registrations.rb +257 -0
- data/lib/coradoc/asciidoc/transform.rb +13 -0
- data/lib/coradoc/asciidoc/transformer/block_rules.rb +101 -0
- data/lib/coradoc/asciidoc/transformer/header_rules.rb +91 -0
- data/lib/coradoc/asciidoc/transformer/inline_rules.rb +179 -0
- data/lib/coradoc/asciidoc/transformer/list_rules.rb +131 -0
- data/lib/coradoc/asciidoc/transformer/misc_rules.rb +196 -0
- data/lib/coradoc/asciidoc/transformer/structural_rules.rb +216 -0
- data/lib/coradoc/asciidoc/transformer/text_rules.rb +107 -0
- data/lib/coradoc/asciidoc/transformer.rb +406 -0
- data/lib/coradoc/asciidoc/version.rb +7 -0
- data/lib/coradoc/asciidoc.rb +148 -0
- data/lib/coradoc/util/asciidoc.rb +71 -0
- data/lib/coradoc/util.rb +8 -0
- metadata +343 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
# Section element for organizing document content hierarchically.
|
|
7
|
+
#
|
|
8
|
+
# Sections represent the hierarchical structure of an AsciiDoc document.
|
|
9
|
+
# They can contain nested subsections, paragraphs, and other content.
|
|
10
|
+
#
|
|
11
|
+
# @!attribute [r] id
|
|
12
|
+
# @return [String, nil] Optional identifier for the section
|
|
13
|
+
# @!attribute [r] content
|
|
14
|
+
# @return [String, nil] Optional string content (typically unused, see contents)
|
|
15
|
+
# @!attribute [r] title
|
|
16
|
+
# @return [Title] Section title
|
|
17
|
+
# @!attribute [r] attrs
|
|
18
|
+
# @return [Array<NamedAttribute>] Additional named attributes
|
|
19
|
+
# @!attribute [r] contents
|
|
20
|
+
# @return [Array<Paragraph>] Paragraph content within this section
|
|
21
|
+
# @!attribute [r] sections
|
|
22
|
+
# @return [Array<Section>] Nested subsections
|
|
23
|
+
#
|
|
24
|
+
# @example Create a section
|
|
25
|
+
# section = Coradoc::AsciiDoc::Model::Section.new(
|
|
26
|
+
# title: Coradoc::AsciiDoc::Model::Title.new("Chapter 1"),
|
|
27
|
+
# contents: [Coradoc::AsciiDoc::Model::Paragraph.new("Content here")]
|
|
28
|
+
# )
|
|
29
|
+
#
|
|
30
|
+
# @example Create nested sections
|
|
31
|
+
# parent = Coradoc::AsciiDoc::Model::Section.new(
|
|
32
|
+
# title: Coradoc::AsciiDoc::Model::Title.new("Parent Section")
|
|
33
|
+
# )
|
|
34
|
+
# child = Coradoc::AsciiDoc::Model::Section.new(
|
|
35
|
+
# title: Coradoc::AsciiDoc::Model::Title.new("Child Section")
|
|
36
|
+
# )
|
|
37
|
+
# parent.sections << child
|
|
38
|
+
#
|
|
39
|
+
class Section < Base
|
|
40
|
+
include Coradoc::AsciiDoc::Model::Anchorable
|
|
41
|
+
|
|
42
|
+
def block_level?
|
|
43
|
+
true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
attribute :id, :string
|
|
47
|
+
attribute :content, :string
|
|
48
|
+
attribute :title, Coradoc::AsciiDoc::Model::Title
|
|
49
|
+
attribute :attrs,
|
|
50
|
+
Coradoc::AsciiDoc::Model::NamedAttribute,
|
|
51
|
+
collection: true,
|
|
52
|
+
initialize_empty: true
|
|
53
|
+
attribute :contents,
|
|
54
|
+
Coradoc::AsciiDoc::Model::Paragraph,
|
|
55
|
+
collection: true,
|
|
56
|
+
initialize_empty: true
|
|
57
|
+
attribute :sections,
|
|
58
|
+
Coradoc::AsciiDoc::Model::Section,
|
|
59
|
+
collection: true,
|
|
60
|
+
initialize_empty: true
|
|
61
|
+
# attribute :anchor, Coradoc::AsciiDoc::Model::Inline::Anchor
|
|
62
|
+
|
|
63
|
+
# Allow setting level directly during initialization
|
|
64
|
+
def initialize(**attributes)
|
|
65
|
+
level_value = attributes.delete(:level)
|
|
66
|
+
super
|
|
67
|
+
if level_value && title
|
|
68
|
+
title.level_int = level_value
|
|
69
|
+
elsif level_value
|
|
70
|
+
self.title = Coradoc::AsciiDoc::Model::Title.new(content: '', level_int: level_value)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def validate
|
|
75
|
+
validate_title_type
|
|
76
|
+
super
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Get the section level from the title
|
|
80
|
+
# @return [Integer, nil] The section level (0-5 for standard sections)
|
|
81
|
+
def level
|
|
82
|
+
title&.level_int
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Set the section level on the title
|
|
86
|
+
# @param value [Integer] The section level
|
|
87
|
+
def level=(value)
|
|
88
|
+
if title
|
|
89
|
+
title.level_int = value
|
|
90
|
+
else
|
|
91
|
+
self.title = Coradoc::AsciiDoc::Model::Title.new(content: '', level_int: value)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def safe_to_collapse?
|
|
96
|
+
title.nil? && sections.empty?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def validate_title_type
|
|
102
|
+
return if title.nil? || title.is_a?(Coradoc::AsciiDoc::Model::Title)
|
|
103
|
+
|
|
104
|
+
raise TypeError, "title must be a Coradoc::AsciiDoc::Model::Title, got #{title.class}"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
module Serialization
|
|
7
|
+
# Adapter for AsciiDoc serialization in Lutaml::Model format registry.
|
|
8
|
+
#
|
|
9
|
+
# This is a standalone adapter class that delegates to Coradoc's
|
|
10
|
+
# parsing infrastructure. It does NOT inherit from Base to avoid
|
|
11
|
+
# circular dependencies with the format registration system.
|
|
12
|
+
#
|
|
13
|
+
class AsciidocAdapter
|
|
14
|
+
# Delegate to Model::Document for AST creation
|
|
15
|
+
def self.from_ast(elements)
|
|
16
|
+
# Lazy reference to avoid loading Document before format is registered
|
|
17
|
+
Coradoc::AsciiDoc::Model::Document.from_ast(elements)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Delegate to Coradoc.parse for parsing
|
|
21
|
+
def self.parse(string)
|
|
22
|
+
Coradoc.parse(string)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
module Serialization
|
|
7
|
+
# Define the DSL for defining mappings in Asciidoc format
|
|
8
|
+
class AsciidocMapping < Lutaml::Model::Mapping
|
|
9
|
+
attr_reader :mappings
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
super
|
|
13
|
+
@mappings = []
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def map_model(to:)
|
|
17
|
+
add_mapping('__element', to, field_type: :parsed_element)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def map_content(to:)
|
|
21
|
+
add_mapping('__content', to, field_type: :content)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def map_attribute(name, to:, render_nil: false)
|
|
25
|
+
add_mapping(
|
|
26
|
+
name,
|
|
27
|
+
to,
|
|
28
|
+
field_type: :attributes,
|
|
29
|
+
render_nil: render_nil
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def add_mapping(name, to, **options)
|
|
36
|
+
@mappings << AsciidocMappingRule.new(name, to: to, **options)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
module Serialization
|
|
7
|
+
class AsciidocMappingRule < Lutaml::Model::MappingRule
|
|
8
|
+
# Can be :parsed_element, :content, or :attributes
|
|
9
|
+
attr_reader :field_type
|
|
10
|
+
|
|
11
|
+
def initialize(
|
|
12
|
+
name,
|
|
13
|
+
to:,
|
|
14
|
+
render_nil: false,
|
|
15
|
+
field_type: :attributes
|
|
16
|
+
)
|
|
17
|
+
super(name, to:, render_nil:)
|
|
18
|
+
@field_type = field_type
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def model_map?
|
|
22
|
+
field_type == :parsed_element
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def content?
|
|
26
|
+
field_type == :content
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def deep_dup
|
|
30
|
+
self.class.new(
|
|
31
|
+
name.dup,
|
|
32
|
+
to: to.dup,
|
|
33
|
+
render_nil: render_nil.dup,
|
|
34
|
+
field_type:
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
module Serialization
|
|
7
|
+
# Transform class for converting between Coradoc::Element and Lutaml::Model objects
|
|
8
|
+
#
|
|
9
|
+
# This handles bidirectional transformation for AsciiDoc serialization:
|
|
10
|
+
# - data_to_model: Coradoc::Element -> Lutaml::Model::Serializable
|
|
11
|
+
# - model_to_data: Lutaml::Model::Serializable -> Coradoc::Element
|
|
12
|
+
#
|
|
13
|
+
class AsciidocTransform < Lutaml::Model::Transform
|
|
14
|
+
# Convert Coradoc::Element data to Lutaml::Model instance
|
|
15
|
+
#
|
|
16
|
+
# @param context [Context] The context with attribute and mapping management
|
|
17
|
+
# @param data [Coradoc::Element::Base] The Coradoc element to convert
|
|
18
|
+
# @param format [Symbol] The format type (:asciidoc)
|
|
19
|
+
# @param options [Hash] Additional options
|
|
20
|
+
# @return [Lutaml::Model::Serializable] The model instance
|
|
21
|
+
def self.data_to_model(context, data, _format, options = {})
|
|
22
|
+
new(context).data_to_model(data, options)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Convert Lutaml::Model instance to Coradoc::Element data
|
|
26
|
+
#
|
|
27
|
+
# @param context [Context] The context with attribute and mapping management
|
|
28
|
+
# @param model [Lutaml::Model::Serializable] The model to convert
|
|
29
|
+
# @param format [Symbol] The format type (:asciidoc)
|
|
30
|
+
# @param options [Hash] Additional options
|
|
31
|
+
# @return [Coradoc::Element::Base] The Coradoc element
|
|
32
|
+
def self.model_to_data(context, model, _format, options = {})
|
|
33
|
+
new(context).model_to_data(model, options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Transform Coradoc::Element to model instance
|
|
37
|
+
def data_to_model(data, options = {})
|
|
38
|
+
return nil if data.nil?
|
|
39
|
+
|
|
40
|
+
# Get mappings for asciidoc format
|
|
41
|
+
mappings = context.mappings_for(:asciidoc)
|
|
42
|
+
return nil unless mappings
|
|
43
|
+
|
|
44
|
+
mapping_rules = mappings.mappings
|
|
45
|
+
return nil unless mapping_rules
|
|
46
|
+
|
|
47
|
+
# Find the parsed_element mapping to get target class
|
|
48
|
+
parsed_element_rule = mapping_rules.find { |m| m.field_type == :parsed_element }
|
|
49
|
+
return nil unless parsed_element_rule
|
|
50
|
+
|
|
51
|
+
target_class = parsed_element_rule.to
|
|
52
|
+
return nil unless target_class
|
|
53
|
+
|
|
54
|
+
# Validate data type if from is specified
|
|
55
|
+
return nil if parsed_element_rule.from && !data.is_a?(parsed_element_rule.from)
|
|
56
|
+
|
|
57
|
+
# Create instance and populate attributes
|
|
58
|
+
instance = target_class.new
|
|
59
|
+
attributes = target_class.attributes
|
|
60
|
+
defaults_used = []
|
|
61
|
+
|
|
62
|
+
mapping_rules.reject(&:model_map?).each do |rule|
|
|
63
|
+
attr = attributes[rule.to]
|
|
64
|
+
next if attr&.derived?
|
|
65
|
+
|
|
66
|
+
# Get value from source data
|
|
67
|
+
source_value = data.public_send(rule.name || rule.to)
|
|
68
|
+
|
|
69
|
+
# Transform the value
|
|
70
|
+
value = transform_value(source_value, attr, options)
|
|
71
|
+
|
|
72
|
+
# Handle defaults
|
|
73
|
+
if value.nil? && (instance.using_default?(rule.to) || rule.render_default)
|
|
74
|
+
defaults_used << rule.to
|
|
75
|
+
value = attr&.default || rule.to_value_for(instance)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Apply value map if present
|
|
79
|
+
value = apply_value_map(value, rule.value_map(:from, options), attr)
|
|
80
|
+
|
|
81
|
+
# Set the value
|
|
82
|
+
instance.public_send(:"#{rule.to}=", value) if value
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Mark defaults as used
|
|
86
|
+
defaults_used.each { |attr_name| instance.using_default_for(attr_name) }
|
|
87
|
+
|
|
88
|
+
instance
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Transform model instance to Coradoc::Element
|
|
92
|
+
def model_to_data(model, options = {})
|
|
93
|
+
return nil if model.nil?
|
|
94
|
+
|
|
95
|
+
# Get mappings for asciidoc format
|
|
96
|
+
mappings = context.mappings_for(:asciidoc)
|
|
97
|
+
return nil unless mappings
|
|
98
|
+
|
|
99
|
+
mapping_rules = mappings.mappings
|
|
100
|
+
return nil unless mapping_rules
|
|
101
|
+
|
|
102
|
+
# Find the parsed_element mapping to get target class
|
|
103
|
+
parsed_element_rule = mapping_rules.find { |m| m.field_type == :parsed_element }
|
|
104
|
+
return nil unless parsed_element_rule
|
|
105
|
+
|
|
106
|
+
target_class = parsed_element_rule.from
|
|
107
|
+
return nil unless target_class
|
|
108
|
+
|
|
109
|
+
# Create instance and populate attributes
|
|
110
|
+
attributes = model.class.attributes
|
|
111
|
+
instance = target_class.new
|
|
112
|
+
|
|
113
|
+
mapping_rules.reject(&:model_map?).each do |rule|
|
|
114
|
+
attr = attributes[rule.to]
|
|
115
|
+
next if attr&.derived?
|
|
116
|
+
|
|
117
|
+
# Get value from model
|
|
118
|
+
model_value = model.public_send(rule.to)
|
|
119
|
+
next if model_value.nil?
|
|
120
|
+
|
|
121
|
+
# Transform the value back
|
|
122
|
+
value = transform_value_to_data(model_value, attr, options)
|
|
123
|
+
|
|
124
|
+
# Set on target instance
|
|
125
|
+
target_attr = rule.name || rule.to
|
|
126
|
+
instance.public_send(:"#{target_attr}=", value)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
instance
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
protected
|
|
133
|
+
|
|
134
|
+
# Transform a value from data to model format
|
|
135
|
+
def transform_value(value, attr, options = {})
|
|
136
|
+
return nil if value.nil?
|
|
137
|
+
|
|
138
|
+
case value
|
|
139
|
+
when Array
|
|
140
|
+
value.map { |v| transform_single_value(v, attr, options) }
|
|
141
|
+
else
|
|
142
|
+
transform_single_value(value, attr, options)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Transform a single value
|
|
147
|
+
def transform_single_value(value, attr, options = {})
|
|
148
|
+
case value
|
|
149
|
+
when Lutaml::Model::Type::Value
|
|
150
|
+
value.value
|
|
151
|
+
when Lutaml::Model::Serializable
|
|
152
|
+
# Recursively transform nested models
|
|
153
|
+
self.class.data_to_model(context, value, :asciidoc, options)
|
|
154
|
+
when Coradoc::Element::Base
|
|
155
|
+
# Already a Coradoc element, may need conversion
|
|
156
|
+
if attr&.type&.<(Lutaml::Model::Type::Value)
|
|
157
|
+
value.is_a?(Coradoc::AsciiDoc::Model::Base) && value.class.attributes.key?(:content) ? value.content : value.to_s
|
|
158
|
+
else
|
|
159
|
+
value
|
|
160
|
+
end
|
|
161
|
+
else
|
|
162
|
+
value
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Transform a value from model to data format
|
|
167
|
+
def transform_value_to_data(value, attr, options = {})
|
|
168
|
+
case value
|
|
169
|
+
when Array
|
|
170
|
+
value.map { |v| transform_single_value_to_data(v, attr, options) }
|
|
171
|
+
else
|
|
172
|
+
transform_single_value_to_data(value, attr, options)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Transform a single value to data format
|
|
177
|
+
def transform_single_value_to_data(value, _attr, options = {})
|
|
178
|
+
case value
|
|
179
|
+
when Lutaml::Model::Serializable
|
|
180
|
+
# Recursively transform back to Coradoc element
|
|
181
|
+
self.class.model_to_data(context, value, :asciidoc, options)
|
|
182
|
+
when Lutaml::Model::Type::Value
|
|
183
|
+
value.value
|
|
184
|
+
else
|
|
185
|
+
value
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Apply value map transformation if present
|
|
190
|
+
def apply_value_map(value, value_map, _attr)
|
|
191
|
+
return value unless value_map
|
|
192
|
+
|
|
193
|
+
case value_map[:type]
|
|
194
|
+
when :symbolize_keys
|
|
195
|
+
value.transform_keys(&:to_sym) if value.is_a?(Hash)
|
|
196
|
+
when :stringify_keys
|
|
197
|
+
value.transform_keys(&:to_s) if value.is_a?(Hash)
|
|
198
|
+
else
|
|
199
|
+
value
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# Get mappings for asciidoc format
|
|
204
|
+
def mappings
|
|
205
|
+
@mappings ||= context.mappings_for(:asciidoc)&.mappings || []
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
module Serialization
|
|
7
|
+
module Errors
|
|
8
|
+
# Base class for all AsciiDoc serialization errors
|
|
9
|
+
# Inherits from Coradoc::Error for consistent error handling
|
|
10
|
+
class AsciidocError < Coradoc::Error; end
|
|
11
|
+
|
|
12
|
+
# Raised when parsing invalid AsciiDoc content
|
|
13
|
+
class ParseError < AsciidocError
|
|
14
|
+
attr_reader :input, :line_number
|
|
15
|
+
|
|
16
|
+
def initialize(message, input: nil, line_number: nil)
|
|
17
|
+
@input = input
|
|
18
|
+
@line_number = line_number
|
|
19
|
+
super(message)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Raised when attribute mapping fails
|
|
24
|
+
class MappingError < AsciidocError
|
|
25
|
+
attr_reader :field_name, :value
|
|
26
|
+
|
|
27
|
+
def initialize(message, field_name: nil, value: nil)
|
|
28
|
+
@field_name = field_name
|
|
29
|
+
@value = value
|
|
30
|
+
super(message)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Raised when required fields are missing
|
|
35
|
+
class ValidationError < AsciidocError
|
|
36
|
+
attr_reader :field_name
|
|
37
|
+
|
|
38
|
+
def initialize(message, field_name: nil)
|
|
39
|
+
@field_name = field_name
|
|
40
|
+
super(message)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Raised when trying to serialize invalid model state
|
|
45
|
+
class SerializationError < AsciidocError
|
|
46
|
+
attr_reader :object
|
|
47
|
+
|
|
48
|
+
def initialize(message, object: nil)
|
|
49
|
+
@object = object
|
|
50
|
+
super(message)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module AsciiDoc
|
|
5
|
+
module Model
|
|
6
|
+
# Serialization support for AsciiDoc models.
|
|
7
|
+
#
|
|
8
|
+
# This module registers the `asciidoc` format with Lutaml::Model,
|
|
9
|
+
# enabling the `asciidoc do ... end` DSL in model classes.
|
|
10
|
+
#
|
|
11
|
+
# IMPORTANT: This module must be loaded BEFORE any model class
|
|
12
|
+
# that uses the `asciidoc` DSL. It is loaded eagerly by model.rb
|
|
13
|
+
# to ensure the format is registered early.
|
|
14
|
+
#
|
|
15
|
+
module Serialization
|
|
16
|
+
# Load all serialization components eagerly (they're small and interdependent)
|
|
17
|
+
require_relative 'serialization/errors'
|
|
18
|
+
require_relative 'serialization/asciidoc_adapter'
|
|
19
|
+
require_relative 'serialization/asciidoc_mapping_rule'
|
|
20
|
+
require_relative 'serialization/asciidoc_mapping'
|
|
21
|
+
require_relative 'serialization/asciidoc_transform'
|
|
22
|
+
|
|
23
|
+
# Register the asciidoc format with Lutaml::Model
|
|
24
|
+
# This enables the `asciidoc do ... end` DSL in model classes
|
|
25
|
+
def self.register_format!
|
|
26
|
+
Lutaml::Model::FormatRegistry.register(
|
|
27
|
+
:asciidoc,
|
|
28
|
+
mapping_class: AsciidocMapping,
|
|
29
|
+
adapter_class: AsciidocAdapter,
|
|
30
|
+
transformer: AsciidocTransform
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Register format when this module is loaded
|
|
35
|
+
register_format!
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|