coradoc-html 1.1.18 → 1.1.20

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coradoc/html/cleaner.rb +128 -0
  3. data/lib/coradoc/html/converters/a.rb +77 -0
  4. data/lib/coradoc/html/converters/aside.rb +20 -0
  5. data/lib/coradoc/html/converters/audio.rb +19 -0
  6. data/lib/coradoc/html/converters/base.rb +98 -0
  7. data/lib/coradoc/html/converters/blockquote.rb +25 -0
  8. data/lib/coradoc/html/converters/br.rb +17 -0
  9. data/lib/coradoc/html/converters/bypass.rb +82 -0
  10. data/lib/coradoc/html/converters/code.rb +25 -0
  11. data/lib/coradoc/html/converters/div.rb +23 -0
  12. data/lib/coradoc/html/converters/dl.rb +82 -0
  13. data/lib/coradoc/html/converters/drop.rb +26 -0
  14. data/lib/coradoc/html/converters/em.rb +23 -0
  15. data/lib/coradoc/html/converters/figure.rb +33 -0
  16. data/lib/coradoc/html/converters/h.rb +58 -0
  17. data/lib/coradoc/html/converters/head.rb +29 -0
  18. data/lib/coradoc/html/converters/hr.rb +17 -0
  19. data/lib/coradoc/html/converters/img.rb +103 -0
  20. data/lib/coradoc/html/converters/li.rb +35 -0
  21. data/lib/coradoc/html/converters/mark.rb +21 -0
  22. data/lib/coradoc/html/converters/markup.rb +93 -0
  23. data/lib/coradoc/html/converters/math.rb +37 -0
  24. data/lib/coradoc/html/converters/media_base.rb +48 -0
  25. data/lib/coradoc/html/converters/ol.rb +42 -0
  26. data/lib/coradoc/html/converters/p.rb +64 -0
  27. data/lib/coradoc/html/converters/pass_through.rb +15 -0
  28. data/lib/coradoc/html/converters/positional_formatting.rb +35 -0
  29. data/lib/coradoc/html/converters/pre.rb +57 -0
  30. data/lib/coradoc/html/converters/q.rb +25 -0
  31. data/lib/coradoc/html/converters/strong.rb +22 -0
  32. data/lib/coradoc/html/converters/sub.rb +20 -0
  33. data/lib/coradoc/html/converters/sup.rb +20 -0
  34. data/lib/coradoc/html/converters/table.rb +64 -0
  35. data/lib/coradoc/html/converters/td.rb +42 -0
  36. data/lib/coradoc/html/converters/text.rb +66 -0
  37. data/lib/coradoc/html/converters/tr.rb +27 -0
  38. data/lib/coradoc/html/converters/video.rb +27 -0
  39. data/lib/coradoc/html/converters.rb +104 -0
  40. data/lib/coradoc/html/drop/definition_item_drop.rb +17 -0
  41. data/lib/coradoc/html/drop/drop_factory.rb +14 -22
  42. data/lib/coradoc/html/drop/inline_element_drop.rb +3 -5
  43. data/lib/coradoc/html/drop/raw_inline_element_drop.rb +30 -0
  44. data/lib/coradoc/html/drop.rb +30 -8
  45. data/lib/coradoc/html/errors.rb +11 -0
  46. data/lib/coradoc/html/html_converter.rb +78 -0
  47. data/lib/coradoc/html/input_config.rb +66 -0
  48. data/lib/coradoc/html/plugin.rb +90 -0
  49. data/lib/coradoc/html/plugins/plateau.rb +212 -0
  50. data/lib/coradoc/html/postprocessor.rb +19 -0
  51. data/lib/coradoc/html/spa.rb +0 -2
  52. data/lib/coradoc/html/static.rb +0 -2
  53. data/lib/coradoc/html/tag_mapping.rb +3 -1
  54. data/lib/coradoc/html/transform/from_core_model.rb +2 -2
  55. data/lib/coradoc/html/transform/to_core_model.rb +3 -3
  56. data/lib/coradoc/html/version.rb +1 -1
  57. data/lib/coradoc/html.rb +30 -5
  58. metadata +46 -47
  59. data/lib/coradoc/html/input/cleaner.rb +0 -134
  60. data/lib/coradoc/html/input/config.rb +0 -80
  61. data/lib/coradoc/html/input/converters/a.rb +0 -79
  62. data/lib/coradoc/html/input/converters/aside.rb +0 -22
  63. data/lib/coradoc/html/input/converters/audio.rb +0 -21
  64. data/lib/coradoc/html/input/converters/base.rb +0 -118
  65. data/lib/coradoc/html/input/converters/blockquote.rb +0 -27
  66. data/lib/coradoc/html/input/converters/br.rb +0 -19
  67. data/lib/coradoc/html/input/converters/bypass.rb +0 -84
  68. data/lib/coradoc/html/input/converters/code.rb +0 -27
  69. data/lib/coradoc/html/input/converters/div.rb +0 -25
  70. data/lib/coradoc/html/input/converters/dl.rb +0 -84
  71. data/lib/coradoc/html/input/converters/drop.rb +0 -28
  72. data/lib/coradoc/html/input/converters/em.rb +0 -25
  73. data/lib/coradoc/html/input/converters/figure.rb +0 -35
  74. data/lib/coradoc/html/input/converters/h.rb +0 -74
  75. data/lib/coradoc/html/input/converters/head.rb +0 -31
  76. data/lib/coradoc/html/input/converters/hr.rb +0 -19
  77. data/lib/coradoc/html/input/converters/img.rb +0 -105
  78. data/lib/coradoc/html/input/converters/li.rb +0 -37
  79. data/lib/coradoc/html/input/converters/mark.rb +0 -23
  80. data/lib/coradoc/html/input/converters/markup.rb +0 -103
  81. data/lib/coradoc/html/input/converters/math.rb +0 -39
  82. data/lib/coradoc/html/input/converters/media_base.rb +0 -50
  83. data/lib/coradoc/html/input/converters/ol.rb +0 -44
  84. data/lib/coradoc/html/input/converters/p.rb +0 -90
  85. data/lib/coradoc/html/input/converters/pass_through.rb +0 -17
  86. data/lib/coradoc/html/input/converters/positional_formatting.rb +0 -37
  87. data/lib/coradoc/html/input/converters/pre.rb +0 -59
  88. data/lib/coradoc/html/input/converters/q.rb +0 -27
  89. data/lib/coradoc/html/input/converters/strong.rb +0 -24
  90. data/lib/coradoc/html/input/converters/sub.rb +0 -22
  91. data/lib/coradoc/html/input/converters/sup.rb +0 -22
  92. data/lib/coradoc/html/input/converters/table.rb +0 -66
  93. data/lib/coradoc/html/input/converters/td.rb +0 -44
  94. data/lib/coradoc/html/input/converters/text.rb +0 -68
  95. data/lib/coradoc/html/input/converters/tr.rb +0 -29
  96. data/lib/coradoc/html/input/converters/video.rb +0 -29
  97. data/lib/coradoc/html/input/converters.rb +0 -107
  98. data/lib/coradoc/html/input/errors.rb +0 -22
  99. data/lib/coradoc/html/input/html_converter.rb +0 -98
  100. data/lib/coradoc/html/input/plugin.rb +0 -120
  101. data/lib/coradoc/html/input/plugins/plateau.rb +0 -214
  102. data/lib/coradoc/html/input/postprocessor.rb +0 -25
  103. data/lib/coradoc/html/input.rb +0 -86
  104. data/lib/coradoc/html/output.rb +0 -89
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Markup < Base
8
- def to_coradoc(node, state = {})
9
- u_before = unconstrained_before?(node)
10
- u_after = unconstrained_after?(node)
11
-
12
- leading_ws, trailing_ws =
13
- extract_leading_trailing_whitespace(node)
14
-
15
- # Wrap whitespace in InlineElement so it can be processed
16
- leading_whitespace = if leading_ws
17
- Coradoc::CoreModel::TextElement.new(
18
- content: leading_ws
19
- )
20
- end
21
- trailing_whitespace = if trailing_ws
22
- Coradoc::CoreModel::TextElement.new(
23
- content: trailing_ws
24
- )
25
- end
26
-
27
- content = treat_children_coradoc(node, state)
28
-
29
- if node_has_ancestor?(node, markup_ancestor_tag_names)
30
- content
31
- elsif node.children.empty?
32
- # Return InlineElement wrapper for whitespace
33
- if leading_ws
34
- Coradoc::CoreModel::TextElement.new(
35
- content: leading_ws
36
- )
37
- end
38
- else
39
- u = (u_before && leading_whitespace.nil?) ||
40
- (u_after && trailing_whitespace.nil?)
41
-
42
- # Separate text strings from InlineElements in content array
43
- text_content, nested = extract_text_and_elements(content)
44
-
45
- # Create CoreModel::InlineElement with the appropriate format type
46
- inline_element = Coradoc::CoreModel::InlineElement.format_type_class(coradoc_format_type).new(
47
- content: text_content,
48
- nested_elements: nested.empty? ? nil : nested,
49
- metadata: { unconstrained: u }
50
- )
51
- result = [leading_whitespace, inline_element, trailing_whitespace].compact
52
- result.length == 1 ? result.first : result
53
- end
54
- end
55
-
56
- # Extract text content and InlineElements from mixed content array
57
- def extract_text_and_elements(content)
58
- return [content, []] unless content.is_a?(Array)
59
-
60
- text_parts = []
61
- elements = []
62
-
63
- content.each do |item|
64
- case item
65
- when String
66
- text_parts << item
67
- when Coradoc::CoreModel::InlineElement
68
- elements << item
69
- when Coradoc::CoreModel::Base
70
- # For other block types, convert to text
71
- text_parts << extract_text_from_model(item)
72
- else
73
- text_parts << item.to_s
74
- end
75
- end
76
-
77
- [text_parts.join, elements]
78
- end
79
-
80
- # Extract text from a CoreModel object
81
- def extract_text_from_model(model)
82
- return '' if model.nil?
83
-
84
- if model.is_a?(Coradoc::CoreModel::Base) && model.content.is_a?(String)
85
- model.content
86
- elsif model.is_a?(Coradoc::CoreModel::StructuralElement) && model.children.is_a?(Array)
87
- model.children.map { |c| extract_text_from_model(c) }.join
88
- elsif model.is_a?(Coradoc::CoreModel::Base) && model.title.is_a?(String)
89
- model.title
90
- else
91
- model.to_s
92
- end
93
- end
94
-
95
- # Subclasses should override this to return the format type
96
- def coradoc_format_type
97
- 'text'
98
- end
99
- end
100
- end
101
- end
102
- end
103
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Math < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, _state = {})
11
- stem = node.to_s.tr("\n", ' ')
12
- if Coradoc::Html::Input.config.mathml2asciimath
13
- require 'plurimath'
14
- stem = Plurimath::Math.parse(stem, :mathml).to_asciimath
15
- end
16
-
17
- unless stem.nil?
18
- stem = stem.gsub('[', '\\[')
19
- stem = stem.gsub(']', '\\]')
20
- loop do
21
- new_stem = stem.gsub(/\(\(([^)]{1,100})\)\)/, '(\\1)')
22
- break if new_stem == stem
23
-
24
- stem = new_stem
25
- end
26
- end
27
-
28
- Coradoc::CoreModel::StemElement.new(
29
- content: stem,
30
- stem_type: 'mathml'
31
- )
32
- end
33
- end
34
-
35
- register :math, Math::INSTANCE
36
- end
37
- end
38
- end
39
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class MediaBase < Base
8
- def to_coradoc(node, _state = {})
9
- src = node['src']
10
- id = node['id']
11
- title = extract_title(node)
12
-
13
- Coradoc::CoreModel::Block.new(
14
- block_semantic_type: semantic_type,
15
- content: src,
16
- title: title,
17
- id: id,
18
- element_attributes: build_attributes(node)
19
- )
20
- end
21
-
22
- def extract_title(node)
23
- track = node.at('./track') || node.at('.//source')
24
- return '' if track.nil?
25
-
26
- track['label'] || track['srclang'] || ''
27
- end
28
-
29
- private
30
-
31
- def semantic_type
32
- raise NotImplementedError
33
- end
34
-
35
- def base_attributes(node)
36
- {
37
- autoplay: node['autoplay'],
38
- loop: node['loop'],
39
- controls: node['controls']
40
- }.compact
41
- end
42
-
43
- def build_attributes(node)
44
- base_attributes(node)
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Ol < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, state = {})
11
- id = node['id']
12
- items = treat_children_coradoc(node, state)
13
-
14
- marker_type = get_list_type(node, state)
15
-
16
- Coradoc::CoreModel::ListBlock.new(
17
- marker_type: marker_type,
18
- items: items,
19
- id: id,
20
- start: node['start']&.to_i
21
- )
22
- end
23
-
24
- def get_list_type(node, _state)
25
- case node.name
26
- when 'ol'
27
- 'ordered'
28
- when 'ul'
29
- 'unordered'
30
- when 'dir'
31
- 'unordered'
32
- else
33
- 'unordered'
34
- end
35
- end
36
- end
37
-
38
- register :ol, Ol::INSTANCE
39
- register :ul, Ol::INSTANCE
40
- register :dir, Ol::INSTANCE
41
- end
42
- end
43
- end
44
- end
@@ -1,90 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class P < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, state = {})
11
- id = node['id']
12
- content = treat_children_coradoc(node, state)
13
-
14
- content = strip_fullwidth_spaces(content)
15
-
16
- Coradoc::CoreModel::ParagraphBlock.new(
17
- children: content,
18
- id: id
19
- )
20
- end
21
-
22
- private
23
-
24
- def strip_fullwidth_spaces(content)
25
- return content unless content.is_a?(Array)
26
-
27
- content.each do |item|
28
- next unless item.is_a?(Coradoc::CoreModel::InlineElement)
29
- next unless item.content.is_a?(String)
30
-
31
- item.content = item.content.gsub(/\A +| +\z/, '')
32
- end
33
-
34
- strip_edge_whitespace(content)
35
- reject_empty_elements(content)
36
- end
37
-
38
- def strip_edge_whitespace(content)
39
- first = content.find { |item| text_element?(item) }
40
- strip_left(first) if first
41
-
42
- last = content.reverse.find { |item| text_element?(item) }
43
- strip_right(last) if last
44
- end
45
-
46
- def strip_left(item)
47
- case item
48
- when Coradoc::CoreModel::InlineElement
49
- item.content = item.content.lstrip if item.content.is_a?(String)
50
- when String
51
- item.replace(item.lstrip)
52
- end
53
- end
54
-
55
- def strip_right(item)
56
- case item
57
- when Coradoc::CoreModel::InlineElement
58
- item.content = item.content.rstrip if item.content.is_a?(String)
59
- when String
60
- item.replace(item.rstrip)
61
- end
62
- end
63
-
64
- def text_element?(item)
65
- item.is_a?(Coradoc::CoreModel::InlineElement) || item.is_a?(String)
66
- end
67
-
68
- def reject_empty_elements(content)
69
- content.reject do |item|
70
- if item.is_a?(Coradoc::CoreModel::InlineElement)
71
- item.content.to_s.empty? && !has_nested_content?(item)
72
- elsif item.is_a?(String)
73
- item.empty?
74
- else
75
- false
76
- end
77
- end
78
- end
79
-
80
- def has_nested_content?(item)
81
- item.is_a?(Coradoc::CoreModel::InlineElement) &&
82
- item.nested_elements && !item.nested_elements.empty?
83
- end
84
- end
85
-
86
- register :p, P::INSTANCE
87
- end
88
- end
89
- end
90
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class PassThrough < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, _state = {})
11
- node.to_s
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- # Shared logic for superscript/subscript converters.
8
- #
9
- # Subclasses must implement `element_class` returning the
10
- # CoreModel class (e.g., SuperscriptElement, SubscriptElement).
11
- module PositionalFormatting
12
- def to_coradoc(node, state = {})
13
- leading_whitespace, trailing_whitespace = extract_leading_trailing_whitespace(node)
14
-
15
- content = treat_children_coradoc(node, state)
16
-
17
- return nil if content_empty?(content)
18
-
19
- e = element_class.new(content: content)
20
- result = [leading_whitespace, e, trailing_whitespace].compact
21
- result.length == 1 ? result.first : result
22
- end
23
-
24
- private
25
-
26
- def content_empty?(content)
27
- return true if content.nil?
28
- return content.strip.empty? if content.is_a?(String)
29
- return content.empty? if content.is_a?(Array)
30
-
31
- false
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Pre < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, _state = {})
11
- id = node['id']
12
- lang = language(node)
13
- content = extract_text_content(node)
14
-
15
- if lang
16
- Coradoc::CoreModel::SourceBlock.new(
17
- content: content,
18
- id: id,
19
- language: lang
20
- )
21
- else
22
- Coradoc::CoreModel::LiteralBlock.new(
23
- content: content,
24
- id: id
25
- )
26
- end
27
- end
28
-
29
- private
30
-
31
- def extract_text_content(node)
32
- # Get text content from pre node
33
- node.text
34
- end
35
-
36
- def language(node)
37
- lang = language_from_highlight_class(node)
38
- lang || language_from_confluence_class(node)
39
- end
40
-
41
- def language_from_highlight_class(node)
42
- node.parent['class'].to_s[/highlight-([a-zA-Z0-9]+)/, 1]
43
- end
44
-
45
- def language_from_confluence_class(node)
46
- class_str = node['class'].to_s
47
- return nil unless class_str.include?('brush:')
48
-
49
- # Extract language from brush: language; pattern
50
- match = class_str.match(/brush:\s*([^;]+);/)
51
- match ? match[1].strip : nil
52
- end
53
- end
54
-
55
- register :pre, Pre::INSTANCE
56
- end
57
- end
58
- end
59
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Q < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, state = {})
11
- content = treat_children_coradoc(node, state)
12
- cite = node['cite']
13
-
14
- Coradoc::CoreModel::InlineElement.new(
15
- format_type: 'quotation',
16
- nested_elements: content,
17
- content: extract_text_from_content(content),
18
- target: cite
19
- )
20
- end
21
- end
22
-
23
- register :q, Q::INSTANCE
24
- end
25
- end
26
- end
27
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Strong < Markup
8
- INSTANCE = new
9
-
10
- def coradoc_format_type
11
- 'bold'
12
- end
13
-
14
- def markup_ancestor_tag_names
15
- %w[strong b]
16
- end
17
- end
18
-
19
- register :strong, Strong::INSTANCE
20
- register :b, Strong::INSTANCE
21
- end
22
- end
23
- end
24
- 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 Sub < Base
8
- INSTANCE = new
9
- include PositionalFormatting
10
-
11
- private
12
-
13
- def element_class
14
- Coradoc::CoreModel::SubscriptElement
15
- end
16
- end
17
-
18
- register :sub, Sub::INSTANCE
19
- end
20
- end
21
- end
22
- 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 Sup < Base
8
- INSTANCE = new
9
- include PositionalFormatting
10
-
11
- private
12
-
13
- def element_class
14
- Coradoc::CoreModel::SuperscriptElement
15
- end
16
- end
17
-
18
- register :sup, Sup::INSTANCE
19
- end
20
- end
21
- end
22
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Table < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, state = {})
11
- id = node['id']
12
- title = extract_title(node)
13
- content = treat_children_coradoc(node, state)
14
-
15
- # Apply frame and grid attributes if available
16
- frame_attr = frame(node)
17
- grid_attr = rules(node)
18
-
19
- Coradoc::CoreModel::Table.new(
20
- title: title,
21
- rows: content,
22
- id: id,
23
- frame: frame_attr,
24
- grid: grid_attr
25
- )
26
- end
27
-
28
- def extract_title(node)
29
- title = node.at('./caption')
30
- return nil if title.nil?
31
-
32
- title.text.strip
33
- end
34
-
35
- def frame(node)
36
- case node['frame']
37
- when 'void'
38
- 'none'
39
- when 'hsides'
40
- 'topbot'
41
- when 'vsides'
42
- 'sides'
43
- when 'box', 'border'
44
- 'all'
45
- end
46
- end
47
-
48
- def rules(node)
49
- case node['rules']
50
- when 'all'
51
- 'all'
52
- when 'rows'
53
- 'rows'
54
- when 'cols'
55
- 'cols'
56
- when 'none'
57
- 'none'
58
- end
59
- end
60
- end
61
-
62
- register :table, Table::INSTANCE
63
- end
64
- end
65
- end
66
- end
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Coradoc
4
- module Input
5
- module Html
6
- module Converters
7
- class Td < Base
8
- INSTANCE = new
9
-
10
- def to_coradoc(node, state = {})
11
- colspan = node['colspan']&.to_i
12
- rowspan = node['rowspan']&.to_i
13
- alignment = extract_alignment(node)
14
-
15
- singlepara = node.elements.size == 1 && node.elements.first.name == 'p'
16
- state[:tdsinglepara] = singlepara if singlepara
17
-
18
- content = treat_children_coradoc(node, state)
19
-
20
- Coradoc::CoreModel::TableCell.new(
21
- content: extract_text_from_content(content),
22
- alignment: alignment,
23
- colspan: colspan && colspan > 1 ? colspan : nil,
24
- rowspan: rowspan && rowspan > 1 ? rowspan : nil,
25
- header: node.name == 'th'
26
- )
27
- end
28
-
29
- def extract_alignment(node)
30
- align = node['align']
31
- case align
32
- when 'left' then 'left'
33
- when 'center' then 'center'
34
- when 'right' then 'right'
35
- end
36
- end
37
- end
38
-
39
- register :td, Td::INSTANCE
40
- register :th, Td::INSTANCE
41
- end
42
- end
43
- end
44
- end