coradoc-html 1.1.7 → 1.1.13

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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coradoc/html/config.rb +36 -12
  3. data/lib/coradoc/html/converter_base.rb +26 -68
  4. data/lib/coradoc/html/drop/annotation_drop.rb +31 -0
  5. data/lib/coradoc/html/drop/base.rb +77 -0
  6. data/lib/coradoc/html/drop/bibliography_drop.rb +15 -0
  7. data/lib/coradoc/html/drop/bibliography_entry_drop.rb +24 -0
  8. data/lib/coradoc/html/drop/block_drop.rb +69 -0
  9. data/lib/coradoc/html/drop/definition_item_drop.rb +36 -0
  10. data/lib/coradoc/html/drop/definition_list_drop.rb +15 -0
  11. data/lib/coradoc/html/drop/document_drop.rb +52 -0
  12. data/lib/coradoc/html/drop/drop_factory.rb +73 -0
  13. data/lib/coradoc/html/drop/footnote_drop.rb +24 -0
  14. data/lib/coradoc/html/drop/image_drop.rb +35 -0
  15. data/lib/coradoc/html/drop/inline_element_drop.rb +64 -0
  16. data/lib/coradoc/html/drop/list_block_drop.rb +23 -0
  17. data/lib/coradoc/html/drop/list_item_drop.rb +20 -0
  18. data/lib/coradoc/html/drop/table_cell_drop.rb +35 -0
  19. data/lib/coradoc/html/drop/table_drop.rb +15 -0
  20. data/lib/coradoc/html/drop/table_row_drop.rb +23 -0
  21. data/lib/coradoc/html/drop/term_drop.rb +24 -0
  22. data/lib/coradoc/html/drop/text_content_drop.rb +15 -0
  23. data/lib/coradoc/html/drop/toc_drop.rb +15 -0
  24. data/lib/coradoc/html/drop/toc_entry_drop.rb +32 -0
  25. data/lib/coradoc/html/escape.rb +29 -0
  26. data/lib/coradoc/html/input/cleaner.rb +4 -33
  27. data/lib/coradoc/html/input/config.rb +4 -3
  28. data/lib/coradoc/html/input/converters/a.rb +8 -19
  29. data/lib/coradoc/html/input/converters/aside.rb +4 -5
  30. data/lib/coradoc/html/input/converters/audio.rb +8 -35
  31. data/lib/coradoc/html/input/converters/base.rb +29 -27
  32. data/lib/coradoc/html/input/converters/blockquote.rb +4 -2
  33. data/lib/coradoc/html/input/converters/br.rb +4 -4
  34. data/lib/coradoc/html/input/converters/bypass.rb +68 -67
  35. data/lib/coradoc/html/input/converters/code.rb +7 -5
  36. data/lib/coradoc/html/input/converters/div.rb +4 -4
  37. data/lib/coradoc/html/input/converters/dl.rb +3 -25
  38. data/lib/coradoc/html/input/converters/drop.rb +13 -13
  39. data/lib/coradoc/html/input/converters/em.rb +5 -3
  40. data/lib/coradoc/html/input/converters/figure.rb +3 -26
  41. data/lib/coradoc/html/input/converters/h.rb +9 -11
  42. data/lib/coradoc/html/input/converters/head.rb +5 -4
  43. data/lib/coradoc/html/input/converters/hr.rb +4 -5
  44. data/lib/coradoc/html/input/converters/img.rb +4 -9
  45. data/lib/coradoc/html/input/converters/li.rb +3 -1
  46. data/lib/coradoc/html/input/converters/mark.rb +3 -1
  47. data/lib/coradoc/html/input/converters/markup.rb +4 -8
  48. data/lib/coradoc/html/input/converters/math.rb +7 -14
  49. data/lib/coradoc/html/input/converters/media_base.rb +50 -0
  50. data/lib/coradoc/html/input/converters/ol.rb +6 -8
  51. data/lib/coradoc/html/input/converters/p.rb +43 -34
  52. data/lib/coradoc/html/input/converters/pass_through.rb +2 -4
  53. data/lib/coradoc/html/input/converters/positional_formatting.rb +37 -0
  54. data/lib/coradoc/html/input/converters/pre.rb +3 -3
  55. data/lib/coradoc/html/input/converters/q.rb +6 -3
  56. data/lib/coradoc/html/input/converters/strong.rb +4 -2
  57. data/lib/coradoc/html/input/converters/sub.rb +7 -23
  58. data/lib/coradoc/html/input/converters/sup.rb +7 -23
  59. data/lib/coradoc/html/input/converters/table.rb +3 -1
  60. data/lib/coradoc/html/input/converters/td.rb +4 -30
  61. data/lib/coradoc/html/input/converters/text.rb +4 -3
  62. data/lib/coradoc/html/input/converters/tr.rb +3 -2
  63. data/lib/coradoc/html/input/converters/video.rb +14 -36
  64. data/lib/coradoc/html/input/converters.rb +17 -35
  65. data/lib/coradoc/html/input/html_converter.rb +2 -74
  66. data/lib/coradoc/html/input/plugin.rb +8 -50
  67. data/lib/coradoc/html/input/plugins/plateau.rb +4 -19
  68. data/lib/coradoc/html/input/postprocessor.rb +3 -9
  69. data/lib/coradoc/html/input.rb +26 -8
  70. data/lib/coradoc/html/layout_renderer.rb +163 -0
  71. data/lib/coradoc/html/output.rb +6 -12
  72. data/lib/coradoc/html/renderer.rb +84 -350
  73. data/lib/coradoc/html/section_numberable.rb +9 -0
  74. data/lib/coradoc/html/spa.rb +29 -270
  75. data/lib/coradoc/html/static.rb +29 -238
  76. data/lib/coradoc/html/template_caching.rb +31 -0
  77. data/lib/coradoc/html/template_config.rb +11 -70
  78. data/lib/coradoc/html/template_helpers.rb +39 -31
  79. data/lib/coradoc/html/template_locator.rb +17 -11
  80. data/lib/coradoc/html/theme.rb +1 -7
  81. data/lib/coradoc/html/title_text.rb +57 -0
  82. data/lib/coradoc/html/toc_builder.rb +105 -0
  83. data/lib/coradoc/html/toc_serializer.rb +33 -0
  84. data/lib/coradoc/html/transform/from_core_model.rb +13 -12
  85. data/lib/coradoc/html/transform/to_core_model.rb +10 -12
  86. data/lib/coradoc/html/version.rb +1 -1
  87. data/lib/coradoc/html.rb +43 -88
  88. metadata +37 -70
  89. data/lib/coradoc/html/base.rb +0 -157
  90. data/lib/coradoc/html/converters/admonition.rb +0 -180
  91. data/lib/coradoc/html/converters/attribute.rb +0 -68
  92. data/lib/coradoc/html/converters/attribute_reference.rb +0 -60
  93. data/lib/coradoc/html/converters/audio.rb +0 -165
  94. data/lib/coradoc/html/converters/base.rb +0 -615
  95. data/lib/coradoc/html/converters/bibliography.rb +0 -82
  96. data/lib/coradoc/html/converters/bibliography_entry.rb +0 -108
  97. data/lib/coradoc/html/converters/block_image.rb +0 -72
  98. data/lib/coradoc/html/converters/bold.rb +0 -34
  99. data/lib/coradoc/html/converters/break.rb +0 -32
  100. data/lib/coradoc/html/converters/comment_block.rb +0 -42
  101. data/lib/coradoc/html/converters/comment_line.rb +0 -54
  102. data/lib/coradoc/html/converters/cross_reference.rb +0 -59
  103. data/lib/coradoc/html/converters/document.rb +0 -108
  104. data/lib/coradoc/html/converters/example.rb +0 -114
  105. data/lib/coradoc/html/converters/highlight.rb +0 -34
  106. data/lib/coradoc/html/converters/include.rb +0 -68
  107. data/lib/coradoc/html/converters/inline_image.rb +0 -41
  108. data/lib/coradoc/html/converters/italic.rb +0 -34
  109. data/lib/coradoc/html/converters/line_break.rb +0 -31
  110. data/lib/coradoc/html/converters/link.rb +0 -46
  111. data/lib/coradoc/html/converters/list_item.rb +0 -75
  112. data/lib/coradoc/html/converters/listing.rb +0 -99
  113. data/lib/coradoc/html/converters/literal.rb +0 -102
  114. data/lib/coradoc/html/converters/monospace.rb +0 -34
  115. data/lib/coradoc/html/converters/open.rb +0 -78
  116. data/lib/coradoc/html/converters/ordered.rb +0 -53
  117. data/lib/coradoc/html/converters/paragraph.rb +0 -46
  118. data/lib/coradoc/html/converters/quote.rb +0 -113
  119. data/lib/coradoc/html/converters/reviewer_comment.rb +0 -74
  120. data/lib/coradoc/html/converters/reviewer_note.rb +0 -134
  121. data/lib/coradoc/html/converters/section.rb +0 -90
  122. data/lib/coradoc/html/converters/sidebar.rb +0 -113
  123. data/lib/coradoc/html/converters/source.rb +0 -137
  124. data/lib/coradoc/html/converters/source_code.rb +0 -16
  125. data/lib/coradoc/html/converters/span.rb +0 -61
  126. data/lib/coradoc/html/converters/strikethrough.rb +0 -34
  127. data/lib/coradoc/html/converters/subscript.rb +0 -34
  128. data/lib/coradoc/html/converters/superscript.rb +0 -34
  129. data/lib/coradoc/html/converters/table.rb +0 -85
  130. data/lib/coradoc/html/converters/table_cell.rb +0 -203
  131. data/lib/coradoc/html/converters/table_row.rb +0 -45
  132. data/lib/coradoc/html/converters/template_html_converter.rb +0 -105
  133. data/lib/coradoc/html/converters/term.rb +0 -58
  134. data/lib/coradoc/html/converters/text_element.rb +0 -44
  135. data/lib/coradoc/html/converters/underline.rb +0 -34
  136. data/lib/coradoc/html/converters/unordered.rb +0 -47
  137. data/lib/coradoc/html/converters/verse.rb +0 -105
  138. data/lib/coradoc/html/converters/video.rb +0 -179
  139. data/lib/coradoc/html/element_mapping.rb +0 -210
  140. data/lib/coradoc/html/entity.rb +0 -137
  141. data/lib/coradoc/html/input/converters/ignore.rb +0 -22
  142. data/lib/coradoc/html/input/converters/th.rb +0 -20
  143. data/lib/coradoc/html/theme/base.rb +0 -231
  144. data/lib/coradoc/html/theme/classic_renderer.rb +0 -390
  145. data/lib/coradoc/html/theme/modern/components/ui_components.rb +0 -344
  146. data/lib/coradoc/html/theme/modern/css_generator.rb +0 -311
  147. data/lib/coradoc/html/theme/modern/javascript_generator.rb +0 -314
  148. data/lib/coradoc/html/theme/modern/serializers/document_serializer.rb +0 -382
  149. data/lib/coradoc/html/theme/modern/tailwind_config_builder.rb +0 -164
  150. data/lib/coradoc/html/theme/modern/vue_template_generator.rb +0 -374
  151. data/lib/coradoc/html/theme/modern_renderer.rb +0 -250
  152. data/lib/coradoc/html/theme/registry.rb +0 -153
