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.
Files changed (225) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/Rakefile +3 -12
  4. data/exe/coradoc +21 -2
  5. data/lib/coradoc/cli.rb +185 -91
  6. data/lib/coradoc/configurable.rb +527 -0
  7. data/lib/coradoc/coradoc.rb +463 -0
  8. data/lib/coradoc/core_model/annotation_block.rb +57 -0
  9. data/lib/coradoc/core_model/base.rb +172 -0
  10. data/lib/coradoc/core_model/bibliography.rb +41 -0
  11. data/lib/coradoc/core_model/bibliography_entry.rb +48 -0
  12. data/lib/coradoc/core_model/block.rb +63 -0
  13. data/lib/coradoc/core_model/children_content.rb +53 -0
  14. data/lib/coradoc/core_model/comment_block.rb +10 -0
  15. data/lib/coradoc/core_model/definition_item.rb +46 -0
  16. data/lib/coradoc/core_model/definition_list.rb +28 -0
  17. data/lib/coradoc/core_model/element_attribute.rb +26 -0
  18. data/lib/coradoc/core_model/example_block.rb +10 -0
  19. data/lib/coradoc/core_model/footnote.rb +92 -0
  20. data/lib/coradoc/core_model/horizontal_rule_block.rb +10 -0
  21. data/lib/coradoc/core_model/id_generator.rb +16 -0
  22. data/lib/coradoc/core_model/image.rb +66 -0
  23. data/lib/coradoc/core_model/inline_element.rb +140 -0
  24. data/lib/coradoc/core_model/list_block.rb +135 -0
  25. data/lib/coradoc/core_model/list_item.rb +142 -0
  26. data/lib/coradoc/core_model/listing_block.rb +13 -0
  27. data/lib/coradoc/core_model/literal_block.rb +10 -0
  28. data/lib/coradoc/core_model/metadata.rb +79 -0
  29. data/lib/coradoc/core_model/open_block.rb +10 -0
  30. data/lib/coradoc/core_model/paragraph_block.rb +10 -0
  31. data/lib/coradoc/core_model/pass_block.rb +10 -0
  32. data/lib/coradoc/core_model/quote_block.rb +12 -0
  33. data/lib/coradoc/core_model/reviewer_block.rb +10 -0
  34. data/lib/coradoc/core_model/sidebar_block.rb +10 -0
  35. data/lib/coradoc/core_model/source_block.rb +10 -0
  36. data/lib/coradoc/core_model/structural_element.rb +94 -0
  37. data/lib/coradoc/core_model/table.rb +148 -0
  38. data/lib/coradoc/core_model/term.rb +53 -0
  39. data/lib/coradoc/core_model/text_content.rb +22 -0
  40. data/lib/coradoc/core_model/toc.rb +105 -0
  41. data/lib/coradoc/core_model/toc_generator.rb +151 -0
  42. data/lib/coradoc/core_model/verse_block.rb +12 -0
  43. data/lib/coradoc/core_model.rb +77 -0
  44. data/lib/coradoc/document_builder.rb +184 -0
  45. data/lib/coradoc/document_manipulator.rb +203 -0
  46. data/lib/coradoc/errors.rb +312 -0
  47. data/lib/coradoc/format_module.rb +49 -0
  48. data/lib/coradoc/hooks.rb +176 -0
  49. data/lib/coradoc/input.rb +17 -7
  50. data/lib/coradoc/logger.rb +54 -0
  51. data/lib/coradoc/output.rb +17 -6
  52. data/lib/coradoc/performance_regression.rb +109 -0
  53. data/lib/coradoc/processor_registry.rb +50 -0
  54. data/lib/coradoc/query.rb +455 -0
  55. data/lib/coradoc/registry.rb +156 -0
  56. data/lib/coradoc/serializer/registry.rb +150 -0
  57. data/lib/coradoc/transform.rb +11 -0
  58. data/lib/coradoc/validation.rb +646 -0
  59. data/lib/coradoc/version.rb +1 -1
  60. data/lib/coradoc/visitor.rb +283 -0
  61. data/lib/coradoc.rb +40 -19
  62. metadata +67 -277
  63. data/.editorconfig +0 -15
  64. data/.envrc +0 -1
  65. data/.irbrc +0 -1
  66. data/.pryrc.sample +0 -1
  67. data/.rubocop.yml +0 -14
  68. data/.rubocop_todo.yml +0 -179
  69. data/CHANGELOG.md +0 -9
  70. data/CODE_OF_CONDUCT.md +0 -84
  71. data/Dockerfile +0 -19
  72. data/Gemfile +0 -16
  73. data/LICENSE.txt +0 -21
  74. data/Makefile +0 -35
  75. data/README.Docker.adoc +0 -57
  76. data/README.adoc +0 -119
  77. data/coradoc.gemspec +0 -40
  78. data/docker-compose.yml +0 -14
  79. data/exe/reverse_adoc +0 -81
  80. data/exe/w2a +0 -60
  81. data/flake.lock +0 -114
  82. data/flake.nix +0 -135
  83. data/lib/coradoc/converter.rb +0 -144
  84. data/lib/coradoc/document.rb +0 -77
  85. data/lib/coradoc/element/admonition.rb +0 -18
  86. data/lib/coradoc/element/attribute.rb +0 -36
  87. data/lib/coradoc/element/attribute_list.rb +0 -138
  88. data/lib/coradoc/element/audio.rb +0 -33
  89. data/lib/coradoc/element/author.rb +0 -24
  90. data/lib/coradoc/element/base.rb +0 -92
  91. data/lib/coradoc/element/bibliography.rb +0 -24
  92. data/lib/coradoc/element/bibliography_entry.rb +0 -24
  93. data/lib/coradoc/element/block/core.rb +0 -76
  94. data/lib/coradoc/element/block/example.rb +0 -23
  95. data/lib/coradoc/element/block/listing.rb +0 -21
  96. data/lib/coradoc/element/block/literal.rb +0 -21
  97. data/lib/coradoc/element/block/open.rb +0 -22
  98. data/lib/coradoc/element/block/pass.rb +0 -21
  99. data/lib/coradoc/element/block/quote.rb +0 -19
  100. data/lib/coradoc/element/block/reviewer_comment.rb +0 -19
  101. data/lib/coradoc/element/block/side.rb +0 -19
  102. data/lib/coradoc/element/block/sourcecode.rb +0 -21
  103. data/lib/coradoc/element/block.rb +0 -17
  104. data/lib/coradoc/element/break.rb +0 -11
  105. data/lib/coradoc/element/comment_block.rb +0 -22
  106. data/lib/coradoc/element/comment_line.rb +0 -18
  107. data/lib/coradoc/element/document_attributes.rb +0 -33
  108. data/lib/coradoc/element/header.rb +0 -22
  109. data/lib/coradoc/element/image/block_image.rb +0 -32
  110. data/lib/coradoc/element/image/core.rb +0 -58
  111. data/lib/coradoc/element/image/inline_image.rb +0 -12
  112. data/lib/coradoc/element/image.rb +0 -10
  113. data/lib/coradoc/element/include.rb +0 -18
  114. data/lib/coradoc/element/inline/anchor.rb +0 -19
  115. data/lib/coradoc/element/inline/attribute_reference.rb +0 -19
  116. data/lib/coradoc/element/inline/bold.rb +0 -25
  117. data/lib/coradoc/element/inline/cross_reference.rb +0 -46
  118. data/lib/coradoc/element/inline/footnote.rb +0 -24
  119. data/lib/coradoc/element/inline/hard_line_break.rb +0 -11
  120. data/lib/coradoc/element/inline/highlight.rb +0 -25
  121. data/lib/coradoc/element/inline/italic.rb +0 -25
  122. data/lib/coradoc/element/inline/link.rb +0 -42
  123. data/lib/coradoc/element/inline/monospace.rb +0 -25
  124. data/lib/coradoc/element/inline/quotation.rb +0 -20
  125. data/lib/coradoc/element/inline/small.rb +0 -19
  126. data/lib/coradoc/element/inline/span.rb +0 -37
  127. data/lib/coradoc/element/inline/subscript.rb +0 -20
  128. data/lib/coradoc/element/inline/superscript.rb +0 -20
  129. data/lib/coradoc/element/inline/underline.rb +0 -19
  130. data/lib/coradoc/element/inline.rb +0 -23
  131. data/lib/coradoc/element/list/core.rb +0 -51
  132. data/lib/coradoc/element/list/definition.rb +0 -29
  133. data/lib/coradoc/element/list/ordered.rb +0 -17
  134. data/lib/coradoc/element/list/unordered.rb +0 -17
  135. data/lib/coradoc/element/list.rb +0 -13
  136. data/lib/coradoc/element/list_item.rb +0 -98
  137. data/lib/coradoc/element/list_item_definition.rb +0 -32
  138. data/lib/coradoc/element/paragraph.rb +0 -37
  139. data/lib/coradoc/element/revision.rb +0 -27
  140. data/lib/coradoc/element/section.rb +0 -62
  141. data/lib/coradoc/element/table.rb +0 -91
  142. data/lib/coradoc/element/tag.rb +0 -19
  143. data/lib/coradoc/element/term.rb +0 -22
  144. data/lib/coradoc/element/text_element.rb +0 -92
  145. data/lib/coradoc/element/title.rb +0 -62
  146. data/lib/coradoc/element/video.rb +0 -50
  147. data/lib/coradoc/generator.rb +0 -19
  148. data/lib/coradoc/input/adoc.rb +0 -30
  149. data/lib/coradoc/input/docx.rb +0 -64
  150. data/lib/coradoc/input/html/LICENSE.txt +0 -25
  151. data/lib/coradoc/input/html/README.adoc +0 -308
  152. data/lib/coradoc/input/html/cleaner.rb +0 -142
  153. data/lib/coradoc/input/html/config.rb +0 -77
  154. data/lib/coradoc/input/html/converters/a.rb +0 -52
  155. data/lib/coradoc/input/html/converters/aside.rb +0 -16
  156. data/lib/coradoc/input/html/converters/audio.rb +0 -29
  157. data/lib/coradoc/input/html/converters/base.rb +0 -108
  158. data/lib/coradoc/input/html/converters/blockquote.rb +0 -22
  159. data/lib/coradoc/input/html/converters/br.rb +0 -15
  160. data/lib/coradoc/input/html/converters/bypass.rb +0 -81
  161. data/lib/coradoc/input/html/converters/code.rb +0 -23
  162. data/lib/coradoc/input/html/converters/div.rb +0 -19
  163. data/lib/coradoc/input/html/converters/dl.rb +0 -62
  164. data/lib/coradoc/input/html/converters/drop.rb +0 -26
  165. data/lib/coradoc/input/html/converters/em.rb +0 -21
  166. data/lib/coradoc/input/html/converters/figure.rb +0 -25
  167. data/lib/coradoc/input/html/converters/h.rb +0 -42
  168. data/lib/coradoc/input/html/converters/head.rb +0 -23
  169. data/lib/coradoc/input/html/converters/hr.rb +0 -15
  170. data/lib/coradoc/input/html/converters/ignore.rb +0 -20
  171. data/lib/coradoc/input/html/converters/img.rb +0 -110
  172. data/lib/coradoc/input/html/converters/li.rb +0 -17
  173. data/lib/coradoc/input/html/converters/mark.rb +0 -19
  174. data/lib/coradoc/input/html/converters/markup.rb +0 -31
  175. data/lib/coradoc/input/html/converters/math.rb +0 -38
  176. data/lib/coradoc/input/html/converters/ol.rb +0 -65
  177. data/lib/coradoc/input/html/converters/p.rb +0 -23
  178. data/lib/coradoc/input/html/converters/pass_through.rb +0 -17
  179. data/lib/coradoc/input/html/converters/pre.rb +0 -55
  180. data/lib/coradoc/input/html/converters/q.rb +0 -16
  181. data/lib/coradoc/input/html/converters/strong.rb +0 -20
  182. data/lib/coradoc/input/html/converters/sub.rb +0 -22
  183. data/lib/coradoc/input/html/converters/sup.rb +0 -22
  184. data/lib/coradoc/input/html/converters/table.rb +0 -319
  185. data/lib/coradoc/input/html/converters/td.rb +0 -81
  186. data/lib/coradoc/input/html/converters/text.rb +0 -32
  187. data/lib/coradoc/input/html/converters/th.rb +0 -18
  188. data/lib/coradoc/input/html/converters/tr.rb +0 -22
  189. data/lib/coradoc/input/html/converters/video.rb +0 -29
  190. data/lib/coradoc/input/html/converters.rb +0 -59
  191. data/lib/coradoc/input/html/errors.rb +0 -14
  192. data/lib/coradoc/input/html/html_converter.rb +0 -168
  193. data/lib/coradoc/input/html/plugin.rb +0 -131
  194. data/lib/coradoc/input/html/plugins/plateau.rb +0 -213
  195. data/lib/coradoc/input/html/postprocessor.rb +0 -220
  196. data/lib/coradoc/input/html.rb +0 -61
  197. data/lib/coradoc/legacy_parser.rb +0 -200
  198. data/lib/coradoc/oscal.rb +0 -99
  199. data/lib/coradoc/output/adoc.rb +0 -19
  200. data/lib/coradoc/output/coradoc_tree_debug.rb +0 -21
  201. data/lib/coradoc/parser/asciidoc/admonition.rb +0 -24
  202. data/lib/coradoc/parser/asciidoc/attribute_list.rb +0 -89
  203. data/lib/coradoc/parser/asciidoc/base.rb +0 -87
  204. data/lib/coradoc/parser/asciidoc/bibliography.rb +0 -29
  205. data/lib/coradoc/parser/asciidoc/block.rb +0 -94
  206. data/lib/coradoc/parser/asciidoc/citation.rb +0 -30
  207. data/lib/coradoc/parser/asciidoc/content.rb +0 -64
  208. data/lib/coradoc/parser/asciidoc/document_attributes.rb +0 -25
  209. data/lib/coradoc/parser/asciidoc/header.rb +0 -29
  210. data/lib/coradoc/parser/asciidoc/inline.rb +0 -195
  211. data/lib/coradoc/parser/asciidoc/list.rb +0 -115
  212. data/lib/coradoc/parser/asciidoc/paragraph.rb +0 -54
  213. data/lib/coradoc/parser/asciidoc/section.rb +0 -61
  214. data/lib/coradoc/parser/asciidoc/table.rb +0 -32
  215. data/lib/coradoc/parser/asciidoc/term.rb +0 -41
  216. data/lib/coradoc/parser/asciidoc/text.rb +0 -158
  217. data/lib/coradoc/parser/base.rb +0 -40
  218. data/lib/coradoc/parser.rb +0 -11
  219. data/lib/coradoc/reverse_adoc.rb +0 -18
  220. data/lib/coradoc/transformer.rb +0 -476
  221. data/lib/coradoc/util.rb +0 -12
  222. data/lib/reverse_adoc.rb +0 -20
  223. data/utils/inspect_asciidoc.rb +0 -29
  224. data/utils/parser_analyzer.rb +0 -66
  225. data/utils/round_trip.rb +0 -53
