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.
Files changed (217) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/lib/coradoc/asciidoc/model/admonition.rb +37 -0
  4. data/lib/coradoc/asciidoc/model/anchorable.rb +64 -0
  5. data/lib/coradoc/asciidoc/model/attached.rb +26 -0
  6. data/lib/coradoc/asciidoc/model/attribute.rb +22 -0
  7. data/lib/coradoc/asciidoc/model/attribute_list/matchers.rb +45 -0
  8. data/lib/coradoc/asciidoc/model/attribute_list.rb +230 -0
  9. data/lib/coradoc/asciidoc/model/attribute_list_attribute.rb +11 -0
  10. data/lib/coradoc/asciidoc/model/audio.rb +44 -0
  11. data/lib/coradoc/asciidoc/model/author.rb +36 -0
  12. data/lib/coradoc/asciidoc/model/base.rb +141 -0
  13. data/lib/coradoc/asciidoc/model/bibliography.rb +37 -0
  14. data/lib/coradoc/asciidoc/model/bibliography_entry.rb +38 -0
  15. data/lib/coradoc/asciidoc/model/block/core.rb +139 -0
  16. data/lib/coradoc/asciidoc/model/block/example.rb +14 -0
  17. data/lib/coradoc/asciidoc/model/block/listing.rb +14 -0
  18. data/lib/coradoc/asciidoc/model/block/literal.rb +14 -0
  19. data/lib/coradoc/asciidoc/model/block/open.rb +14 -0
  20. data/lib/coradoc/asciidoc/model/block/pass.rb +14 -0
  21. data/lib/coradoc/asciidoc/model/block/quote.rb +14 -0
  22. data/lib/coradoc/asciidoc/model/block/reviewer_comment.rb +14 -0
  23. data/lib/coradoc/asciidoc/model/block/side.rb +14 -0
  24. data/lib/coradoc/asciidoc/model/block/source_code.rb +14 -0
  25. data/lib/coradoc/asciidoc/model/block.rb +21 -0
  26. data/lib/coradoc/asciidoc/model/break.rb +33 -0
  27. data/lib/coradoc/asciidoc/model/comment_block.rb +33 -0
  28. data/lib/coradoc/asciidoc/model/comment_line.rb +30 -0
  29. data/lib/coradoc/asciidoc/model/content_list.rb +334 -0
  30. data/lib/coradoc/asciidoc/model/document.rb +197 -0
  31. data/lib/coradoc/asciidoc/model/document_attributes.rb +43 -0
  32. data/lib/coradoc/asciidoc/model/glossaries.rb +11 -0
  33. data/lib/coradoc/asciidoc/model/header.rb +57 -0
  34. data/lib/coradoc/asciidoc/model/highlight.rb +11 -0
  35. data/lib/coradoc/asciidoc/model/image/block_image/attribute_list.rb +23 -0
  36. data/lib/coradoc/asciidoc/model/image/block_image.rb +25 -0
  37. data/lib/coradoc/asciidoc/model/image/core/attribute_list.rb +43 -0
  38. data/lib/coradoc/asciidoc/model/image/core.rb +72 -0
  39. data/lib/coradoc/asciidoc/model/image/inline_image.rb +17 -0
  40. data/lib/coradoc/asciidoc/model/image.rb +14 -0
  41. data/lib/coradoc/asciidoc/model/include.rb +66 -0
  42. data/lib/coradoc/asciidoc/model/inline/anchor.rb +41 -0
  43. data/lib/coradoc/asciidoc/model/inline/attribute_reference.rb +25 -0
  44. data/lib/coradoc/asciidoc/model/inline/base.rb +15 -0
  45. data/lib/coradoc/asciidoc/model/inline/bold.rb +38 -0
  46. data/lib/coradoc/asciidoc/model/inline/cross_reference.rb +29 -0
  47. data/lib/coradoc/asciidoc/model/inline/cross_reference_arg.rb +15 -0
  48. data/lib/coradoc/asciidoc/model/inline/footnote.rb +34 -0
  49. data/lib/coradoc/asciidoc/model/inline/hard_line_break.rb +24 -0
  50. data/lib/coradoc/asciidoc/model/inline/highlight.rb +36 -0
  51. data/lib/coradoc/asciidoc/model/inline/italic.rb +38 -0
  52. data/lib/coradoc/asciidoc/model/inline/link.rb +46 -0
  53. data/lib/coradoc/asciidoc/model/inline/monospace.rb +39 -0
  54. data/lib/coradoc/asciidoc/model/inline/quotation.rb +25 -0
  55. data/lib/coradoc/asciidoc/model/inline/small.rb +25 -0
  56. data/lib/coradoc/asciidoc/model/inline/span.rb +38 -0
  57. data/lib/coradoc/asciidoc/model/inline/stem.rb +24 -0
  58. data/lib/coradoc/asciidoc/model/inline/strikethrough.rb +39 -0
  59. data/lib/coradoc/asciidoc/model/inline/subscript.rb +33 -0
  60. data/lib/coradoc/asciidoc/model/inline/superscript.rb +33 -0
  61. data/lib/coradoc/asciidoc/model/inline/underline.rb +25 -0
  62. data/lib/coradoc/asciidoc/model/inline.rb +31 -0
  63. data/lib/coradoc/asciidoc/model/line_break.rb +11 -0
  64. data/lib/coradoc/asciidoc/model/list/core.rb +61 -0
  65. data/lib/coradoc/asciidoc/model/list/definition.rb +27 -0
  66. data/lib/coradoc/asciidoc/model/list/definition_item.rb +43 -0
  67. data/lib/coradoc/asciidoc/model/list/item.rb +72 -0
  68. data/lib/coradoc/asciidoc/model/list/nestable.rb +14 -0
  69. data/lib/coradoc/asciidoc/model/list/ordered.rb +34 -0
  70. data/lib/coradoc/asciidoc/model/list/unordered.rb +34 -0
  71. data/lib/coradoc/asciidoc/model/list.rb +29 -0
  72. data/lib/coradoc/asciidoc/model/named_attribute.rb +12 -0
  73. data/lib/coradoc/asciidoc/model/paragraph.rb +59 -0
  74. data/lib/coradoc/asciidoc/model/rejected_positional_attribute.rb +12 -0
  75. data/lib/coradoc/asciidoc/model/resolvable.rb +71 -0
  76. data/lib/coradoc/asciidoc/model/resolver.rb +430 -0
  77. data/lib/coradoc/asciidoc/model/reviewer_note.rb +54 -0
  78. data/lib/coradoc/asciidoc/model/revision.rb +47 -0
  79. data/lib/coradoc/asciidoc/model/section.rb +109 -0
  80. data/lib/coradoc/asciidoc/model/serialization/asciidoc_adapter.rb +28 -0
  81. data/lib/coradoc/asciidoc/model/serialization/asciidoc_mapping.rb +42 -0
  82. data/lib/coradoc/asciidoc/model/serialization/asciidoc_mapping_rule.rb +41 -0
  83. data/lib/coradoc/asciidoc/model/serialization/asciidoc_transform.rb +211 -0
  84. data/lib/coradoc/asciidoc/model/serialization/errors.rb +57 -0
  85. data/lib/coradoc/asciidoc/model/serialization.rb +39 -0
  86. data/lib/coradoc/asciidoc/model/spacing.rb +282 -0
  87. data/lib/coradoc/asciidoc/model/table.rb +44 -0
  88. data/lib/coradoc/asciidoc/model/table_cell.rb +122 -0
  89. data/lib/coradoc/asciidoc/model/table_row.rb +26 -0
  90. data/lib/coradoc/asciidoc/model/tag.rb +36 -0
  91. data/lib/coradoc/asciidoc/model/term.rb +48 -0
  92. data/lib/coradoc/asciidoc/model/text_element.rb +66 -0
  93. data/lib/coradoc/asciidoc/model/title.rb +85 -0
  94. data/lib/coradoc/asciidoc/model/video/attribute_list.rb +43 -0
  95. data/lib/coradoc/asciidoc/model/video.rb +49 -0
  96. data/lib/coradoc/asciidoc/model.rb +75 -0
  97. data/lib/coradoc/asciidoc/parse_error.rb +161 -0
  98. data/lib/coradoc/asciidoc/parser/admonition.rb +26 -0
  99. data/lib/coradoc/asciidoc/parser/attribute_list.rb +110 -0
  100. data/lib/coradoc/asciidoc/parser/base.rb +159 -0
  101. data/lib/coradoc/asciidoc/parser/bibliography.rb +31 -0
  102. data/lib/coradoc/asciidoc/parser/block.rb +186 -0
  103. data/lib/coradoc/asciidoc/parser/block_assembler.rb +183 -0
  104. data/lib/coradoc/asciidoc/parser/cache.rb +155 -0
  105. data/lib/coradoc/asciidoc/parser/citation.rb +32 -0
  106. data/lib/coradoc/asciidoc/parser/content.rb +76 -0
  107. data/lib/coradoc/asciidoc/parser/document_attributes.rb +27 -0
  108. data/lib/coradoc/asciidoc/parser/fix_files.rb +76 -0
  109. data/lib/coradoc/asciidoc/parser/header.rb +31 -0
  110. data/lib/coradoc/asciidoc/parser/inline.rb +199 -0
  111. data/lib/coradoc/asciidoc/parser/list.rb +130 -0
  112. data/lib/coradoc/asciidoc/parser/metadata_detector.rb +164 -0
  113. data/lib/coradoc/asciidoc/parser/paragraph.rb +64 -0
  114. data/lib/coradoc/asciidoc/parser/section.rb +62 -0
  115. data/lib/coradoc/asciidoc/parser/stem.rb +19 -0
  116. data/lib/coradoc/asciidoc/parser/table.rb +166 -0
  117. data/lib/coradoc/asciidoc/parser/term.rb +70 -0
  118. data/lib/coradoc/asciidoc/parser/text.rb +156 -0
  119. data/lib/coradoc/asciidoc/parser.rb +10 -0
  120. data/lib/coradoc/asciidoc/serializer/adoc_serializer.rb +86 -0
  121. data/lib/coradoc/asciidoc/serializer/element_registry.rb +95 -0
  122. data/lib/coradoc/asciidoc/serializer/fallback_serializer.rb +21 -0
  123. data/lib/coradoc/asciidoc/serializer/formatter.rb +144 -0
  124. data/lib/coradoc/asciidoc/serializer/registrations.rb +108 -0
  125. data/lib/coradoc/asciidoc/serializer/serialization_context.rb +238 -0
  126. data/lib/coradoc/asciidoc/serializer/serializers/admonition.rb +19 -0
  127. data/lib/coradoc/asciidoc/serializer/serializers/attribute.rb +23 -0
  128. data/lib/coradoc/asciidoc/serializer/serializers/attribute_list.rb +40 -0
  129. data/lib/coradoc/asciidoc/serializer/serializers/attribute_list_attribute.rb +18 -0
  130. data/lib/coradoc/asciidoc/serializer/serializers/audio.rb +33 -0
  131. data/lib/coradoc/asciidoc/serializer/serializers/author.rb +20 -0
  132. data/lib/coradoc/asciidoc/serializer/serializers/base.rb +152 -0
  133. data/lib/coradoc/asciidoc/serializer/serializers/bibliography.rb +35 -0
  134. data/lib/coradoc/asciidoc/serializer/serializers/bibliography_entry.rb +24 -0
  135. data/lib/coradoc/asciidoc/serializer/serializers/block/core.rb +70 -0
  136. data/lib/coradoc/asciidoc/serializer/serializers/block/example.rb +17 -0
  137. data/lib/coradoc/asciidoc/serializer/serializers/block/listing.rb +22 -0
  138. data/lib/coradoc/asciidoc/serializer/serializers/block/literal.rb +17 -0
  139. data/lib/coradoc/asciidoc/serializer/serializers/block/open.rb +22 -0
  140. data/lib/coradoc/asciidoc/serializer/serializers/block/pass.rb +17 -0
  141. data/lib/coradoc/asciidoc/serializer/serializers/block/quote.rb +17 -0
  142. data/lib/coradoc/asciidoc/serializer/serializers/block/reviewer_comment.rb +17 -0
  143. data/lib/coradoc/asciidoc/serializer/serializers/block/side.rb +22 -0
  144. data/lib/coradoc/asciidoc/serializer/serializers/block/source_code.rb +22 -0
  145. data/lib/coradoc/asciidoc/serializer/serializers/block.rb +23 -0
  146. data/lib/coradoc/asciidoc/serializer/serializers/break.rb +18 -0
  147. data/lib/coradoc/asciidoc/serializer/serializers/comment_block.rb +22 -0
  148. data/lib/coradoc/asciidoc/serializer/serializers/comment_line.rb +22 -0
  149. data/lib/coradoc/asciidoc/serializer/serializers/document.rb +65 -0
  150. data/lib/coradoc/asciidoc/serializer/serializers/document_attributes.rb +21 -0
  151. data/lib/coradoc/asciidoc/serializer/serializers/header.rb +24 -0
  152. data/lib/coradoc/asciidoc/serializer/serializers/highlight.rb +23 -0
  153. data/lib/coradoc/asciidoc/serializer/serializers/image/core.rb +30 -0
  154. data/lib/coradoc/asciidoc/serializer/serializers/image.rb +14 -0
  155. data/lib/coradoc/asciidoc/serializer/serializers/include.rb +19 -0
  156. data/lib/coradoc/asciidoc/serializer/serializers/inline/anchor.rb +20 -0
  157. data/lib/coradoc/asciidoc/serializer/serializers/inline/attribute_reference.rb +20 -0
  158. data/lib/coradoc/asciidoc/serializer/serializers/inline/bold.rb +26 -0
  159. data/lib/coradoc/asciidoc/serializer/serializers/inline/cross_reference.rb +30 -0
  160. data/lib/coradoc/asciidoc/serializer/serializers/inline/cross_reference_arg.rb +20 -0
  161. data/lib/coradoc/asciidoc/serializer/serializers/inline/footnote.rb +24 -0
  162. data/lib/coradoc/asciidoc/serializer/serializers/inline/hard_line_break.rb +20 -0
  163. data/lib/coradoc/asciidoc/serializer/serializers/inline/highlight.rb +26 -0
  164. data/lib/coradoc/asciidoc/serializer/serializers/inline/italic.rb +26 -0
  165. data/lib/coradoc/asciidoc/serializer/serializers/inline/link.rb +38 -0
  166. data/lib/coradoc/asciidoc/serializer/serializers/inline/monospace.rb +26 -0
  167. data/lib/coradoc/asciidoc/serializer/serializers/inline/quotation.rb +21 -0
  168. data/lib/coradoc/asciidoc/serializer/serializers/inline/small.rb +20 -0
  169. data/lib/coradoc/asciidoc/serializer/serializers/inline/span.rb +35 -0
  170. data/lib/coradoc/asciidoc/serializer/serializers/inline/stem.rb +23 -0
  171. data/lib/coradoc/asciidoc/serializer/serializers/inline/strikethrough.rb +29 -0
  172. data/lib/coradoc/asciidoc/serializer/serializers/inline/subscript.rb +29 -0
  173. data/lib/coradoc/asciidoc/serializer/serializers/inline/superscript.rb +26 -0
  174. data/lib/coradoc/asciidoc/serializer/serializers/inline/underline.rb +20 -0
  175. data/lib/coradoc/asciidoc/serializer/serializers/inline.rb +32 -0
  176. data/lib/coradoc/asciidoc/serializer/serializers/line_break.rb +18 -0
  177. data/lib/coradoc/asciidoc/serializer/serializers/list/core.rb +47 -0
  178. data/lib/coradoc/asciidoc/serializer/serializers/list/definition.rb +35 -0
  179. data/lib/coradoc/asciidoc/serializer/serializers/list/definition_item.rb +38 -0
  180. data/lib/coradoc/asciidoc/serializer/serializers/list/item.rb +120 -0
  181. data/lib/coradoc/asciidoc/serializer/serializers/list/ordered.rb +24 -0
  182. data/lib/coradoc/asciidoc/serializer/serializers/list/unordered.rb +29 -0
  183. data/lib/coradoc/asciidoc/serializer/serializers/list.rb +19 -0
  184. data/lib/coradoc/asciidoc/serializer/serializers/named_attribute.rb +22 -0
  185. data/lib/coradoc/asciidoc/serializer/serializers/paragraph.rb +65 -0
  186. data/lib/coradoc/asciidoc/serializer/serializers/reviewer_note.rb +28 -0
  187. data/lib/coradoc/asciidoc/serializer/serializers/revision.rb +26 -0
  188. data/lib/coradoc/asciidoc/serializer/serializers/section.rb +37 -0
  189. data/lib/coradoc/asciidoc/serializer/serializers/table.rb +24 -0
  190. data/lib/coradoc/asciidoc/serializer/serializers/table_cell.rb +75 -0
  191. data/lib/coradoc/asciidoc/serializer/serializers/table_row.rb +24 -0
  192. data/lib/coradoc/asciidoc/serializer/serializers/tag.rb +19 -0
  193. data/lib/coradoc/asciidoc/serializer/serializers/term.rb +20 -0
  194. data/lib/coradoc/asciidoc/serializer/serializers/text_element.rb +23 -0
  195. data/lib/coradoc/asciidoc/serializer/serializers/title.rb +55 -0
  196. data/lib/coradoc/asciidoc/serializer/serializers/video.rb +33 -0
  197. data/lib/coradoc/asciidoc/serializer/spacing_strategy.rb +70 -0
  198. data/lib/coradoc/asciidoc/serializer.rb +75 -0
  199. data/lib/coradoc/asciidoc/transform/from_core_model.rb +502 -0
  200. data/lib/coradoc/asciidoc/transform/from_core_model_registrations.rb +126 -0
  201. data/lib/coradoc/asciidoc/transform/registry.rb +146 -0
  202. data/lib/coradoc/asciidoc/transform/to_core_model.rb +564 -0
  203. data/lib/coradoc/asciidoc/transform/to_core_model_registrations.rb +257 -0
  204. data/lib/coradoc/asciidoc/transform.rb +13 -0
  205. data/lib/coradoc/asciidoc/transformer/block_rules.rb +101 -0
  206. data/lib/coradoc/asciidoc/transformer/header_rules.rb +91 -0
  207. data/lib/coradoc/asciidoc/transformer/inline_rules.rb +179 -0
  208. data/lib/coradoc/asciidoc/transformer/list_rules.rb +131 -0
  209. data/lib/coradoc/asciidoc/transformer/misc_rules.rb +196 -0
  210. data/lib/coradoc/asciidoc/transformer/structural_rules.rb +216 -0
  211. data/lib/coradoc/asciidoc/transformer/text_rules.rb +107 -0
  212. data/lib/coradoc/asciidoc/transformer.rb +406 -0
  213. data/lib/coradoc/asciidoc/version.rb +7 -0
  214. data/lib/coradoc/asciidoc.rb +148 -0
  215. data/lib/coradoc/util/asciidoc.rb +71 -0
  216. data/lib/coradoc/util.rb +8 -0
  217. metadata +343 -0
