coradoc 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.docker/Dockerfile +1 -1
  3. data/.docker/docker-compose.yml +2 -2
  4. data/.editorconfig +15 -0
  5. data/CHANGELOG.md +4 -0
  6. data/README.md +4 -0
  7. data/Rakefile +10 -0
  8. data/coradoc.gemspec +11 -2
  9. data/exe/reverse_adoc +91 -0
  10. data/exe/w2a +72 -0
  11. data/lib/coradoc/document.rb +6 -6
  12. data/lib/coradoc/element/admonition.rb +8 -6
  13. data/lib/coradoc/element/attribute.rb +2 -2
  14. data/lib/coradoc/element/attribute_list.rb +94 -15
  15. data/lib/coradoc/element/audio.rb +14 -3
  16. data/lib/coradoc/element/author.rb +18 -14
  17. data/lib/coradoc/element/base.rb +69 -8
  18. data/lib/coradoc/element/block/core.rb +10 -6
  19. data/lib/coradoc/element/block/literal.rb +1 -1
  20. data/lib/coradoc/element/block/quote.rb +1 -1
  21. data/lib/coradoc/element/block/sourcecode.rb +2 -2
  22. data/lib/coradoc/element/break.rb +1 -1
  23. data/lib/coradoc/element/document_attributes.rb +6 -6
  24. data/lib/coradoc/element/header.rb +4 -2
  25. data/lib/coradoc/element/image/block_image.rb +13 -2
  26. data/lib/coradoc/element/image/core.rb +35 -5
  27. data/lib/coradoc/element/image/inline_image.rb +2 -2
  28. data/lib/coradoc/element/image.rb +0 -1
  29. data/lib/coradoc/element/inline/anchor.rb +4 -2
  30. data/lib/coradoc/element/inline/bold.rb +10 -4
  31. data/lib/coradoc/element/inline/cross_reference.rb +4 -2
  32. data/lib/coradoc/element/inline/hard_line_break.rb +1 -1
  33. data/lib/coradoc/element/inline/highlight.rb +12 -6
  34. data/lib/coradoc/element/inline/italic.rb +10 -4
  35. data/lib/coradoc/element/inline/link.rb +26 -10
  36. data/lib/coradoc/element/inline/monospace.rb +10 -4
  37. data/lib/coradoc/element/inline/quotation.rb +4 -1
  38. data/lib/coradoc/element/inline/subscript.rb +5 -2
  39. data/lib/coradoc/element/inline/superscript.rb +5 -2
  40. data/lib/coradoc/element/inline.rb +0 -1
  41. data/lib/coradoc/element/list/core.rb +10 -8
  42. data/lib/coradoc/element/list/definition.rb +19 -0
  43. data/lib/coradoc/element/list/ordered.rb +1 -1
  44. data/lib/coradoc/element/list/unordered.rb +1 -1
  45. data/lib/coradoc/element/list.rb +1 -1
  46. data/lib/coradoc/element/list_item.rb +9 -4
  47. data/lib/coradoc/element/list_item_definition.rb +32 -0
  48. data/lib/coradoc/element/paragraph.rb +5 -3
  49. data/lib/coradoc/element/revision.rb +20 -16
  50. data/lib/coradoc/element/section.rb +21 -4
  51. data/lib/coradoc/element/table.rb +36 -19
  52. data/lib/coradoc/element/text_element.rb +63 -17
  53. data/lib/coradoc/element/title.rb +27 -7
  54. data/lib/coradoc/element/video.rb +33 -6
  55. data/lib/coradoc/generator.rb +2 -2
  56. data/lib/coradoc/legacy_parser.rb +41 -41
  57. data/lib/coradoc/oscal.rb +2 -4
  58. data/lib/coradoc/parser/asciidoc/content.rb +15 -15
  59. data/lib/coradoc/parser/asciidoc/document_attributes.rb +1 -1
  60. data/lib/coradoc/parser/asciidoc/header.rb +6 -6
  61. data/lib/coradoc/parser/asciidoc/section.rb +1 -1
  62. data/lib/coradoc/reverse_adoc/LICENSE.txt +25 -0
  63. data/lib/coradoc/reverse_adoc/README.adoc +308 -0
  64. data/lib/coradoc/reverse_adoc/cleaner.rb +125 -0
  65. data/lib/coradoc/reverse_adoc/config.rb +73 -0
  66. data/lib/coradoc/reverse_adoc/converters/a.rb +47 -0
  67. data/lib/coradoc/reverse_adoc/converters/aside.rb +12 -0
  68. data/lib/coradoc/reverse_adoc/converters/audio.rb +25 -0
  69. data/lib/coradoc/reverse_adoc/converters/base.rb +104 -0
  70. data/lib/coradoc/reverse_adoc/converters/blockquote.rb +18 -0
  71. data/lib/coradoc/reverse_adoc/converters/br.rb +11 -0
  72. data/lib/coradoc/reverse_adoc/converters/bypass.rb +77 -0
  73. data/lib/coradoc/reverse_adoc/converters/code.rb +19 -0
  74. data/lib/coradoc/reverse_adoc/converters/div.rb +14 -0
  75. data/lib/coradoc/reverse_adoc/converters/dl.rb +55 -0
  76. data/lib/coradoc/reverse_adoc/converters/drop.rb +22 -0
  77. data/lib/coradoc/reverse_adoc/converters/em.rb +17 -0
  78. data/lib/coradoc/reverse_adoc/converters/figure.rb +21 -0
  79. data/lib/coradoc/reverse_adoc/converters/h.rb +38 -0
  80. data/lib/coradoc/reverse_adoc/converters/head.rb +19 -0
  81. data/lib/coradoc/reverse_adoc/converters/hr.rb +11 -0
  82. data/lib/coradoc/reverse_adoc/converters/ignore.rb +16 -0
  83. data/lib/coradoc/reverse_adoc/converters/img.rb +98 -0
  84. data/lib/coradoc/reverse_adoc/converters/li.rb +13 -0
  85. data/lib/coradoc/reverse_adoc/converters/mark.rb +15 -0
  86. data/lib/coradoc/reverse_adoc/converters/markup.rb +27 -0
  87. data/lib/coradoc/reverse_adoc/converters/math.rb +31 -0
  88. data/lib/coradoc/reverse_adoc/converters/ol.rb +60 -0
  89. data/lib/coradoc/reverse_adoc/converters/p.rb +19 -0
  90. data/lib/coradoc/reverse_adoc/converters/pass_through.rb +13 -0
  91. data/lib/coradoc/reverse_adoc/converters/pre.rb +51 -0
  92. data/lib/coradoc/reverse_adoc/converters/q.rb +12 -0
  93. data/lib/coradoc/reverse_adoc/converters/strong.rb +16 -0
  94. data/lib/coradoc/reverse_adoc/converters/sub.rb +18 -0
  95. data/lib/coradoc/reverse_adoc/converters/sup.rb +18 -0
  96. data/lib/coradoc/reverse_adoc/converters/table.rb +280 -0
  97. data/lib/coradoc/reverse_adoc/converters/td.rb +77 -0
  98. data/lib/coradoc/reverse_adoc/converters/text.rb +28 -0
  99. data/lib/coradoc/reverse_adoc/converters/th.rb +14 -0
  100. data/lib/coradoc/reverse_adoc/converters/tr.rb +18 -0
  101. data/lib/coradoc/reverse_adoc/converters/video.rb +25 -0
  102. data/lib/coradoc/reverse_adoc/converters.rb +53 -0
  103. data/lib/coradoc/reverse_adoc/errors.rb +10 -0
  104. data/lib/coradoc/reverse_adoc/html_converter.rb +150 -0
  105. data/lib/coradoc/reverse_adoc/plugin.rb +131 -0
  106. data/lib/coradoc/reverse_adoc/plugins/plateau.rb +174 -0
  107. data/lib/coradoc/reverse_adoc/postprocessor.rb +148 -0
  108. data/lib/coradoc/reverse_adoc.rb +30 -0
  109. data/lib/coradoc/transformer.rb +24 -14
  110. data/lib/coradoc/version.rb +1 -1
  111. data/lib/reverse_adoc.rb +20 -0
  112. metadata +184 -5
  113. data/lib/coradoc/element/inline/image.rb +0 -25