@@ -1,210 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Html
5
- # Element mapping between CoreModel and HTML elements
6
- #
7
- # This module provides bidirectional mapping between CoreModel types
8
- # and HTML elements for conversion purposes.
9
- module ElementMapping
10
- class << self
11
- # Map CoreModel class to HTML element
12
- def model_to_html_element(model_class)
13
- model_name = model_class.name.split('::').last.downcase.to_sym
14
- MODEL_TO_HTML[model_name] || default_element_for(model_class)
15
- end
16
-
17
- # Map HTML element to CoreModel class
18
- def html_element_to_model(tag_name, context = {})
19
- tag = tag_name.to_s.downcase.to_sym
20
- HTML_TO_MODEL[tag] || default_model_for(tag, context)
21
- end
22
-
23
- # Get default element for a model class
24
- def default_element_for(model_class)
25
- if model_class.ancestors.any? { |a| a.name&.include?('InlineElement') }
26
- { tag: 'span', semantic: false }
27
- else
28
- { tag: 'div', semantic: false }
29
- end
30
- end
31
-
32
- # Get default model for an HTML element
33
- def default_model_for(tag, _context)
34
- # Return CoreModel types
35
- case tag
36
- when :p, :div, :section, :article
37
- 'Coradoc::CoreModel::Block'
38
- when :strong, :b, :em, :i, :code
39
- 'Coradoc::CoreModel::InlineElement'
40
- else
41
- 'Coradoc::CoreModel::InlineElement'
42
- end
43
- end
44
-
45
- # Mapping from CoreModel types to HTML elements
46
- MODEL_TO_HTML = {
47
- # Document structure
48
- document: { tag: 'article', semantic: true },
49
- section: { tag: 'section', semantic: true },
50
- header: { tag: 'header', semantic: true },
51
- title: { tag: 'h1', semantic: true },
52
- structuralelement: { tag: 'section', semantic: true },
53
-
54
- # Block elements
55
- paragraph: { tag: 'p', semantic: true },
56
- block: { tag: 'div', semantic: true },
57
- example: { tag: 'div', class: 'example', semantic: false },
58
- annotationblock: { tag: 'aside', semantic: true },
59
- quote: { tag: 'blockquote', semantic: true },
60
- verse: { tag: 'div', class: 'verse', semantic: false },
61
- listing: { tag: 'pre', semantic: true },
62
- literal: { tag: 'pre', semantic: true },
63
- source: { tag: 'pre', semantic: true },
64
- open: { tag: 'div', semantic: false },
65
- pass: { tag: 'div', class: 'pass', semantic: false },
66
-
67
- # Inline elements
68
- inlineelement: { tag: 'span', semantic: false },
69
- bold: { tag: 'strong', semantic: true },
70
- italic: { tag: 'em', semantic: true },
71
- monospace: { tag: 'code', semantic: true },
72
- highlight: { tag: 'mark', semantic: true },
73
- superscript: { tag: 'sup', semantic: true },
74
- subscript: { tag: 'sub', semantic: true },
75
- underline: { tag: 'u', semantic: false },
76
- strikethrough: { tag: 'del', semantic: true },
77
- smallcaps: { tag: 'span', class: 'small-caps', semantic: false },
78
- link: { tag: 'a', semantic: true },
79
- anchor: { tag: 'a', semantic: true },
80
- xref: { tag: 'a', class: 'xref', semantic: true },
81
- quotation: { tag: 'q', semantic: true },
82
-
83
- # Lists
84
- listblock: { tag: 'ul', semantic: true },
85
- listitem: { tag: 'li', semantic: true },
86
- orderedlist: { tag: 'ol', semantic: true },
87
- unorderedlist: { tag: 'ul', semantic: true },
88
-
89
- # Tables
90
- table: { tag: 'table', semantic: true },
91
- tablerow: { tag: 'tr', semantic: true },
92
- tablecell: { tag: 'td', semantic: true },
93
-
94
- # Media
95
- image: { tag: 'img', semantic: true, self_closing: true },
96
- video: { tag: 'video', semantic: true },
97
- audio: { tag: 'audio', semantic: true },
98
-
99
- # Other
100
- break: { tag: 'hr', semantic: true, self_closing: true },
101
- linebreak: { tag: 'br', semantic: true, self_closing: true },
102
-
103
- # Text
104
- textelement: { tag: 'text', semantic: false }
105
- }.freeze
106
-
107
- # Mapping from HTML elements to CoreModel types
108
- HTML_TO_MODEL = {
109
- # Block elements
110
- p: 'Coradoc::CoreModel::Block',
111
- div: 'Coradoc::CoreModel::Block',
112
- section: 'Coradoc::CoreModel::StructuralElement',
113
- article: 'Coradoc::CoreModel::StructuralElement',
114
- header: 'Coradoc::CoreModel::StructuralElement',
115
- aside: 'Coradoc::CoreModel::AnnotationBlock',
116
- blockquote: 'Coradoc::CoreModel::Block',
117
- pre: 'Coradoc::CoreModel::Block',
118
-
119
- # Inline elements
120
- strong: 'Coradoc::CoreModel::InlineElement',
121
- b: 'Coradoc::CoreModel::InlineElement',
122
- em: 'Coradoc::CoreModel::InlineElement',
123
- i: 'Coradoc::CoreModel::InlineElement',
124
- code: 'Coradoc::CoreModel::InlineElement',
125
- mark: 'Coradoc::CoreModel::InlineElement',
126
- sup: 'Coradoc::CoreModel::InlineElement',
127
- sub: 'Coradoc::CoreModel::InlineElement',
128
- u: 'Coradoc::CoreModel::InlineElement',
129
- del: 'Coradoc::CoreModel::InlineElement',
130
- s: 'Coradoc::CoreModel::InlineElement',
131
- strike: 'Coradoc::CoreModel::InlineElement',
132
-
133
- # Links
134
- a: 'Coradoc::CoreModel::InlineElement',
135
-
136
- # Lists
137
- ul: 'Coradoc::CoreModel::ListBlock',
138
- ol: 'Coradoc::CoreModel::ListBlock',
139
- li: 'Coradoc::CoreModel::ListItem',
140
- dl: 'Coradoc::CoreModel::ListBlock',
141
- dt: 'Coradoc::CoreModel::ListItem',
142
- dd: 'Coradoc::CoreModel::ListItem',
143
-
144
- # Tables
145
- table: 'Coradoc::CoreModel::Table',
146
- tr: 'Coradoc::CoreModel::TableRow',
147
- td: 'Coradoc::CoreModel::TableCell',
148
- th: 'Coradoc::CoreModel::TableCell',
149
-
150
- # Media
151
- img: 'Coradoc::CoreModel::Image',
152
- video: 'Coradoc::CoreModel::Block',
153
- audio: 'Coradoc::CoreModel::Block',
154
-
155
- # Other
156
- hr: 'Coradoc::CoreModel::Block',
157
- br: 'Coradoc::CoreModel::InlineElement',
158
-
159
- # Headings
160
- h1: 'Coradoc::CoreModel::StructuralElement',
161
- h2: 'Coradoc::CoreModel::StructuralElement',
162
- h3: 'Coradoc::CoreModel::StructuralElement',
163
- h4: 'Coradoc::CoreModel::StructuralElement',
164
- h5: 'Coradoc::CoreModel::StructuralElement',
165
- h6: 'Coradoc::CoreModel::StructuralElement'
166
- }.freeze
167
-
168
- # Check if HTML element is block-level
169
- def block_element?(tag)
170
- BLOCK_ELEMENTS.include?(tag.to_sym)
171
- end
172
-
173
- # Check if HTML element is inline-level
174
- def inline_element?(tag)
175
- INLINE_ELEMENTS.include?(tag.to_sym)
176
- end
177
-
178
- # Check if HTML element is self-closing
179
- def self_closing?(tag)
180
- SELF_CLOSING_ELEMENTS.include?(tag.to_sym)
181
- end
182
-
183
- # Block-level HTML elements
184
- BLOCK_ELEMENTS = %i[
185
- div p section article aside header footer main nav
186
- blockquote pre ul ol li dl dt dd
187
- table tr td th thead tbody tfoot
188
- h1 h2 h3 h4 h5 h6
189
- hr
190
- figure figcaption
191
- ].freeze
192
-
193
- # Inline-level HTML elements
194
- INLINE_ELEMENTS = %i[
195
- span strong em b i u s del ins mark small
196
- code kbd samp var
197
- a abbr cite dfn q
198
- sub sup
199
- time
200
- br wbr
201
- ].freeze
202
-
203
- # Self-closing HTML elements
204
- SELF_CLOSING_ELEMENTS = %i[
205
- area base br col embed hr img input link meta param source track wbr
206
- ].freeze
207
- end
208
- end
209
- end
210
- end
@@ -1,137 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Html
5
- # HTML entity handling
6
- module Entity
7
- # Named HTML entities
8
- NAMED_ENTITIES = {
9
- 'nbsp' => "\u00A0",
10
- 'lt' => '<',
11
- 'gt' => '>',
12
- 'amp' => '&',
13
- 'quot' => '"',
14
- 'apos' => "'",
15
- 'cent' => "\u00A2",
16
- 'pound' => "\u00A3",
17
- 'yen' => "\u00A5",
18
- 'euro' => "\u20AC",
19
- 'copy' => "\u00A9",
20
- 'reg' => "\u00AE",
21
- 'trade' => "\u2122",
22
- 'mdash' => "\u2014",
23
- 'ndash' => "\u2013",
24
- 'hellip' => "\u2026",
25
- 'laquo' => "\u00AB",
26
- 'raquo' => "\u00BB",
27
- 'ldquo' => "\u201C",
28
- 'rdquo' => "\u201D",
29
- 'lsquo' => "\u2018",
30
- 'rsquo' => "\u2019"
31
- }.freeze
32
-
33
- class << self
34
- # Encode text to HTML entities
35
- def encode(text, options = {})
36
- return '' if text.nil?
37
- return text unless text.is_a?(String)
38
-
39
- encoded = text.dup
40
-
41
- # Basic HTML entities
42
- encoded = encoded
43
- .gsub('&', '&amp;')
44
- .gsub('<', '&lt;')
45
- .gsub('>', '&gt;')
46
- .gsub('"', '&quot;')
47
-
48
- # Optionally encode additional characters
49
- encoded = encoded.gsub("'", '&#39;') if options[:encode_quotes]
50
-
51
- encoded = encoded.gsub("\u00A0", '&nbsp;') if options[:encode_nbsp]
52
-
53
- encoded
54
- end
55
-
56
- # Decode HTML entities to text
57
- def decode(text)
58
- return '' if text.nil?
59
- return text unless text.is_a?(String)
60
-
61
- decoded = text.dup
62
-
63
- # Decode named entities
64
- NAMED_ENTITIES.each do |name, char|
65
- decoded = decoded.gsub("&#{name};", char)
66
- end
67
-
68
- # Decode numeric entities (decimal)
69
- decoded = decoded.gsub(/&#(\d+);/) do
70
- [::Regexp.last_match(1).to_i].pack('U')
71
- end
72
-
73
- # Decode numeric entities (hexadecimal)
74
- decoded = decoded.gsub(/&#x([0-9a-fA-F]+);/) do
75
- [::Regexp.last_match(1).to_i(16)].pack('U')
76
- end
77
-
78
- # Decode basic entities last
79
- decoded
80
- .gsub('&quot;', '"')
81
- .gsub('&#39;', "'")
82
- .gsub('&#x27;', "'")
83
- .gsub('&lt;', '<')
84
- .gsub('&gt;', '>')
85
- .gsub('&amp;', '&')
86
- end
87
-
88
- # Convert character to named entity if available
89
- def to_named_entity(char)
90
- entity_name = NAMED_ENTITIES.key(char)
91
- entity_name ? "&#{entity_name};" : char
92
- end
93
-
94
- # Convert character to numeric entity
95
- def to_numeric_entity(char, format: :decimal)
96
- codepoint = char.ord
97
-
98
- case format
99
- when :decimal
100
- "&##{codepoint};"
101
- when :hex, :hexadecimal
102
- "&#x#{codepoint.to_s(16)};"
103
- else
104
- char
105
- end
106
- end
107
-
108
- # Check if text contains HTML entities
109
- def has_entities?(text)
110
- return false unless text.is_a?(String)
111
-
112
- text.match?(/&[a-zA-Z]+;|&#\d+;|&#x[0-9a-fA-F]+;/)
113
- end
114
-
115
- # Normalize entities (convert all to named where possible, numeric otherwise)
116
- def normalize(text)
117
- return '' if text.nil?
118
- return text unless text.is_a?(String)
119
-
120
- # First decode to get actual characters
121
- decoded = decode(text)
122
-
123
- # Then encode back using named entities where possible
124
- decoded.chars.map do |char|
125
- case char
126
- when '&', '<', '>', '"', "'"
127
- encode(char)
128
- else
129
- named = to_named_entity(char)
130
- named == char ? char : named
131
- end
132
- end.join
133
- end
134
- end
135
- end
136
- end
137
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Ignore < Base
8
- def to_coradoc(node, state = {})
9
- convert(node, state)
10
- end
11
-
12
- def convert(_node, _state = {})
13
- '' # noop
14
- end
15
- end
16
-
17
- register :colgroup, Ignore.new
18
- register :col, Ignore.new
19
- end
20
- end
21
- end
22
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Th < Td
8
- def cellstyle(node)
9
- # this is the header row
10
- return '' if node.parent.previous_element.nil?
11
-
12
- 'h'
13
- end
14
- end
15
-
16
- register :th, Th.new
17
- end
18
- end
19
- end
20
- end
@@ -1,231 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'coradoc/html/base'
4
-
5
- module Coradoc
6
- module Html
7
- module Theme
8
- # Abstract base class for all HTML themes
9
- #
10
- # This class defines the interface that all theme renderers must implement.
11
- # Themes are responsible for converting Coradoc document models to HTML output.
12
- #
13
- # @abstract Subclass and implement {#render} to create a custom theme
14
- class Base
15
- attr_reader :document, :options
16
-
17
- # Initialize a new theme instance
18
- #
19
- # @param document [Coradoc::CoreModel::StructuralElement] The document to render
20
- # @param options [Hash] Rendering options
21
- def initialize(document, options = {})
22
- @document = document
23
- @options = options
24
- end
25
-
26
- # Render the document to HTML
27
- #
28
- # This method must be implemented by subclasses.
29
- #
30
- # @abstract
31
- # @return [String] The rendered HTML content
32
- def render
33
- raise NotImplementedError,
34
- "#{self.class.name} must implement #render method"
35
- end
36
-
37
- # Render the complete HTML5 document
38
- #
39
- # @return [String] Complete HTML5 document
40
- def render_html5
41
- html_body = render
42
- build_html5_document(html_body)
43
- end
44
-
45
- # Get the theme name
46
- #
47
- # @return [Symbol] Theme name (e.g., :classic, :modern)
48
- def theme_name
49
- @theme_name ||= self.class.name.split('::').last
50
- .gsub(/Renderer$/, '')
51
- .downcase
52
- .to_sym
53
- end
54
-
55
- # Check if this theme supports a specific feature
56
- #
57
- # @param feature [Symbol] Feature to check (e.g., :dark_mode, :interactive_toc)
58
- # @return [Boolean] true if the feature is supported
59
- def supports?(feature)
60
- supported_features.include?(feature)
61
- end
62
-
63
- # List of features supported by this theme
64
- #
65
- # Subclasses can override to declare supported features.
66
- #
67
- # @return [Array<Symbol>] List of supported features
68
- def supported_features
69
- []
70
- end
71
-
72
- protected
73
-
74
- # Build complete HTML5 document
75
- #
76
- # @param body_html [String] HTML body content
77
- # @return [String] Complete HTML5 document
78
- def build_html5_document(body_html)
79
- lang = @options[:lang] || 'en'
80
- body_classes = build_body_classes
81
-
82
- <<~HTML
83
- <!DOCTYPE html>
84
- <html lang="#{lang}">
85
- <head>
86
- #{build_head_content}
87
- </head>
88
- <body#{body_classes}>
89
- #{body_html}
90
- </body>
91
- </html>
92
- HTML
93
- end
94
-
95
- # Build HTML head content
96
- #
97
- # @return [String] Head section HTML
98
- def build_head_content
99
- parts = []
100
- parts << build_meta_tags
101
- parts << build_title_tag
102
- parts << build_css_tags
103
- parts << build_script_tags
104
- parts.compact.reject(&:empty?).join("\n")
105
- end
106
-
107
- # Build meta tags
108
- #
109
- # @return [String] Meta tags HTML
110
- def build_meta_tags
111
- meta = []
112
- meta << ' <meta charset="UTF-8">'
113
- meta << ' <meta name="viewport" content="width=device-width, initial-scale=1.0">'
114
-
115
- # Author meta tag
116
- if @options[:author]
117
- author = escape_attr(@options[:author])
118
- meta << %( <meta name="author" content="#{author}">)
119
- end
120
-
121
- # Description meta tag
122
- if @options[:description]
123
- description = escape_attr(@options[:description])
124
- meta << %( <meta name="description" content="#{description}">)
125
- end
126
-
127
- # Keywords meta tag
128
- if @options[:keywords]
129
- keywords = escape_attr(@options[:keywords])
130
- meta << %( <meta name="keywords" content="#{keywords}">)
131
- end
132
-
133
- # Generator meta tag with version
134
- meta << %( <meta name="generator" content="Coradoc #{Coradoc::VERSION}">)
135
-
136
- # Generation timestamp
137
- meta << %( <meta name="generated" content="#{Time.now.utc.iso8601}">)
138
-
139
- # Custom meta tags
140
- if @options[:meta_tags].is_a?(Hash)
141
- @options[:meta_tags].each do |name, content|
142
- meta << %( <meta name="#{escape_attr(name)}" content="#{escape_attr(content)}">)
143
- end
144
- end
145
-
146
- meta.join("\n")
147
- end
148
-
149
- # Build title tag
150
- #
151
- # @return [String] Title tag HTML
152
- def build_title_tag
153
- title = extract_document_title
154
- " <title>#{escape_html(title)}</title>"
155
- end
156
-
157
- # Extract document title
158
- #
159
- # @return [String] Document title
160
- def extract_document_title
161
- if @document.is_a?(Coradoc::CoreModel::StructuralElement) && @document.title
162
- title = @document.title
163
- return title if title.is_a?(String)
164
- return title.text if title.is_a?(Coradoc::CoreModel::Base) && title.text
165
-
166
- return title.to_s
167
- end
168
-
169
- 'Untitled Document'
170
- end
171
-
172
- # Extract text from content (array of inline elements)
173
- #
174
- # @param content [Array] Content elements
175
- # @return [String] Extracted text
176
- def extract_text_from_content(content)
177
- case content
178
- when Array
179
- content.map { |item| extract_text_from_content(item) }.join
180
- when String
181
- content
182
- when Coradoc::CoreModel::InlineElement
183
- content.text
184
- else
185
- content.to_s
186
- end
187
- end
188
-
189
- # Build body classes
190
- #
191
- # @return [String] Body class attribute
192
- def build_body_classes
193
- classes = []
194
- classes << "theme-#{theme_name}"
195
-
196
- classes.empty? ? '' : %( class="#{classes.join(' ')}")
197
- end
198
-
199
- # Build CSS tags
200
- #
201
- # @return [String] CSS link or style tags
202
- def build_css_tags
203
- ''
204
- end
205
-
206
- # Build script tags
207
- #
208
- # @return [String] Script tags
209
- def build_script_tags
210
- ''
211
- end
212
-
213
- # Escape HTML content
214
- #
215
- # @param text [String] Text to escape
216
- # @return [String] Escaped text
217
- def escape_html(text)
218
- Coradoc::Html::Base.escape_html(text.to_s)
219
- end
220
-
221
- # Escape HTML attribute value
222
- #
223
- # @param value [String] Value to escape
224
- # @return [String] Escaped value
225
- def escape_attr(value)
226
- value.to_s.gsub('"', '&quot;').gsub('<', '&lt;').gsub('>', '&gt;')
227
- end
228
- end
229
- end
230
- end
231
- end