coradoc 1.1.8 → 2.0.12
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/.rspec +1 -1
- data/Rakefile +3 -12
- data/exe/coradoc +21 -2
- data/lib/coradoc/cli.rb +185 -91
- data/lib/coradoc/configurable.rb +527 -0
- data/lib/coradoc/coradoc.rb +463 -0
- data/lib/coradoc/core_model/annotation_block.rb +57 -0
- data/lib/coradoc/core_model/base.rb +172 -0
- data/lib/coradoc/core_model/bibliography.rb +41 -0
- data/lib/coradoc/core_model/bibliography_entry.rb +48 -0
- data/lib/coradoc/core_model/block.rb +63 -0
- data/lib/coradoc/core_model/children_content.rb +53 -0
- data/lib/coradoc/core_model/comment_block.rb +10 -0
- data/lib/coradoc/core_model/definition_item.rb +46 -0
- data/lib/coradoc/core_model/definition_list.rb +28 -0
- data/lib/coradoc/core_model/element_attribute.rb +26 -0
- data/lib/coradoc/core_model/example_block.rb +10 -0
- data/lib/coradoc/core_model/footnote.rb +92 -0
- data/lib/coradoc/core_model/horizontal_rule_block.rb +10 -0
- data/lib/coradoc/core_model/id_generator.rb +16 -0
- data/lib/coradoc/core_model/image.rb +66 -0
- data/lib/coradoc/core_model/inline_element.rb +140 -0
- data/lib/coradoc/core_model/list_block.rb +135 -0
- data/lib/coradoc/core_model/list_item.rb +142 -0
- data/lib/coradoc/core_model/listing_block.rb +13 -0
- data/lib/coradoc/core_model/literal_block.rb +10 -0
- data/lib/coradoc/core_model/metadata.rb +79 -0
- data/lib/coradoc/core_model/open_block.rb +10 -0
- data/lib/coradoc/core_model/paragraph_block.rb +10 -0
- data/lib/coradoc/core_model/pass_block.rb +10 -0
- data/lib/coradoc/core_model/quote_block.rb +12 -0
- data/lib/coradoc/core_model/reviewer_block.rb +10 -0
- data/lib/coradoc/core_model/sidebar_block.rb +10 -0
- data/lib/coradoc/core_model/source_block.rb +10 -0
- data/lib/coradoc/core_model/structural_element.rb +94 -0
- data/lib/coradoc/core_model/table.rb +148 -0
- data/lib/coradoc/core_model/term.rb +53 -0
- data/lib/coradoc/core_model/text_content.rb +22 -0
- data/lib/coradoc/core_model/toc.rb +105 -0
- data/lib/coradoc/core_model/toc_generator.rb +151 -0
- data/lib/coradoc/core_model/verse_block.rb +12 -0
- data/lib/coradoc/core_model.rb +77 -0
- data/lib/coradoc/document_builder.rb +184 -0
- data/lib/coradoc/document_manipulator.rb +203 -0
- data/lib/coradoc/errors.rb +312 -0
- data/lib/coradoc/format_module.rb +49 -0
- data/lib/coradoc/hooks.rb +176 -0
- data/lib/coradoc/input.rb +17 -7
- data/lib/coradoc/logger.rb +54 -0
- data/lib/coradoc/output.rb +17 -6
- data/lib/coradoc/performance_regression.rb +109 -0
- data/lib/coradoc/processor_registry.rb +50 -0
- data/lib/coradoc/query.rb +455 -0
- data/lib/coradoc/registry.rb +156 -0
- data/lib/coradoc/serializer/registry.rb +150 -0
- data/lib/coradoc/transform.rb +11 -0
- data/lib/coradoc/validation.rb +646 -0
- data/lib/coradoc/version.rb +1 -1
- data/lib/coradoc/visitor.rb +283 -0
- data/lib/coradoc.rb +40 -19
- metadata +67 -277
- data/.editorconfig +0 -15
- data/.envrc +0 -1
- data/.irbrc +0 -1
- data/.pryrc.sample +0 -1
- data/.rubocop.yml +0 -14
- data/.rubocop_todo.yml +0 -179
- data/CHANGELOG.md +0 -9
- data/CODE_OF_CONDUCT.md +0 -84
- data/Dockerfile +0 -19
- data/Gemfile +0 -16
- data/LICENSE.txt +0 -21
- data/Makefile +0 -35
- data/README.Docker.adoc +0 -57
- data/README.adoc +0 -119
- data/coradoc.gemspec +0 -40
- data/docker-compose.yml +0 -14
- data/exe/reverse_adoc +0 -81
- data/exe/w2a +0 -60
- data/flake.lock +0 -114
- data/flake.nix +0 -135
- data/lib/coradoc/converter.rb +0 -144
- data/lib/coradoc/document.rb +0 -77
- data/lib/coradoc/element/admonition.rb +0 -18
- data/lib/coradoc/element/attribute.rb +0 -36
- data/lib/coradoc/element/attribute_list.rb +0 -138
- data/lib/coradoc/element/audio.rb +0 -33
- data/lib/coradoc/element/author.rb +0 -24
- data/lib/coradoc/element/base.rb +0 -92
- data/lib/coradoc/element/bibliography.rb +0 -24
- data/lib/coradoc/element/bibliography_entry.rb +0 -24
- data/lib/coradoc/element/block/core.rb +0 -76
- data/lib/coradoc/element/block/example.rb +0 -23
- data/lib/coradoc/element/block/listing.rb +0 -21
- data/lib/coradoc/element/block/literal.rb +0 -21
- data/lib/coradoc/element/block/open.rb +0 -22
- data/lib/coradoc/element/block/pass.rb +0 -21
- data/lib/coradoc/element/block/quote.rb +0 -19
- data/lib/coradoc/element/block/reviewer_comment.rb +0 -19
- data/lib/coradoc/element/block/side.rb +0 -19
- data/lib/coradoc/element/block/sourcecode.rb +0 -21
- data/lib/coradoc/element/block.rb +0 -17
- data/lib/coradoc/element/break.rb +0 -11
- data/lib/coradoc/element/comment_block.rb +0 -22
- data/lib/coradoc/element/comment_line.rb +0 -18
- data/lib/coradoc/element/document_attributes.rb +0 -33
- data/lib/coradoc/element/header.rb +0 -22
- data/lib/coradoc/element/image/block_image.rb +0 -32
- data/lib/coradoc/element/image/core.rb +0 -58
- data/lib/coradoc/element/image/inline_image.rb +0 -12
- data/lib/coradoc/element/image.rb +0 -10
- data/lib/coradoc/element/include.rb +0 -18
- data/lib/coradoc/element/inline/anchor.rb +0 -19
- data/lib/coradoc/element/inline/attribute_reference.rb +0 -19
- data/lib/coradoc/element/inline/bold.rb +0 -25
- data/lib/coradoc/element/inline/cross_reference.rb +0 -46
- data/lib/coradoc/element/inline/footnote.rb +0 -24
- data/lib/coradoc/element/inline/hard_line_break.rb +0 -11
- data/lib/coradoc/element/inline/highlight.rb +0 -25
- data/lib/coradoc/element/inline/italic.rb +0 -25
- data/lib/coradoc/element/inline/link.rb +0 -42
- data/lib/coradoc/element/inline/monospace.rb +0 -25
- data/lib/coradoc/element/inline/quotation.rb +0 -20
- data/lib/coradoc/element/inline/small.rb +0 -19
- data/lib/coradoc/element/inline/span.rb +0 -37
- data/lib/coradoc/element/inline/subscript.rb +0 -20
- data/lib/coradoc/element/inline/superscript.rb +0 -20
- data/lib/coradoc/element/inline/underline.rb +0 -19
- data/lib/coradoc/element/inline.rb +0 -23
- data/lib/coradoc/element/list/core.rb +0 -51
- data/lib/coradoc/element/list/definition.rb +0 -29
- data/lib/coradoc/element/list/ordered.rb +0 -17
- data/lib/coradoc/element/list/unordered.rb +0 -17
- data/lib/coradoc/element/list.rb +0 -13
- data/lib/coradoc/element/list_item.rb +0 -98
- data/lib/coradoc/element/list_item_definition.rb +0 -32
- data/lib/coradoc/element/paragraph.rb +0 -37
- data/lib/coradoc/element/revision.rb +0 -27
- data/lib/coradoc/element/section.rb +0 -62
- data/lib/coradoc/element/table.rb +0 -91
- data/lib/coradoc/element/tag.rb +0 -19
- data/lib/coradoc/element/term.rb +0 -22
- data/lib/coradoc/element/text_element.rb +0 -92
- data/lib/coradoc/element/title.rb +0 -62
- data/lib/coradoc/element/video.rb +0 -50
- data/lib/coradoc/generator.rb +0 -19
- data/lib/coradoc/input/adoc.rb +0 -30
- data/lib/coradoc/input/docx.rb +0 -64
- data/lib/coradoc/input/html/LICENSE.txt +0 -25
- data/lib/coradoc/input/html/README.adoc +0 -308
- data/lib/coradoc/input/html/cleaner.rb +0 -142
- data/lib/coradoc/input/html/config.rb +0 -77
- data/lib/coradoc/input/html/converters/a.rb +0 -52
- data/lib/coradoc/input/html/converters/aside.rb +0 -16
- data/lib/coradoc/input/html/converters/audio.rb +0 -29
- data/lib/coradoc/input/html/converters/base.rb +0 -108
- data/lib/coradoc/input/html/converters/blockquote.rb +0 -22
- data/lib/coradoc/input/html/converters/br.rb +0 -15
- data/lib/coradoc/input/html/converters/bypass.rb +0 -81
- data/lib/coradoc/input/html/converters/code.rb +0 -23
- data/lib/coradoc/input/html/converters/div.rb +0 -19
- data/lib/coradoc/input/html/converters/dl.rb +0 -62
- data/lib/coradoc/input/html/converters/drop.rb +0 -26
- data/lib/coradoc/input/html/converters/em.rb +0 -21
- data/lib/coradoc/input/html/converters/figure.rb +0 -25
- data/lib/coradoc/input/html/converters/h.rb +0 -42
- data/lib/coradoc/input/html/converters/head.rb +0 -23
- data/lib/coradoc/input/html/converters/hr.rb +0 -15
- data/lib/coradoc/input/html/converters/ignore.rb +0 -20
- data/lib/coradoc/input/html/converters/img.rb +0 -110
- data/lib/coradoc/input/html/converters/li.rb +0 -17
- data/lib/coradoc/input/html/converters/mark.rb +0 -19
- data/lib/coradoc/input/html/converters/markup.rb +0 -31
- data/lib/coradoc/input/html/converters/math.rb +0 -38
- data/lib/coradoc/input/html/converters/ol.rb +0 -65
- data/lib/coradoc/input/html/converters/p.rb +0 -23
- data/lib/coradoc/input/html/converters/pass_through.rb +0 -17
- data/lib/coradoc/input/html/converters/pre.rb +0 -55
- data/lib/coradoc/input/html/converters/q.rb +0 -16
- data/lib/coradoc/input/html/converters/strong.rb +0 -20
- data/lib/coradoc/input/html/converters/sub.rb +0 -22
- data/lib/coradoc/input/html/converters/sup.rb +0 -22
- data/lib/coradoc/input/html/converters/table.rb +0 -319
- data/lib/coradoc/input/html/converters/td.rb +0 -81
- data/lib/coradoc/input/html/converters/text.rb +0 -32
- data/lib/coradoc/input/html/converters/th.rb +0 -18
- data/lib/coradoc/input/html/converters/tr.rb +0 -22
- data/lib/coradoc/input/html/converters/video.rb +0 -29
- data/lib/coradoc/input/html/converters.rb +0 -59
- data/lib/coradoc/input/html/errors.rb +0 -14
- data/lib/coradoc/input/html/html_converter.rb +0 -168
- data/lib/coradoc/input/html/plugin.rb +0 -131
- data/lib/coradoc/input/html/plugins/plateau.rb +0 -213
- data/lib/coradoc/input/html/postprocessor.rb +0 -220
- data/lib/coradoc/input/html.rb +0 -61
- data/lib/coradoc/legacy_parser.rb +0 -200
- data/lib/coradoc/oscal.rb +0 -99
- data/lib/coradoc/output/adoc.rb +0 -19
- data/lib/coradoc/output/coradoc_tree_debug.rb +0 -21
- data/lib/coradoc/parser/asciidoc/admonition.rb +0 -24
- data/lib/coradoc/parser/asciidoc/attribute_list.rb +0 -89
- data/lib/coradoc/parser/asciidoc/base.rb +0 -87
- data/lib/coradoc/parser/asciidoc/bibliography.rb +0 -29
- data/lib/coradoc/parser/asciidoc/block.rb +0 -94
- data/lib/coradoc/parser/asciidoc/citation.rb +0 -30
- data/lib/coradoc/parser/asciidoc/content.rb +0 -64
- data/lib/coradoc/parser/asciidoc/document_attributes.rb +0 -25
- data/lib/coradoc/parser/asciidoc/header.rb +0 -29
- data/lib/coradoc/parser/asciidoc/inline.rb +0 -195
- data/lib/coradoc/parser/asciidoc/list.rb +0 -115
- data/lib/coradoc/parser/asciidoc/paragraph.rb +0 -54
- data/lib/coradoc/parser/asciidoc/section.rb +0 -61
- data/lib/coradoc/parser/asciidoc/table.rb +0 -32
- data/lib/coradoc/parser/asciidoc/term.rb +0 -41
- data/lib/coradoc/parser/asciidoc/text.rb +0 -158
- data/lib/coradoc/parser/base.rb +0 -40
- data/lib/coradoc/parser.rb +0 -11
- data/lib/coradoc/reverse_adoc.rb +0 -18
- data/lib/coradoc/transformer.rb +0 -476
- data/lib/coradoc/util.rb +0 -12
- data/lib/reverse_adoc.rb +0 -20
- data/utils/inspect_asciidoc.rb +0 -29
- data/utils/parser_analyzer.rb +0 -66
- data/utils/round_trip.rb +0 -53
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Bibliography section in a document.
|
|
6
|
+
#
|
|
7
|
+
# Bibliography sections contain lists of references cited in the document.
|
|
8
|
+
#
|
|
9
|
+
# @!attribute [r] id
|
|
10
|
+
# @return [String, nil] Optional identifier for the bibliography
|
|
11
|
+
#
|
|
12
|
+
# @!attribute [r] title
|
|
13
|
+
# @return [String, nil] Bibliography section title
|
|
14
|
+
#
|
|
15
|
+
# @!attribute [r] level
|
|
16
|
+
# @return [Integer, nil] Section level
|
|
17
|
+
#
|
|
18
|
+
# @!attribute [r] entries
|
|
19
|
+
# @return [Array<Coradoc::CoreModel::BibliographyEntry>] Bibliography entries
|
|
20
|
+
#
|
|
21
|
+
# @example Create a bibliography section
|
|
22
|
+
# bib = Coradoc::CoreModel::Bibliography.new(
|
|
23
|
+
# id: "norm-refs",
|
|
24
|
+
# title: "Normative references",
|
|
25
|
+
# entries: [
|
|
26
|
+
# Coradoc::CoreModel::BibliographyEntry.new(
|
|
27
|
+
# anchor_name: "ISO712",
|
|
28
|
+
# document_id: "ISO 712",
|
|
29
|
+
# ref_text: "Cereals and cereal products..."
|
|
30
|
+
# )
|
|
31
|
+
# ]
|
|
32
|
+
# )
|
|
33
|
+
#
|
|
34
|
+
class Bibliography < Base
|
|
35
|
+
attribute :id, :string
|
|
36
|
+
attribute :title, :string
|
|
37
|
+
attribute :level, :integer
|
|
38
|
+
attribute :entries, Coradoc::CoreModel::BibliographyEntry, collection: true
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Individual bibliography entry (reference).
|
|
6
|
+
#
|
|
7
|
+
# Bibliography entries represent single references within a bibliography,
|
|
8
|
+
# with anchor names for citation linking.
|
|
9
|
+
#
|
|
10
|
+
# @!attribute [r] anchor_name
|
|
11
|
+
# @return [String, nil] The anchor name for citing this entry (e.g., "ISO712")
|
|
12
|
+
#
|
|
13
|
+
# @!attribute [r] document_id
|
|
14
|
+
# @return [String, nil] The document identifier (e.g., "ISO 712")
|
|
15
|
+
#
|
|
16
|
+
# @!attribute [r] ref_text
|
|
17
|
+
# @return [String, nil] The reference text/citation description
|
|
18
|
+
#
|
|
19
|
+
# @!attribute [r] url
|
|
20
|
+
# @return [String, nil] Optional URL for the reference
|
|
21
|
+
#
|
|
22
|
+
# @example Create a bibliography entry
|
|
23
|
+
# entry = Coradoc::CoreModel::BibliographyEntry.new(
|
|
24
|
+
# anchor_name: "ISO712",
|
|
25
|
+
# document_id: "ISO 712",
|
|
26
|
+
# ref_text: "Cereals and cereal products. Determination of moisture content."
|
|
27
|
+
# )
|
|
28
|
+
#
|
|
29
|
+
class BibliographyEntry < Base
|
|
30
|
+
attribute :anchor_name, :string
|
|
31
|
+
attribute :document_id, :string
|
|
32
|
+
attribute :ref_text, :string
|
|
33
|
+
attribute :url, :string
|
|
34
|
+
|
|
35
|
+
# Returns a formatted display string combining label and reference text.
|
|
36
|
+
#
|
|
37
|
+
# Uses document_id or anchor_name as the label, falling back to ref_text
|
|
38
|
+
# alone when no label is available.
|
|
39
|
+
#
|
|
40
|
+
# @return [String] formatted citation text
|
|
41
|
+
def display_text
|
|
42
|
+
label = document_id || anchor_name || ''
|
|
43
|
+
ref = ref_text || ''
|
|
44
|
+
label.empty? ? ref : "#{label}: #{ref}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Generic block model
|
|
6
|
+
#
|
|
7
|
+
# Represents all block-level elements in a format-neutral way.
|
|
8
|
+
# Typed subclasses (SourceBlock, QuoteBlock, etc.) express their
|
|
9
|
+
# semantic identity via the class hierarchy — the class IS the type.
|
|
10
|
+
# Generic Block instances use block_semantic_type for typing.
|
|
11
|
+
class Block < Base
|
|
12
|
+
attribute :children, Base, collection: true
|
|
13
|
+
|
|
14
|
+
include ChildrenContent
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
def semantic_type
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def resolve_semantic_type
|
|
23
|
+
self.class.semantic_type || block_semantic_type&.to_sym
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Derived element_type string for backward compatibility.
|
|
27
|
+
# Returns the semantic type as a string, derived from the class
|
|
28
|
+
# or block_semantic_type.
|
|
29
|
+
def element_type
|
|
30
|
+
resolve_semantic_type&.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @!attribute block_semantic_type
|
|
34
|
+
# @return [String, nil] semantic type for generic Block instances.
|
|
35
|
+
# Typed subclasses should not override this — use the class instead.
|
|
36
|
+
attribute :block_semantic_type, :string
|
|
37
|
+
|
|
38
|
+
# @!attribute delimiter_type
|
|
39
|
+
# @return [String, nil] raw delimiter for round-trip fidelity.
|
|
40
|
+
# Format-specific; CoreModel does NOT derive semantics from this.
|
|
41
|
+
attribute :delimiter_type, :string
|
|
42
|
+
|
|
43
|
+
# @!attribute content
|
|
44
|
+
# @return [String, nil] the block's text content (simple string)
|
|
45
|
+
# For mixed content with inline elements, use children instead.
|
|
46
|
+
attribute :content, :string
|
|
47
|
+
|
|
48
|
+
# @!attribute lines
|
|
49
|
+
# @return [Array<String>, nil] individual lines of content
|
|
50
|
+
attribute :lines, :string, collection: true
|
|
51
|
+
|
|
52
|
+
# @!attribute language
|
|
53
|
+
# @return [String, nil] language identifier for source code blocks
|
|
54
|
+
attribute :language, :string
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def comparable_attributes
|
|
59
|
+
super + %i[block_semantic_type content]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Shared helpers for models that carry mixed-content children
|
|
6
|
+
# (TextContent + InlineElement + Block instances) alongside a string
|
|
7
|
+
# content attribute.
|
|
8
|
+
#
|
|
9
|
+
# Included by Block, ListItem, TableCell, and InlineElement.
|
|
10
|
+
# The children attribute is declared as
|
|
11
|
+
# attribute :children, Base, collection: true
|
|
12
|
+
# on each including class. This module overrides the setter to
|
|
13
|
+
# auto-wrap raw strings as TextContent, keeping all callers simple.
|
|
14
|
+
module ChildrenContent
|
|
15
|
+
# Override the children= setter to auto-wrap strings as TextContent.
|
|
16
|
+
# This is defined via define_method so it always overrides the
|
|
17
|
+
# lutaml-generated setter, regardless of include order.
|
|
18
|
+
def self.included(base)
|
|
19
|
+
super
|
|
20
|
+
|
|
21
|
+
base.define_method(:children=) do |value|
|
|
22
|
+
wrapped = Array(value).map do |item|
|
|
23
|
+
next nil if item.nil?
|
|
24
|
+
next item if item.is_a?(CoreModel::Base)
|
|
25
|
+
|
|
26
|
+
CoreModel::TextContent.new(text: item.to_s)
|
|
27
|
+
end.compact
|
|
28
|
+
instance_variable_set(:@children, wrapped)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Get content for rendering, preferring children over content.
|
|
33
|
+
# When children are all TextContent (plain text), use the content
|
|
34
|
+
# attribute instead since it already has proper spacing between lines.
|
|
35
|
+
def renderable_content
|
|
36
|
+
return content if children.nil? || children.none?
|
|
37
|
+
return content if content && children.all?(TextContent)
|
|
38
|
+
|
|
39
|
+
children
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Flatten renderable_content to a single plain-text string.
|
|
43
|
+
def flat_text
|
|
44
|
+
rc = renderable_content
|
|
45
|
+
case rc
|
|
46
|
+
when String then rc
|
|
47
|
+
when Array then rc.map { |c| c.is_a?(TextContent) ? c.text : c.content.to_s }.join
|
|
48
|
+
else rc.to_s
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
class DefinitionItem < Base
|
|
6
|
+
attribute :term, :string
|
|
7
|
+
attribute :definitions, :string, collection: true
|
|
8
|
+
|
|
9
|
+
def initialize(args = {})
|
|
10
|
+
@term_children = args.delete(:term_children) || []
|
|
11
|
+
@definition_children = args.delete(:definition_children) || []
|
|
12
|
+
super(args)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :term_children, :definition_children
|
|
16
|
+
|
|
17
|
+
def term_children=(value)
|
|
18
|
+
@term_children = value || []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def definition_children=(value)
|
|
22
|
+
@definition_children = value || []
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def term_renderable
|
|
26
|
+
return term if term_children.nil? || term_children.none?
|
|
27
|
+
return term if term && term_children.all?(String)
|
|
28
|
+
|
|
29
|
+
term_children
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def definition_renderable
|
|
33
|
+
return definitions if definition_children.nil? || definition_children.none?
|
|
34
|
+
return definitions if definition_children.all?(String)
|
|
35
|
+
|
|
36
|
+
definition_children
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def comparable_attributes
|
|
42
|
+
super + %i[term definitions term_children definition_children]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Represents a definition list
|
|
6
|
+
#
|
|
7
|
+
# DefinitionList contains terms and their definitions.
|
|
8
|
+
#
|
|
9
|
+
# @example Creating a definition list
|
|
10
|
+
# list = CoreModel::DefinitionList.new(
|
|
11
|
+
# items: [
|
|
12
|
+
# DefinitionItem.new(term: "API", definitions: ["Application Programming Interface"]),
|
|
13
|
+
# DefinitionItem.new(term: "REST", definitions: ["Representational State Transfer"])
|
|
14
|
+
# ]
|
|
15
|
+
# )
|
|
16
|
+
class DefinitionList < Base
|
|
17
|
+
# @!attribute items
|
|
18
|
+
# @return [Array<DefinitionItem>] the definition items
|
|
19
|
+
attribute :items, DefinitionItem, collection: true
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def comparable_attributes
|
|
24
|
+
super + %i[items]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Represents a single attribute (key-value pair) on an element
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# attr = ElementAttribute.new(name: "role", value: "note")
|
|
9
|
+
class ElementAttribute < Base
|
|
10
|
+
attribute :name, :string
|
|
11
|
+
attribute :value, :string
|
|
12
|
+
|
|
13
|
+
# Convert to hash representation
|
|
14
|
+
# @return [Hash] Single key-value pair
|
|
15
|
+
def to_h
|
|
16
|
+
{ name => value }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Convert to string representation (e.g., for serialization)
|
|
20
|
+
# @return [String] Attribute in name="value" format
|
|
21
|
+
def to_s
|
|
22
|
+
%("#{name}="#{value}"")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Represents a footnote definition in a document
|
|
6
|
+
#
|
|
7
|
+
# Footnotes are used for auxiliary information, citations, or
|
|
8
|
+
# explanatory notes that appear at the bottom of a page or
|
|
9
|
+
# end of a document.
|
|
10
|
+
#
|
|
11
|
+
# @example Creating a simple footnote
|
|
12
|
+
# footnote = CoreModel::Footnote.new(
|
|
13
|
+
# id: "fn1",
|
|
14
|
+
# content: "This is a footnote explanation."
|
|
15
|
+
# )
|
|
16
|
+
#
|
|
17
|
+
# @example Creating a footnote with backlink
|
|
18
|
+
# footnote = CoreModel::Footnote.new(
|
|
19
|
+
# id: "cite1",
|
|
20
|
+
# content: "Smith, J. (2024). The Reference.",
|
|
21
|
+
# backlink: true
|
|
22
|
+
# )
|
|
23
|
+
class Footnote < Base
|
|
24
|
+
# @!attribute id
|
|
25
|
+
# @return [String, nil] the footnote identifier (e.g., "1", "fn1")
|
|
26
|
+
attribute :id, :string
|
|
27
|
+
|
|
28
|
+
# @!attribute content
|
|
29
|
+
# @return [String, nil] the footnote content
|
|
30
|
+
attribute :content, :string
|
|
31
|
+
|
|
32
|
+
# @!attribute inline_content
|
|
33
|
+
# @return [Array<String>, nil] inline content elements
|
|
34
|
+
attribute :inline_content, :string, collection: true
|
|
35
|
+
|
|
36
|
+
# @!attribute backlink
|
|
37
|
+
# @return [Boolean] whether to include backlink to reference
|
|
38
|
+
attribute :backlink, :boolean, default: -> { true }
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def comparable_attributes
|
|
43
|
+
super + %i[id content backlink]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Represents an inline footnote reference
|
|
48
|
+
#
|
|
49
|
+
# FootnoteReference links to a Footnote definition within document text.
|
|
50
|
+
#
|
|
51
|
+
# @example Creating a footnote reference
|
|
52
|
+
# ref = CoreModel::FootnoteReference.new(id: "fn1")
|
|
53
|
+
# # Renders as: [^fn1] in Markdown, <sup>1</sup> in HTML
|
|
54
|
+
class FootnoteReference < Base
|
|
55
|
+
# @!attribute id
|
|
56
|
+
# @return [String, nil] the footnote identifier being referenced
|
|
57
|
+
attribute :id, :string
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def comparable_attributes
|
|
62
|
+
super + %i[id]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Represents an abbreviation definition in a document
|
|
67
|
+
#
|
|
68
|
+
# Abbreviations define the expansion of shortened terms.
|
|
69
|
+
# They are typically rendered with the full definition on first use.
|
|
70
|
+
#
|
|
71
|
+
# @example Creating an abbreviation
|
|
72
|
+
# abbr = CoreModel::Abbreviation.new(
|
|
73
|
+
# term: "API",
|
|
74
|
+
# definition: "Application Programming Interface"
|
|
75
|
+
# )
|
|
76
|
+
class Abbreviation < Base
|
|
77
|
+
# @!attribute term
|
|
78
|
+
# @return [String, nil] the abbreviated term
|
|
79
|
+
attribute :term, :string
|
|
80
|
+
|
|
81
|
+
# @!attribute definition
|
|
82
|
+
# @return [String, nil] the full definition/expansion
|
|
83
|
+
attribute :definition, :string
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def comparable_attributes
|
|
88
|
+
super + %i[term definition]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
module IdGenerator
|
|
6
|
+
def self.generate_from_title(title)
|
|
7
|
+
return nil if title.nil? || title.to_s.strip.empty?
|
|
8
|
+
|
|
9
|
+
'_' + title.to_s.downcase
|
|
10
|
+
.gsub(/[^a-z0-9\s]/, '')
|
|
11
|
+
.gsub(/\s+/, '_')
|
|
12
|
+
.gsub(/^_+|_+$/, '')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Represents an image in a document
|
|
6
|
+
#
|
|
7
|
+
# Images can be block-level (standalone) or inline. They support
|
|
8
|
+
# various attributes like alt text, dimensions, and linking.
|
|
9
|
+
#
|
|
10
|
+
# @example Creating a block image
|
|
11
|
+
# image = CoreModel::Image.new(
|
|
12
|
+
# src: "images/diagram.png",
|
|
13
|
+
# alt: "System Architecture",
|
|
14
|
+
# caption: "Figure 1: System Overview",
|
|
15
|
+
# width: "800px"
|
|
16
|
+
# )
|
|
17
|
+
#
|
|
18
|
+
# @example Creating an inline image
|
|
19
|
+
# icon = CoreModel::Image.new(
|
|
20
|
+
# src: "icons/warning.png",
|
|
21
|
+
# alt: "Warning",
|
|
22
|
+
# inline: true
|
|
23
|
+
# )
|
|
24
|
+
class Image < Base
|
|
25
|
+
# @!attribute src
|
|
26
|
+
# @return [String, nil] source URL or path to the image
|
|
27
|
+
attribute :src, :string
|
|
28
|
+
|
|
29
|
+
# @!attribute alt
|
|
30
|
+
# @return [String, nil] alternative text for accessibility
|
|
31
|
+
attribute :alt, :string
|
|
32
|
+
|
|
33
|
+
# @!attribute caption
|
|
34
|
+
# @return [String, nil] caption text for the image
|
|
35
|
+
attribute :caption, :string
|
|
36
|
+
|
|
37
|
+
# @!attribute width
|
|
38
|
+
# @return [String, nil] image width (e.g., '100%', '500px')
|
|
39
|
+
attribute :width, :string
|
|
40
|
+
|
|
41
|
+
# @!attribute height
|
|
42
|
+
# @return [String, nil] image height (e.g., '300px', 'auto')
|
|
43
|
+
attribute :height, :string
|
|
44
|
+
|
|
45
|
+
# @!attribute link
|
|
46
|
+
# @return [String, nil] URL to link to when image is clicked
|
|
47
|
+
# @note Not yet wired by any transformer; reserved for future use
|
|
48
|
+
attribute :link, :string
|
|
49
|
+
|
|
50
|
+
# @!attribute inline
|
|
51
|
+
# @return [Boolean] whether this is an inline image
|
|
52
|
+
attribute :inline, :boolean, default: -> { false }
|
|
53
|
+
|
|
54
|
+
# @!attribute float
|
|
55
|
+
# @return [String, nil] float position ('left', 'right')
|
|
56
|
+
# @note Not yet wired by any transformer; reserved for future use
|
|
57
|
+
attribute :float, :string
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def comparable_attributes
|
|
62
|
+
super + %i[src alt caption width height link inline]
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module CoreModel
|
|
5
|
+
# Generic inline formatting element
|
|
6
|
+
#
|
|
7
|
+
# Typed subclasses (BoldElement, ItalicElement, etc.) express their
|
|
8
|
+
# format identity via the class hierarchy — the class IS the format type.
|
|
9
|
+
# Generic InlineElement instances use the format_type attribute for typing.
|
|
10
|
+
class InlineElement < Base
|
|
11
|
+
attribute :children, Base, collection: true
|
|
12
|
+
|
|
13
|
+
include ChildrenContent
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
def format_type
|
|
17
|
+
nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def format_type_class(type)
|
|
21
|
+
FORMAT_TYPE_CLASS_MAP[type] || InlineElement
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def resolve_format_type
|
|
26
|
+
self.class.format_type || format_type
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
FORMAT_TYPES = %w[
|
|
30
|
+
bold italic monospace underline strikethrough
|
|
31
|
+
subscript superscript highlight
|
|
32
|
+
link xref stem footnote
|
|
33
|
+
hard_line_break text span term
|
|
34
|
+
line_break quotation
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
37
|
+
attribute :format_type, :string
|
|
38
|
+
attribute :content, :string
|
|
39
|
+
attribute :nested_elements, InlineElement, collection: true
|
|
40
|
+
attribute :target, :string
|
|
41
|
+
attribute :stem_type, :string
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def comparable_attributes
|
|
46
|
+
%i[format_type content nested_elements stem_type]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Typed InlineElement subclasses
|
|
51
|
+
|
|
52
|
+
class BoldElement < InlineElement
|
|
53
|
+
def self.format_type = 'bold'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class ItalicElement < InlineElement
|
|
57
|
+
def self.format_type = 'italic'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class MonospaceElement < InlineElement
|
|
61
|
+
def self.format_type = 'monospace'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class UnderlineElement < InlineElement
|
|
65
|
+
def self.format_type = 'underline'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class StrikethroughElement < InlineElement
|
|
69
|
+
def self.format_type = 'strikethrough'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
class SubscriptElement < InlineElement
|
|
73
|
+
def self.format_type = 'subscript'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class SuperscriptElement < InlineElement
|
|
77
|
+
def self.format_type = 'superscript'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class HighlightElement < InlineElement
|
|
81
|
+
def self.format_type = 'highlight'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
class LinkElement < InlineElement
|
|
85
|
+
def self.format_type = 'link'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class CrossReferenceElement < InlineElement
|
|
89
|
+
def self.format_type = 'xref'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
class StemElement < InlineElement
|
|
93
|
+
def self.format_type = 'stem'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
class FootnoteElement < InlineElement
|
|
97
|
+
def self.format_type = 'footnote'
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class HardLineBreakElement < InlineElement
|
|
101
|
+
def self.format_type = 'hard_line_break'
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class TextElement < InlineElement
|
|
105
|
+
def self.format_type = 'text'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class SpanElement < InlineElement
|
|
109
|
+
def self.format_type = 'span'
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
class TermElement < InlineElement
|
|
113
|
+
def self.format_type = 'term'
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class LineBreakElement < InlineElement
|
|
117
|
+
def self.format_type = 'line_break'
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
FORMAT_TYPE_CLASS_MAP = {
|
|
121
|
+
'bold' => BoldElement,
|
|
122
|
+
'italic' => ItalicElement,
|
|
123
|
+
'monospace' => MonospaceElement,
|
|
124
|
+
'underline' => UnderlineElement,
|
|
125
|
+
'strikethrough' => StrikethroughElement,
|
|
126
|
+
'subscript' => SubscriptElement,
|
|
127
|
+
'superscript' => SuperscriptElement,
|
|
128
|
+
'highlight' => HighlightElement,
|
|
129
|
+
'link' => LinkElement,
|
|
130
|
+
'xref' => CrossReferenceElement,
|
|
131
|
+
'stem' => StemElement,
|
|
132
|
+
'footnote' => FootnoteElement,
|
|
133
|
+
'hard_line_break' => HardLineBreakElement,
|
|
134
|
+
'text' => TextElement,
|
|
135
|
+
'span' => SpanElement,
|
|
136
|
+
'term' => TermElement,
|
|
137
|
+
'line_break' => LineBreakElement
|
|
138
|
+
}.freeze
|
|
139
|
+
end
|
|
140
|
+
end
|