@@ -0,0 +1,47 @@
1
+ require "coradoc"
2
+
3
+ module Coradoc::ReverseAdoc
4
+ module Converters
5
+ class A < Base
6
+ def to_coradoc(node, state = {})
7
+ name = treat_children(node, state)
8
+
9
+ href = node["href"]
10
+ title = extract_title(node)
11
+ id = node["id"] || node["name"]
12
+
13
+ id = id&.gsub(/\s/, "")&.gsub(/__+/, "_")
14
+ id = nil if id&.empty?
15
+
16
+ return "" if /^_Toc\d+$|^_GoBack$/.match?(id)
17
+
18
+ return Coradoc::Element::Inline::Anchor.new(id) if id
19
+
20
+ if href.to_s.start_with?("#")
21
+ href = href.sub(/^#/, "").gsub(/\s/, "").gsub(/__+/, "_")
22
+ return Coradoc::Element::Inline::CrossReference.new(href, name)
23
+ end
24
+
25
+ return name if href.to_s.empty?
26
+
27
+ ambigous_characters = /[\w.?&#=%;\[\u{ff}-\u{10ffff}]/
28
+ if name&.strip == href
29
+ name = ""
30
+ right_constrain = textnode_after_start_with?(node, ambigous_characters)
31
+ end
32
+
33
+ out = []
34
+ out << " " if textnode_before_end_with?(node, ambigous_characters)
35
+ out << Coradoc::Element::Inline::Link.new(
36
+ path: href,
37
+ name: name.strip,
38
+ title: title.strip,
39
+ right_constrain: right_constrain,
40
+ )
41
+ out
42
+ end
43
+ end
44
+
45
+ register :a, A.new
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Aside < Base
4
+ def to_coradoc(node, state = {})
5
+ content = treat_children(node, state)
6
+ Coradoc::Element::Block::Side.new(lines: content.lines)
7
+ end
8
+ end
9
+
10
+ register :aside, Aside.new
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Audio < Base
4
+ def to_coradoc(node, _state = {})
5
+ src = node["src"]
6
+ id = node["id"]
7
+ title = extract_title(node)
8
+ attributes = Coradoc::Element::AttributeList.new
9
+ options = options(node)
10
+ attributes.add_named("options", options) if options.any?
11
+ Coradoc::Element::Audio.new(title, id: id, src: src,
12
+ attributes: attributes)
13
+ end
14
+
15
+ def options(node)
16
+ autoplay = node["autoplay"]
17
+ loop_attr = node["loop"]
18
+ controls = node["controls"]
19
+ [autoplay, loop_attr, controls].compact
20
+ end
21
+ end
22
+
23
+ register :audio, Audio.new
24
+ end
25
+ end
@@ -0,0 +1,104 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Base
4
+ # Default implementation to convert a given Nokogiri node
5
+ # to an AsciiDoc script.
6
+ # Can be overriden by subclasses.
7
+ def convert(node, state = {})
8
+ Coradoc::Generator.gen_adoc(to_coradoc(node, state))
9
+ end
10
+
11
+ # Note: treat_children won't run plugin hooks
12
+ def treat_children(node, state)
13
+ node.children.inject("") do |memo, child|
14
+ memo << treat(child, state)
15
+ end
16
+ end
17
+
18
+ def treat(node, state)
19
+ Converters.process(node, state)
20
+ end
21
+
22
+ def treat_children_coradoc(node, state)
23
+ node.children.inject([]) do |memo, child|
24
+ memo << treat_coradoc(child, state)
25
+ end.flatten.reject { |x| x == "" || x.nil? }
26
+ end
27
+
28
+ def treat_coradoc(node, state)
29
+ Converters.process_coradoc(node, state)
30
+ end
31
+
32
+ def extract_title(node)
33
+ title = Coradoc::Element::TextElement.escape_keychars(
34
+ node["title"].to_s,
35
+ )
36
+ title.empty? ? "" : %[ #{title}]
37
+ end
38
+
39
+ def node_has_ancestor?(node, name)
40
+ case name
41
+ when String
42
+ node.ancestors.map(&:name).include?(name)
43
+ when Array
44
+ (node.ancestors.map(&:name) & name).any?
45
+ end
46
+ end
47
+
48
+ def textnode_before_end_with?(node, str)
49
+ return nil unless [String, Regexp].include?(str.class)
50
+ return nil if str.is_a?(String) && str.empty?
51
+
52
+ str = /#{Regexp.escape(str)}/ if str.is_a?(String)
53
+ str = /(?:#{str})\z/
54
+
55
+ node2 = node.at_xpath("preceding-sibling::node()[1]")
56
+ node2.respond_to?(:text) && node2.text.match?(str)
57
+ end
58
+
59
+ def textnode_after_start_with?(node, str)
60
+ return nil unless [String, Regexp].include?(str.class)
61
+ return nil if str.is_a?(String) && str.empty?
62
+
63
+ str = /#{Regexp.escape(str)}/ if str.is_a?(String)
64
+ str = /\A(?:#{str})/
65
+
66
+ node2 = node.at_xpath("following-sibling::node()[1]")
67
+ node2.respond_to?(:text) && node2.text.match?(str)
68
+ end
69
+
70
+ def extract_leading_trailing_whitespace(node)
71
+ node.text =~ /^(\s+)/
72
+ leading_whitespace = $1
73
+ if !leading_whitespace.nil?
74
+ first_text = node.at_xpath("./text()[1]")
75
+ first_text.replace(first_text.text.lstrip)
76
+ leading_whitespace = " "
77
+ end
78
+ node.text =~ /(\s+)$/
79
+ trailing_whitespace = $1
80
+ if !trailing_whitespace.nil?
81
+ last_text = node.at_xpath("./text()[last()]")
82
+ last_text.replace(last_text.text.rstrip)
83
+ trailing_whitespace = " "
84
+ end
85
+ [leading_whitespace, trailing_whitespace]
86
+ end
87
+
88
+ def unconstrained_before?(node)
89
+ before = node.at_xpath("preceding::node()[1]")
90
+
91
+ before &&
92
+ !before.text.strip.empty? &&
93
+ before.text[-1]&.match?(/\w/)
94
+ end
95
+
96
+ def unconstrained_after?(node)
97
+ after = node.at_xpath("following::node()[1]")
98
+
99
+ after && !after.text.strip.empty? &&
100
+ after.text[0]&.match?(/\w|,|;|"|\.\?!/)
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,18 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Blockquote < Base
4
+ def to_coradoc(node, state = {})
5
+ node["id"]
6
+ cite = node["cite"]
7
+ attributes = Coradoc::Element::AttributeList.new
8
+ attributes.add_positional("quote", cite) if !cite.nil?
9
+ content = treat_children(node, state).strip
10
+ content = Coradoc::ReverseAdoc.cleaner.remove_newlines(content)
11
+ Coradoc::Element::Block::Quote.new(nil, lines: content,
12
+ attributes: attributes)
13
+ end
14
+ end
15
+
16
+ register :blockquote, Blockquote.new
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Br < Base
4
+ def to_coradoc(_node, _state = {})
5
+ Coradoc::Element::Inline::HardLineBreak.new
6
+ end
7
+ end
8
+
9
+ register :br, Br.new
10
+ end
11
+ end
@@ -0,0 +1,77 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Bypass < Base
4
+ def to_coradoc(node, state = {})
5
+ treat_children_coradoc(node, state)
6
+ end
7
+ end
8
+
9
+ register :document, Bypass.new
10
+ register :html, Bypass.new
11
+ register :body, Bypass.new
12
+ register :span, Bypass.new
13
+ register :thead, Bypass.new
14
+ register :tbody, Bypass.new
15
+ register :tfoot, Bypass.new
16
+ register :abbr, Bypass.new
17
+ register :acronym, Bypass.new
18
+ register :address, Bypass.new
19
+ register :applet, Bypass.new
20
+ register :map, Bypass.new
21
+ register :area, Bypass.new
22
+ register :bdi, Bypass.new
23
+ register :bdo, Bypass.new
24
+ register :big, Bypass.new
25
+ register :button, Bypass.new
26
+ register :canvas, Bypass.new
27
+ register :data, Bypass.new
28
+ register :datalist, Bypass.new
29
+ register :del, Bypass.new
30
+ register :ins, Bypass.new
31
+ register :dfn, Bypass.new
32
+ register :dialog, Bypass.new
33
+ register :embed, Bypass.new
34
+ register :fieldset, Bypass.new
35
+ register :font, Bypass.new
36
+ register :footer, Bypass.new
37
+ register :form, Bypass.new
38
+ register :frame, Bypass.new
39
+ register :frameset, Bypass.new
40
+ register :header, Bypass.new
41
+ register :iframe, Bypass.new
42
+ register :input, Bypass.new
43
+ register :label, Bypass.new
44
+ register :legend, Bypass.new
45
+ register :main, Bypass.new
46
+ register :menu, Bypass.new
47
+ register :menulist, Bypass.new
48
+ register :meter, Bypass.new
49
+ register :nav, Bypass.new
50
+ register :noframes, Bypass.new
51
+ register :noscript, Bypass.new
52
+ register :object, Bypass.new
53
+ register :optgroup, Bypass.new
54
+ register :option, Bypass.new
55
+ register :output, Bypass.new
56
+ register :param, Bypass.new
57
+ register :picture, Bypass.new
58
+ register :progress, Bypass.new
59
+ register :ruby, Bypass.new
60
+ register :rt, Bypass.new
61
+ register :rp, Bypass.new
62
+ register :s, Bypass.new
63
+ register :select, Bypass.new
64
+ register :small, Bypass.new
65
+ register :span, Bypass.new
66
+ register :strike, Bypass.new
67
+ register :details, Bypass.new
68
+ register :section, Bypass.new
69
+ register :summary, Bypass.new
70
+ register :svg, Bypass.new
71
+ register :template, Bypass.new
72
+ register :textarea, Bypass.new
73
+ register :track, Bypass.new
74
+ register :u, Bypass.new
75
+ register :wbr, Bypass.new
76
+ end
77
+ end
@@ -0,0 +1,19 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Code < Markup
4
+ def coradoc_class
5
+ Coradoc::Element::Inline::Monospace
6
+ end
7
+
8
+ def markup_ancestor_tag_names
9
+ %w[code tt kbd samp var]
10
+ end
11
+ end
12
+
13
+ register :code, Code.new
14
+ register :tt, Code.new
15
+ register :kbd, Code.new
16
+ register :samp, Code.new
17
+ register :var, Code.new
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Div < Base
4
+ def to_coradoc(node, state = {})
5
+ id = node["id"]
6
+ contents = treat_children_coradoc(node, state)
7
+ Coradoc::Element::Section.new(nil, id: id, contents: contents)
8
+ end
9
+ end
10
+
11
+ register :div, Div.new
12
+ register :article, Div.new
13
+ end
14
+ end
@@ -0,0 +1,55 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Dl < Base
4
+ def to_coradoc(node, state = {})
5
+ items = process_dl(node, state)
6
+ items2 = items.map do |item|
7
+ Coradoc::Element::ListItemDefinition.new(item[:name], item[:value])
8
+ end
9
+ Coradoc::Element::List::Definition.new(items2, delimiter: "::")
10
+ end
11
+
12
+ def process_dl(node, state = {})
13
+ groups = []
14
+ current = {name: [], value: []}
15
+
16
+ seen_dd = false
17
+ child = node.at_xpath("*[1]")
18
+ grandchild = nil
19
+ while !child.nil?
20
+ if child.name == "div"
21
+ grandchild = child.at_xpath("*[1]")
22
+ while !grandchild.nil?
23
+ groups, current, seen_dd = process_dt_or_dd(groups, current, seen_dd, grandchild, state)
24
+ grandchild = grandchild.at_xpath("following-sibling::*[1]")
25
+ end
26
+ elsif ["dt", "dd"].include?(child.name)
27
+ groups, current, seen_dd = process_dt_or_dd(groups, current, seen_dd, child, state)
28
+ end
29
+ child = child.at_xpath("following-sibling::*[1]")
30
+ if current[:name].any? && current[:value].any?
31
+ groups << current
32
+ end
33
+ end
34
+ groups
35
+ end
36
+
37
+ def process_dt_or_dd(groups, current, seen_dd, subnode, state = {})
38
+ if subnode.name == "dt"
39
+ if seen_dd
40
+ # groups << current
41
+ current = {name: [], value: []}
42
+ seen_dd = false
43
+ end
44
+ current[:name] += treat_children_coradoc(subnode, state)
45
+ elsif subnode.name == "dd"
46
+ current[:value] += treat_children_coradoc(subnode, state)
47
+ seen_dd = true
48
+ end
49
+ [groups, current, seen_dd]
50
+ end
51
+ end
52
+
53
+ register :dl, Dl.new
54
+ end
55
+ end
@@ -0,0 +1,22 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Drop < Base
4
+ def to_coradoc(node, state = {})
5
+ convert(node, state)
6
+ end
7
+
8
+ def convert(_node, _state = {})
9
+ ""
10
+ end
11
+ end
12
+
13
+ register :caption, Drop.new
14
+ register :figcaption, Drop.new
15
+ register :title, Drop.new
16
+ register :link, Drop.new
17
+ register :style, Drop.new
18
+ register :meta, Drop.new
19
+ register :script, Drop.new
20
+ register :comment, Drop.new
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Em < Markup
4
+ def coradoc_class
5
+ Coradoc::Element::Inline::Italic
6
+ end
7
+
8
+ def markup_ancestor_tag_names
9
+ %w[em i cite]
10
+ end
11
+ end
12
+
13
+ register :em, Em.new
14
+ register :i, Em.new
15
+ register :cite, Em.new
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Figure < Base
4
+ def to_coradoc(node, state = {})
5
+ id = node["id"]
6
+ title = extract_title(node)
7
+ content = treat_children_coradoc(node, state)
8
+ Coradoc::Element::Block::Example.new(title, lines: content, id: id)
9
+ end
10
+
11
+ def extract_title(node)
12
+ title = node.at("./figcaption")
13
+ return "" if title.nil?
14
+
15
+ treat_children_coradoc(title, {})
16
+ end
17
+ end
18
+
19
+ register :figure, Figure.new
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class H < Base
4
+ def to_coradoc(node, state = {})
5
+ id = node["id"]
6
+ internal_anchor = treat_children_anchors(node, state)
7
+
8
+ if id.to_s.empty? && internal_anchor.size.positive?
9
+ id = internal_anchor.first.id
10
+ end
11
+
12
+ level = node.name[/\d/].to_i
13
+ content = treat_children_no_anchors(node, state)
14
+
15
+ Coradoc::Element::Title.new(content, level, id: id)
16
+ end
17
+
18
+ def treat_children_no_anchors(node, state)
19
+ node.children.reject { |a| a.name == "a" }.inject([]) do |memo, child|
20
+ memo << treat_coradoc(child, state)
21
+ end
22
+ end
23
+
24
+ def treat_children_anchors(node, state)
25
+ node.children.select { |a| a.name == "a" }.inject([]) do |memo, child|
26
+ memo << treat_coradoc(child, state)
27
+ end
28
+ end
29
+ end
30
+
31
+ register :h1, H.new
32
+ register :h2, H.new
33
+ register :h3, H.new
34
+ register :h4, H.new
35
+ register :h5, H.new
36
+ register :h6, H.new
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Head < Base
4
+ def to_coradoc(node, _state = {})
5
+ title = extract_title(node)
6
+ Coradoc::Element::Header.new(title)
7
+ end
8
+
9
+ def extract_title(node)
10
+ title = node.at("./title")
11
+ return "(???)" if title.nil?
12
+
13
+ title.text
14
+ end
15
+ end
16
+
17
+ register :head, Head.new
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Hr < Base
4
+ def to_coradoc(_node, _state = {})
5
+ Coradoc::Element::Break::ThematicBreak.new
6
+ end
7
+ end
8
+
9
+ register :hr, Hr.new
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Ignore < Base
4
+ def to_coradoc(node, state = {})
5
+ convert(node, state)
6
+ end
7
+
8
+ def convert(_node, _state = {})
9
+ "" # noop
10
+ end
11
+ end
12
+
13
+ register :colgroup, Ignore.new
14
+ register :col, Ignore.new
15
+ end
16
+ end
@@ -0,0 +1,98 @@
1
+ require "fileutils"
2
+ require "pathname"
3
+ require "tempfile"
4
+ require "base64"
5
+ require "marcel"
6
+
7
+ module Coradoc::ReverseAdoc
8
+ module Converters
9
+ class Img < Base
10
+ def image_number
11
+ sprintf(
12
+ Coradoc::ReverseAdoc.config.image_counter_pattern,
13
+ Coradoc::ReverseAdoc.config.image_counter,
14
+ )
15
+ end
16
+
17
+ def image_number_increment
18
+ Coradoc::ReverseAdoc.config.image_counter += 1
19
+ end
20
+
21
+ def datauri2file(src)
22
+ return unless src
23
+
24
+ %r{^data:image/(?:[^;]+);base64,(?<imgdata>.+)$} =~ src
25
+
26
+ dest_dir = Pathname.new(Coradoc::ReverseAdoc.config.destination).dirname
27
+ images_dir = dest_dir.join("images")
28
+ FileUtils.mkdir_p(images_dir)
29
+
30
+ ext, image_src_path, tempfile = determine_image_src_path(src, imgdata)
31
+ image_dest_path = images_dir + "#{image_number}.#{ext}"
32
+
33
+ # puts "image_dest_path: #{image_dest_path.to_s}"
34
+ # puts "image_src_path: #{image_src_path.to_s}"
35
+
36
+ FileUtils.cp(image_src_path, image_dest_path)
37
+ image_number_increment
38
+
39
+ image_dest_path.relative_path_from(dest_dir)
40
+ ensure
41
+ tempfile&.close!
42
+ end
43
+
44
+ def determine_image_src_path(src, imgdata)
45
+ return copy_temp_file(imgdata) if imgdata
46
+
47
+ ext = File.extname(src).strip.downcase[1..-1]
48
+ [ext, Pathname.new(Coradoc::ReverseAdoc.config.sourcedir).join(src)]
49
+ end
50
+
51
+ def copy_temp_file(imgdata)
52
+ f = Tempfile.open(["radoc", ".jpg"])
53
+ f.binmode
54
+ f.write(Base64.strict_decode64(imgdata))
55
+ f.rewind
56
+ ext = Marcel::MimeType.for(f).sub(%r{^[^/]+/}, "")
57
+ ext = "svg" if ext == "svg+xml"
58
+ [ext, f.path, f]
59
+ end
60
+
61
+ def to_coradoc(node, _state = {})
62
+ id = node["id"]
63
+ alt = node["alt"]
64
+ src = node["src"]
65
+ width = node["width"]
66
+ height = node["height"]
67
+
68
+ width = width.to_i if width&.match?(/\A\d+\z/)
69
+ height = height.to_i if height&.match?(/\A\d+\z/)
70
+
71
+ title = extract_title(node)
72
+
73
+ if Coradoc::ReverseAdoc.config.external_images
74
+ # puts "external image conversion #{id}, #{src}"
75
+ src = datauri2file(src)
76
+ end
77
+
78
+ attributes = Coradoc::Element::AttributeList.new
79
+ # attributes.add_named("id", id) if id
80
+ if alt # && !alt.to_s.empty?
81
+ attributes.add_positional(alt)
82
+ elsif width || height
83
+ attributes.add_positional(nil)
84
+ end
85
+ attributes.add_named("title", title) if title && !title.empty?
86
+ attributes.add_positional(width) if width
87
+ attributes.add_positional(height) if height
88
+
89
+ if src
90
+ Coradoc::Element::Image::BlockImage.new(title, id, src,
91
+ attributes: attributes)
92
+ end
93
+ end
94
+ end
95
+
96
+ register :img, Img.new
97
+ end
98
+ end
@@ -0,0 +1,13 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Li < Base
4
+ def to_coradoc(node, state = {})
5
+ id = node["id"]
6
+ content = treat_children_coradoc(node, state)
7
+ Coradoc::Element::ListItem.new(content, id: id)
8
+ end
9
+ end
10
+
11
+ register :li, Li.new
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module Coradoc::ReverseAdoc
2
+ module Converters
3
+ class Mark < Markup
4
+ def coradoc_class
5
+ Coradoc::Element::Inline::Highlight
6
+ end
7
+
8
+ def markup_ancestor_tag_names
9
+ %w[mark]
10
+ end
11
+ end
12
+
13
+ register :mark, Mark.new
14
+ end
15
+ end