@@ -1,31 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Markup < Base
6
- def to_coradoc(node, state = {})
7
- u_before = unconstrained_before?(node)
8
- u_after = unconstrained_after?(node)
9
-
10
- leading_whitespace, trailing_whitespace =
11
- extract_leading_trailing_whitespace(node)
12
-
13
- content = treat_children_coradoc(node, state)
14
-
15
- if node_has_ancestor?(node, markup_ancestor_tag_names)
16
- content
17
- elsif node.children.empty?
18
- leading_whitespace.to_s
19
- else
20
- u = (u_before && leading_whitespace.nil?) ||
21
- (u_after && trailing_whitespace.nil?)
22
-
23
- e = coradoc_class.new(content, unconstrained: u)
24
- [leading_whitespace, e, trailing_whitespace]
25
- end
26
- end
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,38 +0,0 @@
1
- # Unless run with Coradoc::Input::HTML.config.mathml2asciimath,
2
- # this is cheating: we're injecting MathML into Asciidoctor, but
3
- # Asciidoctor only understands AsciiMath or LaTeX
4
-
5
- require "plurimath"
6
-
7
- module Coradoc
8
- module Input
9
- module Html
10
- module Converters
11
- class Math < Base
12
- # FIXIT
13
- def to_coradoc(node, state = {})
14
- convert(node, state)
15
- end
16
-
17
- def convert(node, _state = {})
18
- stem = node.to_s.tr("\n", " ")
19
- if Coradoc::Input::Html.config.mathml2asciimath
20
- stem = Plurimath::Math.parse(stem, :mathml).to_asciimath
21
- end
22
-
23
- unless stem.nil?
24
- stem = stem.gsub(/\[/, "\\[").gsub(/\]/, "\\]").gsub(
25
- /\(\(([^\)]+)\)\)/, "(\\1)"
26
- )
27
- end
28
-
29
- # TODO: This is to be done in Coradoc
30
- " stem:[" << stem << "] "
31
- end
32
- end
33
-
34
- register :math, Math.new
35
- end
36
- end
37
- end
38
- end
@@ -1,65 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Ol < Base
6
- # FIXIT
7
- def to_coradoc(node, state = {})
8
- # convert(node, state)
9
- id = node["id"]
10
- ol_count = state.fetch(:ol_count, 0) + 1
11
- attrs = ol_attrs(node)
12
- items = treat_children_coradoc(node,
13
- state.merge(ol_count: ol_count))
14
-
15
- options = {}.tap do |hash|
16
- hash[:id] = id
17
- hash[:ol_count] = ol_count
18
- hash[:attrs] = attrs
19
- end
20
-
21
- case get_list_type(node, state)
22
- when :ordered
23
- Coradoc::Element::List::Ordered.new(items, options)
24
- when :unordered
25
- Coradoc::Element::List::Unordered.new(items, options)
26
- end
27
- end
28
-
29
- def get_list_type(node, _state)
30
- case node.name
31
- when "ol"
32
- :ordered
33
- when "ul"
34
- :unordered
35
- end
36
- end
37
-
38
- def number_style(node)
39
- case node["style"]
40
- when "1" then "arabic"
41
- when "A" then "upperalpha"
42
- when "a" then "loweralpha"
43
- when "I" then "upperroman"
44
- when "i" then "lowerroman"
45
- end
46
- end
47
-
48
- def ol_attrs(node)
49
- attrs = Coradoc::Element::AttributeList.new
50
- style = number_style(node)
51
- attrs.add_positional(style) if style
52
- attrs.add_positional("%reversed") if node["reversed"]
53
- attrs.add_named("start", node["start"]) if node["start"]
54
- attrs.add_named("type", node["type"]) if node["type"]
55
- attrs
56
- end
57
- end
58
-
59
- register :ol, Ol.new
60
- register :ul, Ol.new
61
- register :dir, Ol.new
62
- end
63
- end
64
- end
65
- end
@@ -1,23 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class P < Base
6
- def to_coradoc(node, state = {})
7
- id = node["id"]
8
- content = treat_children_coradoc(node, state)
9
-
10
- options = {}.tap do |hash|
11
- hash[:id] = id if id
12
- hash[:tdsinglepara] = true if state[:tdsinglepara]
13
- end
14
-
15
- Coradoc::Element::Paragraph.new(content, options)
16
- end
17
- end
18
-
19
- register :p, P.new
20
- end
21
- end
22
- end
23
- end
@@ -1,17 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class PassThrough < Base
6
- def to_coradoc(node, _state = {})
7
- node.to_s
8
- end
9
-
10
- def convert(node, state = {})
11
- to_coradoc(node, state)
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,55 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Pre < Base
6
- def to_coradoc(node, state = {})
7
- id = node["id"]
8
- lang = language(node)
9
- content = treat_children(node, state)
10
-
11
- unless lang
12
- return Coradoc::Element::Block::Literal.new(
13
- nil,
14
- lines: content,
15
- id: id,
16
- )
17
- end
18
-
19
- Coradoc::Element::Block::SourceCode.new(
20
- nil,
21
- lines: content,
22
- lang: lang,
23
- id: id,
24
- )
25
- end
26
-
27
- private
28
-
29
- def treat(node, _state)
30
- return "\n" if node.name == "br"
31
-
32
- prefix = postfix = "\n\n" if node.name == "p"
33
-
34
- "#{prefix}#{node.text}#{postfix}"
35
- end
36
-
37
- def language(node)
38
- lang = language_from_highlight_class(node)
39
- lang || language_from_confluence_class(node)
40
- end
41
-
42
- def language_from_highlight_class(node)
43
- node.parent["class"].to_s[/highlight-([a-zA-Z0-9]+)/, 1]
44
- end
45
-
46
- def language_from_confluence_class(node)
47
- node["class"].to_s[/brush:\s?(:?.*);/, 1]
48
- end
49
- end
50
-
51
- register :pre, Pre.new
52
- end
53
- end
54
- end
55
- end
@@ -1,16 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Q < Base
6
- def to_coradoc(node, state = {})
7
- content = treat_children(node, state)
8
- Coradoc::Element::Inline::Quotation.new(content)
9
- end
10
- end
11
-
12
- register :q, Q.new
13
- end
14
- end
15
- end
16
- end
@@ -1,20 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Strong < Markup
6
- def coradoc_class
7
- Coradoc::Element::Inline::Bold
8
- end
9
-
10
- def markup_ancestor_tag_names
11
- %w[strong b]
12
- end
13
- end
14
-
15
- register :strong, Strong.new
16
- register :b, Strong.new
17
- end
18
- end
19
- end
20
- end
@@ -1,22 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Sub < Base
6
- def to_coradoc(node, state = {})
7
- leading_whitespace, trailing_whitespace = extract_leading_trailing_whitespace(node)
8
-
9
- content = treat_children_coradoc(node, state)
10
-
11
- return content if Coradoc::Generator.gen_adoc(content).strip.empty?
12
-
13
- e = Coradoc::Element::Inline::Subscript.new(content)
14
- [leading_whitespace, e, trailing_whitespace]
15
- end
16
- end
17
-
18
- register :sub, Sub.new
19
- end
20
- end
21
- end
22
- end
@@ -1,22 +0,0 @@
1
- module Coradoc
2
- module Input
3
- module Html
4
- module Converters
5
- class Sup < Base
6
- def to_coradoc(node, state = {})
7
- leading_whitespace, trailing_whitespace = extract_leading_trailing_whitespace(node)
8
-
9
- content = treat_children_coradoc(node, state)
10
-
11
- return content if Coradoc::Generator.gen_adoc(content).strip.empty?
12
-
13
- e = Coradoc::Element::Inline::Superscript.new(content)
14
- [leading_whitespace, e, trailing_whitespace]
15
- end
16
- end
17
-
18
- register :sup, Sup.new
19
- end
20
- end
21
- end
22
- end
@@ -1,319 +0,0 @@
1
- module Coradoc::Input
2
- module Html
3
- module Converters
4
- class Table < Base
5
- def to_coradoc(node, state = {})
6
- id = node["id"]
7
- title = extract_title(node)
8
- attributes = style(node)
9
- content = treat_children_coradoc(node, state)
10
- Coradoc::Element::Table.new(title, content, { id: id, attributes: attributes })
11
- end
12
-
13
- def extract_title(node)
14
- title = node.at("./caption")
15
- return "" if title.nil?
16
-
17
- treat_children(title, {})
18
- end
19
-
20
- def frame(node)
21
- case node["frame"]
22
- when "void"
23
- "none"
24
- when "hsides"
25
- "topbot"
26
- when "vsides"
27
- "sides"
28
- when "box", "border"
29
- "all"
30
- end
31
- end
32
-
33
- def rules(node)
34
- case node["rules"]
35
- when "all"
36
- "all"
37
- when "rows"
38
- "rows"
39
- when "cols"
40
- "cols"
41
- when "none"
42
- "none"
43
- end
44
- end
45
-
46
- def style(node)
47
- attrs = Coradoc::Element::AttributeList.new
48
- # Width is disabled on tables for now. (From #88)
49
- # attrs.add_named("width", node["width"]) if node["width"]
50
-
51
- frame_attr = frame(node)
52
- attrs.add_named("frame", frame_attr) if frame_attr
53
-
54
- rules_attr = rules(node)
55
- attrs.add_named("rules", rules_attr) if rules_attr
56
-
57
- # We can't, and shouldn't do those calculation if the table we are
58
- # processing is empty.
59
- unless empty?(node)
60
- cols = ensure_row_column_integrity_and_get_column_sizes(node)
61
- attrs.add_named("cols", cols)
62
-
63
- # Header first rows can't span multiple riws - drop header if they do.
64
- header = node.at_xpath(".//tr")
65
- unless header.xpath("./td | ./th").all? { |i|
66
- [nil, "1", ""].include? i["rowspan"] }
67
- attrs.add_named("options", ["noheader"])
68
- end
69
- end
70
-
71
- # This line should be removed.
72
- return "" if attrs.empty?
73
-
74
- attrs
75
- end
76
-
77
- def empty?(node)
78
- !node.at_xpath(".//td | .//th")
79
- end
80
-
81
- def ensure_row_column_integrity_and_get_column_sizes(node)
82
- rows = node.xpath(".//tr")
83
- num_rows = rows.length
84
- computed_columns_per_row = [0] * num_rows
85
- # Both those variables may seem the same, but they have a crucial
86
- # difference.
87
- #
88
- # cell_references don't necessarily contain an image of created
89
- # table. New cells are pushed to it as needed, so if we have a
90
- # one cell with colspan and rowspan of 2 on the previous row,
91
- # those will always be first in the row, regardless of their
92
- # position. This array is only used to warrant the table
93
- # integrity.
94
- #
95
- # cell_matrix, on the other hand, can't be constructed outright.
96
- # It will be incorrect as long as the table isn't fixed. So we
97
- # can't use it to correct colspans/rowspans/missing rows. Once
98
- # we have it constructed, only then we can calculate the correct
99
- # column widths.
100
- cell_references = [nil] * num_rows
101
- cell_matrix = [nil] * num_rows
102
-
103
- recompute = proc do
104
- return ensure_row_column_integrity_and_get_column_sizes(node)
105
- end
106
-
107
- fits_in_cell_matrix = proc do |y, x, rowspan, colspan|
108
- rowspan.times.all? do |yy|
109
- colspan.times.all? do |xx|
110
- !cell_matrix.dig(y + yy, x + xx)
111
- end
112
- end
113
- end
114
-
115
- rows.each_with_index do |row, i|
116
- columns = row.xpath("./td | ./th")
117
- column_id = 0
118
-
119
- cell_references[i] ||= []
120
- cell_matrix[i] ||= []
121
-
122
- # Empty row support: pass row object via an instance variable
123
- cell_references[i].instance_variable_set(:@row_obj, row)
124
-
125
- columns.each do |cell|
126
- colspan = cell["colspan"]&.to_i || 1
127
- rowspan = cell["rowspan"]&.to_i || 1
128
-
129
- column_id += 1 until fits_in_cell_matrix.(i, column_id, rowspan,
130
- colspan)
131
-
132
- rowspan.times do |j|
133
- # Let's increase the table for particularly bad documents
134
- computed_columns_per_row[i + j] ||= 0
135
- computed_columns_per_row[i + j] += colspan
136
-
137
- cell_references[i + j] ||= []
138
- cell_matrix[i + j] ||= []
139
- colspan.times do |k|
140
- cell_references[i + j] << [cell, k.positive?]
141
- cell_matrix[i + j][column_id] = cell
142
- column_id += 1
143
- end
144
- column_id -= colspan
145
- end
146
- column_id += colspan
147
- end
148
- end
149
-
150
- ##### Fixups
151
- cpr = computed_columns_per_row
152
-
153
- # Some cell has too high colspan
154
- if cpr.length > num_rows
155
- cell_references[num_rows].each do |cell,|
156
- next unless cell
157
-
158
- cell["rowspan"] = cell["rowspan"].to_i - 1
159
- end
160
-
161
- # Let's recompute the numbers
162
- recompute.()
163
- end
164
-
165
- if [cpr.first] * num_rows != cpr
166
- # Colspan inconsistencies
167
- modified = false
168
- cpr_max = cpr.max
169
- max_rows = cell_references.sort_by(&:length).reverse
170
- max_rows.each do |row|
171
- break if row.length != cpr_max
172
-
173
- cell, spanning = row.last
174
-
175
- if spanning
176
- modified = true
177
- cell["colspan"] = cell["colspan"].to_i - 1
178
- end
179
- end
180
-
181
- recompute.() if modified
182
-
183
- # We are out of colspans to fix. If we are at this point, this
184
- # means there is an inconsistent number of TH/TDs simply.
185
- # Here, the solution is to add empty TDs.
186
- min_rows = cell_references.sort_by(&:length)
187
- cpr_min = cpr.min
188
- min_rows.each do |row|
189
- break if row.length != cpr_min
190
-
191
- row_obj = row.last&.first&.parent || row.instance_variable_get(:@row_obj)
192
- doc = row_obj.document
193
- added_node = Nokogiri::XML::Node.new("td", doc)
194
- added_node["x-added"] = "x-added"
195
- row_obj.add_child(added_node)
196
-
197
- modified = true
198
- end
199
-
200
- recompute.() if modified
201
-
202
- ### We should have a correct document now and we should never
203
- ### end up here.
204
- warn "**** Couldn't fix table sizes for table on line #{node.line}"
205
- end
206
-
207
- # For column size computation, we must have an integral cell_matrix.
208
- # Let's verify that all columns and rows are populated.
209
- cell_matrix_correct = cell_matrix.length.times.all? do |y|
210
- cell_matrix[y].length.times.all? do |x|
211
- cell_matrix[y][x]
212
- end
213
- end
214
-
215
- unless cell_matrix_correct
216
- # It may be a special case that we need to add virtual cells at the
217
- # beginning not the end of a row.
218
- needs_recompute = false
219
- cell_matrix.each do |row|
220
- if row.compact.length != row.length
221
- last_cell = row.last
222
- if last_cell["x-added"]
223
- last_cell.parent.prepend_child(last_cell)
224
- needs_recompute = true
225
- end
226
- end
227
- end
228
- recompute.() if needs_recompute
229
-
230
- # But otherwise... we've got a really nasty table.
231
- warn <<~WARNING.tr("\n", " ")
232
- **** Couldn't construct a valid image of a table on line
233
- #{node.line}. We need that to reliably compute column
234
- widths of that table. Please report a bug to metanorma/coradoc
235
- repository.
236
- WARNING
237
- end
238
-
239
- # Compute column sizes
240
- column_sizes = []
241
- cell_matrix.each do |row|
242
- row.each_with_index do |(cell, _), i|
243
- next unless !cell || [nil, "", "1"].include?(cell["colspan"])
244
-
245
- column_sizes[i] ||= []
246
- column_sizes[i] << cell["width"]
247
- end
248
- end
249
-
250
- document_width = Coradoc::Input::Html.config.doc_width.to_r
251
-
252
- column_sizes += [nil] * (cpr.first - column_sizes.length)
253
-
254
- sizes = column_sizes.map do |col|
255
- col = [] if col.nil?
256
-
257
- max = col.map do |i|
258
- if i.nil?
259
- 0r
260
- elsif i.end_with?("%")
261
- document_width * i.to_i / 100
262
- else
263
- i.to_r
264
- end
265
- end.max
266
-
267
- if max.nil? || max.negative?
268
- 0r
269
- else
270
- max
271
- end
272
- end
273
-
274
- # The table seems bigger than the document... let's scale all
275
- # values.
276
- while sizes.map { |i|
277
- if i.zero?
278
- document_width / 3 / sizes.length
279
- else
280
- i
281
- end
282
- }.sum > document_width
283
-
284
- sizes = sizes.map { |i| i * 4 / 5 }
285
- end
286
-
287
- rest = document_width - sizes.sum
288
- unset = sizes.count(&:zero?)
289
-
290
- # Fill in zeros with remainder space
291
- sizes = sizes.map do |i|
292
- if i.zero?
293
- rest / unset
294
- else
295
- i
296
- end
297
- end
298
-
299
- # Scale to integers
300
- lcm = sizes.map(&:denominator).inject(1) { |i, j| i.lcm(j) }
301
- sizes = sizes.map { |i| i * lcm }.map(&:to_i)
302
-
303
- # Scale down by gcd
304
- gcd = sizes.inject(sizes.first) { |i, j| i.gcd(j) }
305
- sizes = sizes.map { |i| i / gcd }
306
-
307
- # Try to generate a shorter definition
308
- if [sizes.first] * sizes.length == sizes
309
- sizes.length
310
- else
311
- sizes.join(",")
312
- end
313
- end
314
- end
315
-
316
- register :table, Table.new
317
- end
318
- end
319
- end