@@ -0,0 +1,282 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ # Value object for defining spacing behavior of document elements
7
+ #
8
+ # Provides a unified way to control spacing around blocks, replacing
9
+ # the scattered spacing_* attributes and trailing_newlines.
10
+ #
11
+ # @example Default spacing
12
+ # spacing = Spacing.default
13
+ # # before_block: 0, after_close: 2
14
+ #
15
+ # @example Compact spacing (for lists)
16
+ # spacing = Spacing.compact
17
+ # # after_close: 1
18
+ #
19
+ # @example No spacing (last element)
20
+ # spacing = Spacing.none
21
+ # # after_close: 0, trailing_newlines: ""
22
+ #
23
+ # @example Custom spacing
24
+ # spacing = Spacing.new(
25
+ # before_block: 1,
26
+ # after_close: 3
27
+ # )
28
+ #
29
+ # @example Exact round-trip spacing
30
+ # spacing = Spacing.new(
31
+ # trailing_newlines: "\n\n\n"
32
+ # )
33
+ #
34
+ class Spacing
35
+ # Number of newlines before the block element
36
+ #
37
+ # @return [Integer] newlines before block
38
+ attr_reader :before_block
39
+
40
+ # Number of newlines after opening delimiter
41
+ # (for delimited blocks like ===, ****, etc.)
42
+ #
43
+ # @return [Integer] newlines after open delimiter
44
+ attr_reader :after_open
45
+
46
+ # Number of newlines before closing delimiter
47
+ # (for delimited blocks)
48
+ #
49
+ # @return [Integer] newlines before close delimiter
50
+ attr_reader :before_close
51
+
52
+ # Number of newlines after closing delimiter
53
+ # (most common spacing control)
54
+ #
55
+ # @return [Integer] newlines after close delimiter
56
+ attr_reader :after_close
57
+
58
+ # Exact trailing newlines for round-trip preservation
59
+ # When nil, uses calculated spacing from after_close
60
+ # When set to a string, uses that exact value
61
+ #
62
+ # @return [String, nil] exact trailing newlines or nil
63
+ attr_reader :trailing_newlines
64
+
65
+ # Create a new Spacing value object
66
+ #
67
+ # @param before_block [Integer] Newlines before block
68
+ # @param after_open [Integer] Newlines after opening delimiter
69
+ # @param before_close [Integer] Newlines before closing delimiter
70
+ # @param after_close [Integer] Newlines after closing delimiter
71
+ # @param trailing_newlines [String, nil] Exact trailing newlines for round-trip
72
+ #
73
+ # @example Create default spacing
74
+ # spacing = Spacing.new
75
+ #
76
+ # @example Create compact spacing
77
+ # spacing = Spacing.new(after_close: 1)
78
+ #
79
+ # @example Create exact spacing for round-trip
80
+ # spacing = Spacing.new(trailing_newlines: "\n\n")
81
+ #
82
+ def initialize(before_block: 0, after_open: 1, before_close: 1,
83
+ after_close: 2, trailing_newlines: nil)
84
+ @before_block = before_block
85
+ @after_open = after_open
86
+ @before_close = before_close
87
+ @after_close = after_close
88
+ @trailing_newlines = trailing_newlines
89
+ freeze
90
+ end
91
+
92
+ # Default spacing for standard blocks
93
+ # Most blocks have 2 newlines after them
94
+ #
95
+ # @return [Spacing] Default spacing configuration
96
+ #
97
+ # @example Use default spacing
98
+ # paragraph.spacing = Spacing.default
99
+ #
100
+ def self.default
101
+ new
102
+ end
103
+
104
+ # Compact spacing for tight layouts
105
+ # Used in lists, nested blocks, etc.
106
+ #
107
+ # @return [Spacing] Compact spacing configuration
108
+ #
109
+ # @example Use compact spacing in lists
110
+ # list_item.spacing = Spacing.compact
111
+ #
112
+ def self.compact
113
+ new(after_close: 1)
114
+ end
115
+
116
+ # No spacing after the element
117
+ # Used for the last element in a container
118
+ #
119
+ # @return [Spacing] No trailing spacing configuration
120
+ #
121
+ # @example Use for last element
122
+ # last_paragraph.spacing = Spacing.none
123
+ #
124
+ def self.none
125
+ new(after_close: 0, trailing_newlines: '')
126
+ end
127
+
128
+ # Check if this is the default spacing
129
+ #
130
+ # @return [Boolean] true if default spacing
131
+ #
132
+ def default?
133
+ before_block.zero? &&
134
+ after_open == 1 &&
135
+ before_close == 1 &&
136
+ after_close == 2 &&
137
+ trailing_newlines.nil?
138
+ end
139
+
140
+ # Check if this is compact spacing
141
+ #
142
+ # @return [Boolean] true if compact spacing
143
+ #
144
+ def compact?
145
+ before_block.zero? &&
146
+ after_open == 1 &&
147
+ before_close == 1 &&
148
+ after_close == 1 &&
149
+ trailing_newlines.nil?
150
+ end
151
+
152
+ # Check if this has no trailing spacing
153
+ #
154
+ # @return [Boolean] true if no trailing spacing
155
+ #
156
+ def none?
157
+ after_close.zero? && trailing_newlines == ''
158
+ end
159
+
160
+ # Check if exact trailing newlines are set
161
+ #
162
+ # @return [Boolean] true if trailing_newlines is explicitly set
163
+ #
164
+ def exact_mode?
165
+ !trailing_newlines.nil?
166
+ end
167
+
168
+ # Get the trailing newlines string
169
+ #
170
+ # Returns the exact trailing_newlines if set,
171
+ # otherwise calculates from after_close
172
+ #
173
+ # @return [String] The trailing newlines string
174
+ #
175
+ # @example Get trailing newlines
176
+ # spacing = Spacing.new(after_close: 2)
177
+ # spacing.trailing # => "\n\n"
178
+ #
179
+ def trailing
180
+ return trailing_newlines if exact_mode?
181
+
182
+ "\n" * after_close
183
+ end
184
+
185
+ # Get newlines before block
186
+ #
187
+ # @return [String] Newlines before block
188
+ #
189
+ def before
190
+ "\n" * before_block
191
+ end
192
+
193
+ # Get newlines after opening delimiter
194
+ #
195
+ # @return [String] Newlines after open
196
+ #
197
+ def after_open_newlines
198
+ "\n" * after_open
199
+ end
200
+
201
+ # Get newlines before closing delimiter
202
+ #
203
+ # @return [String] Newlines before close
204
+ #
205
+ def before_close_newlines
206
+ "\n" * before_close
207
+ end
208
+
209
+ # Create a new spacing with modified after_close value
210
+ #
211
+ # @param value [Integer] New after_close value
212
+ # @return [Spacing] New spacing with modified value
213
+ #
214
+ # @example
215
+ # spacing = Spacing.default.with_after_close(3)
216
+ #
217
+ def with_after_close(value)
218
+ Spacing.new(
219
+ before_block: before_block,
220
+ after_open: after_open,
221
+ before_close: before_close,
222
+ after_close: value,
223
+ trailing_newlines: trailing_newlines
224
+ )
225
+ end
226
+
227
+ # Create a new spacing with exact trailing newlines
228
+ #
229
+ # @param value [String] Exact trailing newlines
230
+ # @return [Spacing] New spacing with exact trailing newlines
231
+ #
232
+ # @example
233
+ # spacing = Spacing.default.with_trailing("\n\n\n")
234
+ #
235
+ def with_trailing(value)
236
+ Spacing.new(
237
+ before_block: before_block,
238
+ after_open: after_open,
239
+ before_close: before_close,
240
+ after_close: after_close,
241
+ trailing_newlines: value
242
+ )
243
+ end
244
+
245
+ # String representation for debugging
246
+ #
247
+ # @return [String] Debug string
248
+ #
249
+ def inspect
250
+ "#<#{self.class.name} before=#{before_block} after_open=#{after_open} " \
251
+ "before_close=#{before_close} after_close=#{after_close} " \
252
+ "trailing=#{trailing_newlines.inspect}>"
253
+ end
254
+ alias to_s inspect
255
+
256
+ # Two spacings are equal if all attributes match
257
+ #
258
+ # @param other [Object] Object to compare
259
+ # @return [Boolean] true if equal
260
+ #
261
+ def ==(other)
262
+ return false unless other.is_a?(Spacing)
263
+
264
+ before_block == other.before_block &&
265
+ after_open == other.after_open &&
266
+ before_close == other.before_close &&
267
+ after_close == other.after_close &&
268
+ trailing_newlines == other.trailing_newlines
269
+ end
270
+ alias eql? ==
271
+
272
+ # Hash code for use in Hash keys
273
+ #
274
+ # @return [Integer] Hash code
275
+ #
276
+ def hash
277
+ [before_block, after_open, before_close, after_close, trailing_newlines].hash
278
+ end
279
+ end
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ # Table element for AsciiDoc tables.
7
+ #
8
+ # Represents a table with rows and cells. Tables can have titles,
9
+ # captions, and various formatting options.
10
+ #
11
+ # @!attribute [r] id
12
+ # @return [String, nil] Optional identifier for the table
13
+ # @!attribute [r] title
14
+ # @return [String, nil] Optional table title
15
+ # @!attribute [r] rows
16
+ # @return [Array<TableRow>] Table rows
17
+ # @!attribute [r] content
18
+ # @return [String, nil] Optional string content
19
+ # @!attribute [r] attrs
20
+ # @return [AttributeList] Additional table attributes
21
+ #
22
+ # @example Create a simple table
23
+ # table = Coradoc::AsciiDoc::Model::Table.new
24
+ # table.rows << Coradoc::AsciiDoc::Model::TableRow.new
25
+ #
26
+ class Table < Base
27
+ include Coradoc::AsciiDoc::Model::Anchorable
28
+
29
+ def block_level?
30
+ true
31
+ end
32
+
33
+ attribute :id, :string
34
+ attribute :title, :string
35
+ attribute :rows, Coradoc::AsciiDoc::Model::TableRow, collection: true
36
+ attribute :content, :string
37
+ # attribute :anchor, Inline::Anchor, default: -> {
38
+ # id.nil? ? nil : Inline::Anchor.new(id)
39
+ # }
40
+ attribute :attrs, Coradoc::AsciiDoc::Model::AttributeList
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ # Table cell with full AsciiDoc format specification support
7
+ #
8
+ # Cell format specification: [colspan][.rowspan][halign][valign][style][*]
9
+ #
10
+ # @!attribute [r] id
11
+ # @return [String, nil] Optional cell identifier
12
+ # @!attribute [r] content
13
+ # @return [Array<TextElement>] Cell content
14
+ # @!attribute [r] colspan
15
+ # @return [Integer, nil] Number of columns to span
16
+ # @!attribute [r] rowspan
17
+ # @return [Integer, nil] Number of rows to span
18
+ # @!attribute [r] halign
19
+ # @return [String, nil] Horizontal alignment: "<" left, "^" center, ">" right
20
+ # @!attribute [r] valign
21
+ # @return [String, nil] Vertical alignment: "<" top, "^" middle, ">" bottom
22
+ # @!attribute [r] style
23
+ # @return [String, nil] Cell style: d/s/e/m/a/l/v
24
+ # @!attribute [r] repeat
25
+ # @return [Boolean] Whether to repeat last cell
26
+ # @!attribute [r] colrowattr
27
+ # @return [String] Legacy combined colspan.rowspan string (for serialization)
28
+ # @!attribute [r] alignattr
29
+ # @return [String] Legacy alignment string (for serialization)
30
+ #
31
+ # @example Cell spanning 2 columns
32
+ # cell = TableCell.new(content: "text", colspan: 2)
33
+ #
34
+ # @example Centered cell with emphasis style
35
+ # cell = TableCell.new(content: "text", halign: "^", style: "e")
36
+ #
37
+ class TableCell < Base
38
+ include Coradoc::AsciiDoc::Model::Anchorable
39
+
40
+ # Core attributes
41
+ attribute :id, :string
42
+ attribute :content, Coradoc::AsciiDoc::Model::TextElement, collection: true, initialize_empty: true
43
+
44
+ # Cell format specification attributes
45
+ attribute :colspan, :integer
46
+ attribute :rowspan, :integer
47
+ attribute :halign, :string # "<" left, "^" center, ">" right
48
+ attribute :valign, :string # "<" top, "^" middle, ">" bottom
49
+ attribute :style, :string # d/s/e/m/a/l/v
50
+ attribute :repeat, :boolean, default: -> { false }
51
+
52
+ # Legacy attributes for backward compatibility with serializer
53
+ attribute :colrowattr, :string, default: -> { '' }
54
+ attribute :alignattr, :string, default: -> { '' }
55
+
56
+ # Check if this cell contains AsciiDoc content
57
+ def asciidoc?
58
+ style == 'a'
59
+ end
60
+
61
+ # Check if this cell has literal content
62
+ def literal?
63
+ style == 'l'
64
+ end
65
+
66
+ # Check if this cell has verse style
67
+ def verse?
68
+ style == 'v'
69
+ end
70
+
71
+ # Get horizontal alignment as CSS value
72
+ # @return [String, nil] "left", "center", or "right"
73
+ def horizontal_alignment
74
+ case halign
75
+ when '<' then 'left'
76
+ when '^' then 'center'
77
+ when '>' then 'right'
78
+ end
79
+ end
80
+
81
+ # Get vertical alignment as CSS value
82
+ # @return [String, nil] "top", "middle", or "bottom"
83
+ def vertical_alignment
84
+ case valign
85
+ when '<' then 'top'
86
+ when '^' then 'middle'
87
+ when '>' then 'bottom'
88
+ end
89
+ end
90
+
91
+ # Get style name as human-readable string
92
+ # @return [String, nil] Style name
93
+ def style_name
94
+ case style
95
+ when 'd' then 'default'
96
+ when 's' then 'strong'
97
+ when 'e' then 'emphasis'
98
+ when 'm' then 'monospace'
99
+ when 'a' then 'asciidoc'
100
+ when 'l' then 'literal'
101
+ when 'v' then 'verse'
102
+ end
103
+ end
104
+
105
+ # Generate colrowattr for serialization (e.g., "2.3" for colspan=2, rowspan=3)
106
+ # @return [String] Combined colspan.rowspan string
107
+ def generate_colrowattr
108
+ result = ''
109
+ result += colspan.to_s if colspan && colspan > 1
110
+ result += ".#{rowspan}" if rowspan && rowspan > 1
111
+ result
112
+ end
113
+
114
+ # Generate alignattr for serialization (e.g., "^" for center)
115
+ # @return [String] Combined alignment string
116
+ def generate_alignattr
117
+ (halign || '') + (valign || '')
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ class TableRow < Base
7
+ attribute :columns, Coradoc::AsciiDoc::Model::TableCell, collection: true
8
+ attribute :header, :boolean, default: -> { false }
9
+
10
+ def table_header_row?
11
+ header
12
+ end
13
+
14
+ def asciidoc?
15
+ columns&.any? { |c| c.is_a?(Coradoc::AsciiDoc::Model::TableCell) && c.asciidoc? } || false
16
+ end
17
+
18
+ # NOTE: underline_for provides trailing newline for table row serialization.
19
+ # The method name follows AsciiDoc table formatting conventions.
20
+ def underline_for
21
+ "\n"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ # Tag element for AsciiDoc documents.
7
+ #
8
+ # Tags are metadata markers that can be associated with document elements.
9
+ #
10
+ # @!attribute [r] name
11
+ # @return [String] The tag name
12
+ #
13
+ # @!attribute [r] prefix
14
+ # @return [String] Tag prefix (default: "tag")
15
+ #
16
+ # @!attribute [r] attrs
17
+ # @return [Coradoc::AsciiDoc::Model::AttributeList] Tag attributes
18
+ #
19
+ # @!attribute [r] line_break
20
+ # @return [String] Line break character (default: "\n")
21
+ #
22
+ # @example Create a tag
23
+ # tag = Coradoc::AsciiDoc::Model::Tag.new
24
+ # tag.name = "important"
25
+ #
26
+ class Tag < Base
27
+ attribute :name, :string
28
+ attribute :prefix, :string, default: 'tag'
29
+ attribute :attrs, Coradoc::AsciiDoc::Model::AttributeList, default: lambda {
30
+ Coradoc::AsciiDoc::Model::AttributeList.new
31
+ }
32
+ attribute :line_break, :string, default: -> { "\n" }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ # Term element for AsciiDoc definition lists.
7
+ #
8
+ # Terms are the items being defined in definition lists.
9
+ # Each term has a text value and can have an optional type.
10
+ #
11
+ # @!attribute [r] term
12
+ # @return [String] The term text being defined
13
+ #
14
+ # @!attribute [r] type
15
+ # @return [String] The term type/category
16
+ #
17
+ # @!attribute [r] lang
18
+ # @return [String] Language code (default: "en")
19
+ #
20
+ # @!attribute [r] line_break
21
+ # @return [String] Line break character (default: "")
22
+ #
23
+ # @example Create a term
24
+ # term = Coradoc::AsciiDoc::Model::Term.new
25
+ # term.term = "ASCII"
26
+ # term.type = "acronym"
27
+ #
28
+ # @see Coradoc::AsciiDoc::Model::List::Definition Definition lists
29
+ #
30
+ class Term < Base
31
+ attribute :term, :string
32
+ attribute :type, :string
33
+ attribute :lang, :string, default: -> { 'en' }
34
+ attribute :line_break, :string, default: -> { '' }
35
+
36
+ def validate
37
+ errors = super
38
+
39
+ errors << Lutaml::Model::Error.new('Term cannot be nil or empty') if term.nil? || term.empty?
40
+
41
+ errors << Lutaml::Model::Error.new('Type cannot be nil or empty') if type.nil? || type.empty?
42
+
43
+ errors
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coradoc
4
+ module AsciiDoc
5
+ module Model
6
+ class TextElement < Base
7
+ def inline?
8
+ true
9
+ end
10
+
11
+ attribute :id, :string
12
+ attribute :content,
13
+ Lutaml::Model::Serializable,
14
+ default: -> { '' },
15
+ polymorphic: [
16
+ Lutaml::Model::Type::String,
17
+ :array
18
+ ]
19
+ attribute :line_break, :string, default: -> { '' }
20
+
21
+ def self.escape_keychars(string)
22
+ subs = { '*' => '\*', '_' => '\_' }
23
+ string
24
+ .gsub(/((?<=\s)[*_]+)|[*_]+(?=\s)/) do |n|
25
+ n.chars.map do |char|
26
+ subs[char]
27
+ end.join
28
+ end
29
+ end
30
+
31
+ # Get text content as string
32
+ #
33
+ # @return [String] The text content
34
+ #
35
+ def to_s
36
+ case content
37
+ when String
38
+ content
39
+ when Array
40
+ content.map(&:to_s).join
41
+ when Coradoc::AsciiDoc::Model::Base
42
+ content.to_adoc
43
+ when Lutaml::Model::Serializable
44
+ if content.class.attributes.key?(:content)
45
+ content.content.to_s
46
+ else
47
+ ''
48
+ end
49
+ when nil
50
+ ''
51
+ else
52
+ content.is_a?(String) ? content.to_s : ''
53
+ end
54
+ end
55
+
56
+ # Alias for text to work with ContentList
57
+ #
58
+ # @return [String] The text content
59
+ #
60
+ def text
61
+ to_s
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end