coradoc 1.1.5 → 1.1.7

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +1 -0
  3. data/.irbrc +1 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +5 -1
  6. data/.rubocop_todo.yml +179 -0
  7. data/Gemfile +11 -0
  8. data/README.adoc +5 -7
  9. data/coradoc.gemspec +5 -16
  10. data/exe/reverse_adoc +1 -1
  11. data/exe/w2a +1 -1
  12. data/flake.lock +114 -0
  13. data/flake.nix +135 -0
  14. data/lib/coradoc/cli.rb +1 -1
  15. data/lib/coradoc/converter.rb +4 -5
  16. data/lib/coradoc/element/attribute.rb +10 -1
  17. data/lib/coradoc/element/attribute_list.rb +4 -3
  18. data/lib/coradoc/element/audio.rb +1 -1
  19. data/lib/coradoc/element/author.rb +2 -2
  20. data/lib/coradoc/element/base.rb +14 -2
  21. data/lib/coradoc/element/bibliography.rb +1 -1
  22. data/lib/coradoc/element/bibliography_entry.rb +1 -1
  23. data/lib/coradoc/element/block/open.rb +1 -1
  24. data/lib/coradoc/element/block.rb +1 -1
  25. data/lib/coradoc/element/document_attributes.rb +8 -2
  26. data/lib/coradoc/element/image/block_image.rb +3 -2
  27. data/lib/coradoc/element/image/core.rb +5 -4
  28. data/lib/coradoc/element/inline/attribute_reference.rb +19 -0
  29. data/lib/coradoc/element/inline/cross_reference.rb +4 -3
  30. data/lib/coradoc/element/inline/footnote.rb +24 -0
  31. data/lib/coradoc/element/inline/small.rb +19 -0
  32. data/lib/coradoc/element/inline/span.rb +37 -0
  33. data/lib/coradoc/element/inline/underline.rb +19 -0
  34. data/lib/coradoc/element/inline.rb +5 -1
  35. data/lib/coradoc/element/list/core.rb +2 -2
  36. data/lib/coradoc/element/list/ordered.rb +1 -0
  37. data/lib/coradoc/element/list/unordered.rb +1 -0
  38. data/lib/coradoc/element/list_item.rb +19 -20
  39. data/lib/coradoc/element/table.rb +4 -2
  40. data/lib/coradoc/element/term.rb +1 -0
  41. data/lib/coradoc/element/text_element.rb +4 -1
  42. data/lib/coradoc/element/title.rb +1 -1
  43. data/lib/coradoc/element/video.rb +2 -2
  44. data/lib/coradoc/input/adoc.rb +20 -18
  45. data/lib/coradoc/input/docx.rb +25 -23
  46. data/lib/coradoc/input/html/README.adoc +1 -1
  47. data/lib/coradoc/input/html/cleaner.rb +121 -117
  48. data/lib/coradoc/input/html/config.rb +58 -56
  49. data/lib/coradoc/input/html/converters/a.rb +44 -39
  50. data/lib/coradoc/input/html/converters/aside.rb +12 -8
  51. data/lib/coradoc/input/html/converters/audio.rb +24 -20
  52. data/lib/coradoc/input/html/converters/base.rb +103 -99
  53. data/lib/coradoc/input/html/converters/blockquote.rb +18 -14
  54. data/lib/coradoc/input/html/converters/br.rb +11 -7
  55. data/lib/coradoc/input/html/converters/bypass.rb +77 -73
  56. data/lib/coradoc/input/html/converters/code.rb +18 -14
  57. data/lib/coradoc/input/html/converters/div.rb +15 -11
  58. data/lib/coradoc/input/html/converters/dl.rb +51 -44
  59. data/lib/coradoc/input/html/converters/drop.rb +21 -17
  60. data/lib/coradoc/input/html/converters/em.rb +16 -12
  61. data/lib/coradoc/input/html/converters/figure.rb +19 -15
  62. data/lib/coradoc/input/html/converters/h.rb +32 -30
  63. data/lib/coradoc/input/html/converters/head.rb +17 -13
  64. data/lib/coradoc/input/html/converters/hr.rb +11 -7
  65. data/lib/coradoc/input/html/converters/ignore.rb +15 -11
  66. data/lib/coradoc/input/html/converters/img.rb +98 -93
  67. data/lib/coradoc/input/html/converters/li.rb +13 -9
  68. data/lib/coradoc/input/html/converters/mark.rb +14 -10
  69. data/lib/coradoc/input/html/converters/markup.rb +22 -18
  70. data/lib/coradoc/input/html/converters/math.rb +26 -19
  71. data/lib/coradoc/input/html/converters/ol.rb +55 -50
  72. data/lib/coradoc/input/html/converters/p.rb +16 -12
  73. data/lib/coradoc/input/html/converters/pass_through.rb +12 -8
  74. data/lib/coradoc/input/html/converters/pre.rb +49 -45
  75. data/lib/coradoc/input/html/converters/q.rb +12 -8
  76. data/lib/coradoc/input/html/converters/strong.rb +15 -11
  77. data/lib/coradoc/input/html/converters/sub.rb +15 -11
  78. data/lib/coradoc/input/html/converters/sup.rb +15 -11
  79. data/lib/coradoc/input/html/converters/table.rb +21 -13
  80. data/lib/coradoc/input/html/converters/td.rb +64 -60
  81. data/lib/coradoc/input/html/converters/text.rb +24 -20
  82. data/lib/coradoc/input/html/converters/th.rb +13 -9
  83. data/lib/coradoc/input/html/converters/tr.rb +17 -13
  84. data/lib/coradoc/input/html/converters/video.rb +24 -20
  85. data/lib/coradoc/input/html/converters.rb +45 -43
  86. data/lib/coradoc/input/html/errors.rb +8 -6
  87. data/lib/coradoc/input/html/html_converter.rb +93 -90
  88. data/lib/coradoc/input/html/plugin.rb +104 -104
  89. data/lib/coradoc/input/html/plugins/plateau.rb +197 -190
  90. data/lib/coradoc/input/html/postprocessor.rb +188 -182
  91. data/lib/coradoc/input/html.rb +34 -32
  92. data/lib/coradoc/oscal.rb +18 -5
  93. data/lib/coradoc/output/adoc.rb +13 -11
  94. data/lib/coradoc/output/coradoc_tree_debug.rb +15 -13
  95. data/lib/coradoc/parser/asciidoc/admonition.rb +6 -6
  96. data/lib/coradoc/parser/asciidoc/attribute_list.rb +43 -27
  97. data/lib/coradoc/parser/asciidoc/base.rb +3 -6
  98. data/lib/coradoc/parser/asciidoc/bibliography.rb +5 -6
  99. data/lib/coradoc/parser/asciidoc/block.rb +30 -31
  100. data/lib/coradoc/parser/asciidoc/citation.rb +11 -29
  101. data/lib/coradoc/parser/asciidoc/content.rb +23 -33
  102. data/lib/coradoc/parser/asciidoc/document_attributes.rb +2 -3
  103. data/lib/coradoc/parser/asciidoc/header.rb +1 -2
  104. data/lib/coradoc/parser/asciidoc/inline.rb +165 -42
  105. data/lib/coradoc/parser/asciidoc/list.rb +27 -27
  106. data/lib/coradoc/parser/asciidoc/paragraph.rb +28 -19
  107. data/lib/coradoc/parser/asciidoc/section.rb +11 -17
  108. data/lib/coradoc/parser/asciidoc/table.rb +5 -5
  109. data/lib/coradoc/parser/asciidoc/term.rb +24 -8
  110. data/lib/coradoc/parser/asciidoc/text.rb +18 -21
  111. data/lib/coradoc/parser/base.rb +0 -3
  112. data/lib/coradoc/reverse_adoc.rb +3 -3
  113. data/lib/coradoc/transformer.rb +167 -137
  114. data/lib/coradoc/version.rb +1 -1
  115. data/lib/reverse_adoc.rb +1 -1
  116. data/utils/inspect_asciidoc.rb +29 -0
  117. data/utils/parser_analyzer.rb +14 -14
  118. data/utils/round_trip.rb +31 -15
  119. metadata +34 -137
  120. data/.hound.yml +0 -5
  121. data/lib/coradoc/element/inline/citation.rb +0 -24
  122. data/todo.md +0 -10
@@ -1,214 +1,220 @@
1
- module Coradoc::Input::HTML
2
- # Postprocessor's aim is to convert a Coradoc tree from
3
- # a mess that has been created from HTML into a tree that
4
- # is compatible with what we would get out of Coradoc, if
5
- # it parsed it directly.
6
- class Postprocessor
7
- Element = Coradoc::Element
8
-
9
- def self.process(coradoc)
10
- new(coradoc).process
11
- end
12
-
13
- def initialize(coradoc)
14
- @tree = coradoc
15
- end
1
+ module Coradoc
2
+ module Input
3
+ module Html
4
+ # Postprocessor's aim is to convert a Coradoc tree from
5
+ # a mess that has been created from HTML into a tree that
6
+ # is compatible with what we would get out of Coradoc, if
7
+ # it parsed it directly.
8
+ class Postprocessor
9
+ Element = Coradoc::Element
10
+
11
+ def self.process(coradoc)
12
+ new(coradoc).process
13
+ end
16
14
 
17
- # Extracts titles from lists. This happens in HTML files
18
- # generated from DOCX documents by LibreOffice.
19
- #
20
- # We are interested in a particular tree:
21
- # Element::List::Ordered items:
22
- # Element::List::Ordered items: (any depth)
23
- # Element::ListItem content:
24
- # Element::Title
25
- # (any number of other titles of the same scheme)
26
- #
27
- # This tree is flattened into:
28
- # Element::Title
29
- # Element::Title (any number of titles)
30
- def extract_titles_from_lists
31
- @tree = Element::Base.visit(@tree) do |elem, dir|
32
- next elem unless dir == :pre
33
- next elem unless elem.is_a?(Element::List::Ordered)
34
- next elem if elem.items.length != 1
35
-
36
- anchors = []
37
- anchors << elem.anchor if elem.anchor
38
-
39
- # Extract ListItem from any depth of List::Ordered
40
- processed = elem
41
- while processed.is_a?(Element::List::Ordered)
42
- if processed.items.length != 1
43
- backtrack = true
44
- break
45
- end
46
- anchors << processed.anchor if processed.anchor
47
- processed = processed.items.first
15
+ def initialize(coradoc)
16
+ @tree = coradoc
48
17
  end
49
18
 
50
- # Something went wrong? Anything not matching on the way?
51
- next elem if backtrack
52
- next elem unless processed.is_a?(Element::ListItem)
19
+ # Extracts titles from lists. This happens in HTML files
20
+ # generated from DOCX documents by LibreOffice.
21
+ #
22
+ # We are interested in a particular tree:
23
+ # Element::List::Ordered items:
24
+ # Element::List::Ordered items: (any depth)
25
+ # Element::ListItem content:
26
+ # Element::Title
27
+ # (any number of other titles of the same scheme)
28
+ #
29
+ # This tree is flattened into:
30
+ # Element::Title
31
+ # Element::Title (any number of titles)
32
+ def extract_titles_from_lists
33
+ @tree = Element::Base.visit(@tree) do |elem, dir|
34
+ next elem unless dir == :pre
35
+ next elem unless elem.is_a?(Element::List::Ordered)
36
+ next elem if elem.items.length != 1
37
+
38
+ anchors = []
39
+ anchors << elem.anchor if elem.anchor
40
+
41
+ # Extract ListItem from any depth of List::Ordered
42
+ processed = elem
43
+ while processed.is_a?(Element::List::Ordered)
44
+ if processed.items.length != 1
45
+ backtrack = true
46
+ break
47
+ end
48
+ anchors << processed.anchor if processed.anchor
49
+ processed = processed.items.first
50
+ end
53
51
 
54
- anchors << processed.anchor if processed.anchor
52
+ # Something went wrong? Anything not matching on the way?
53
+ next elem if backtrack
54
+ next elem unless processed.is_a?(Element::ListItem)
55
55
 
56
- # Now we must have a title (or titles).
57
- titles = processed.content.flatten
56
+ anchors << processed.anchor if processed.anchor
58
57
 
59
- # Don't bother if there's no title in there.
60
- next elem unless titles.any? { |i| i.is_a? Element::Title }
58
+ # Now we must have a title (or titles).
59
+ titles = processed.content.flatten
61
60
 
62
- # Ordered is another iteration for our cleanup.
63
- next elem unless titles.all? do |i|
64
- i.is_a?(Element::Title) || i.is_a?(Element::List::Ordered)
65
- end
61
+ # Don't bother if there's no title in there.
62
+ next elem unless titles.any? { |i| i.is_a? Element::Title }
66
63
 
67
- # We are done now.
68
- titles + anchors
69
- end
70
- end
64
+ # Ordered is another iteration for our cleanup.
65
+ next elem unless titles.all? do |i|
66
+ i.is_a?(Element::Title) || i.is_a?(Element::List::Ordered)
67
+ end
71
68
 
72
- # Collapse DIVs that only have a title, or nest another DIV.
73
- def collapse_meaningless_sections
74
- @tree = Element::Base.visit(@tree) do |elem, _dir|
75
- if elem.is_a?(Element::Section) && elem.safe_to_collapse?
76
- children_classes = Array(elem.contents).map(&:class)
77
- count = children_classes.length
78
- safe_classes = [Element::Section, Element::Title]
79
-
80
- # Count > 0 because some documents use <div> as a <br>.
81
- if count > 0 && children_classes.all? { |i| safe_classes.include?(i) }
82
- contents = elem.contents.dup
83
- contents.prepend(elem.anchor) if elem.anchor
84
- next contents
69
+ # We are done now.
70
+ titles + anchors
85
71
  end
86
72
  end
87
- elem
88
- end
89
- end
90
73
 
91
- # tree should now be more cleaned up, so we can progress with
92
- # creating meaningful sections
93
- def generate_meaningful_sections
94
- @tree = Element::Base.visit(@tree) do |elem, dir|
95
- # We are searching for an array, that has a title. This
96
- # will be a candidate for our section array.
97
- if dir == :post &&
98
- elem.is_a?(Array) &&
99
- !elem.flatten.grep(Element::Title).empty?
100
-
101
- elem = elem.flatten
102
-
103
- new_array = []
104
- content_array = new_array
105
- section_arrays_by_level = [new_array] * 8
106
-
107
- # For each title element, we create a new section. Then we push
108
- # all descendant sections into those sections. Otherwise, we push
109
- # an element as content of current section.
110
- elem.each do |e|
111
- if e.is_a? Element::Title
112
- title = e
113
- content_array = []
114
- section_array = []
115
- level = title.level_int
116
- section = Element::Section.new(
117
- title, contents: content_array, sections: section_array
118
- )
119
- # Some documents may not be consistent and eg. follow H4 after
120
- # H2. Let's ensure that proceeding sections will land in a
121
- # correct place.
122
- (8 - level).times do |j|
123
- section_arrays_by_level[level + j] = section_array
74
+ # Collapse DIVs that only have a title, or nest another DIV.
75
+ def collapse_meaningless_sections
76
+ @tree = Element::Base.visit(@tree) do |elem, _dir|
77
+ if elem.is_a?(Element::Section) && elem.safe_to_collapse?
78
+ children_classes = Array(elem.contents).map(&:class)
79
+ count = children_classes.length
80
+ safe_classes = [Element::Section, Element::Title]
81
+
82
+ # Count > 0 because some documents use <div> as a <br>.
83
+ if count.positive? && children_classes.all? do |i|
84
+ safe_classes.include?(i)
85
+ end
86
+ contents = elem.contents.dup
87
+ contents.prepend(elem.anchor) if elem.anchor
88
+ next contents
124
89
  end
125
- section_arrays_by_level[level - 1] << section
126
- else
127
- content_array << e
128
90
  end
91
+ elem
129
92
  end
130
- next new_array
131
93
  end
132
- elem
133
- end
134
- end
135
-
136
- def split_sections
137
- max_level = Coradoc::Input::HTML.config.split_sections
138
-
139
- return unless max_level
140
94
 
141
- sections = {}
142
- parent_sections = []
143
- previous_sections = {}
144
-
145
- determine_section_id = ->(elem) do
146
- level = if elem.title.style == "appendix"
147
- "A"
95
+ # tree should now be more cleaned up, so we can progress with
96
+ # creating meaningful sections
97
+ def generate_meaningful_sections
98
+ @tree = Element::Base.visit(@tree) do |elem, dir|
99
+ # We are searching for an array, that has a title. This
100
+ # will be a candidate for our section array.
101
+ if dir == :post &&
102
+ elem.is_a?(Array) &&
103
+ !elem.flatten.grep(Element::Title).empty?
104
+
105
+ elem = elem.flatten
106
+
107
+ new_array = []
108
+ content_array = new_array
109
+ section_arrays_by_level = [new_array] * 8
110
+
111
+ # For each title element, we create a new section. Then we push
112
+ # all descendant sections into those sections. Otherwise, we push
113
+ # an element as content of current section.
114
+ elem.each do |e|
115
+ if e.is_a? Element::Title
116
+ title = e
117
+ content_array = []
118
+ section_array = []
119
+ level = title.level_int
120
+ section = Element::Section.new(
121
+ title, contents: content_array, sections: section_array
122
+ )
123
+ # Some documents may not be consistent and eg. follow H4 after
124
+ # H2. Let's ensure that proceeding sections will land in a
125
+ # correct place.
126
+ (8 - level).times do |j|
127
+ section_arrays_by_level[level + j] = section_array
128
+ end
129
+ section_arrays_by_level[level - 1] << section
148
130
  else
149
- 1
131
+ content_array << e
150
132
  end
151
-
152
- section = previous_sections[elem]
153
- while section
154
- level = level.succ if elem.title.style == section.title.style
155
- section = previous_sections[section]
133
+ end
134
+ next new_array
135
+ end
136
+ elem
137
+ end
156
138
  end
157
- level.is_a?(Integer) ? "%02d" % level : level
158
- end
159
139
 
160
- determine_style = ->(elem) do
161
- style = elem.title.style || "section"
162
- style += "-"
163
- style
164
- end
140
+ def split_sections
141
+ max_level = Coradoc::Input::Html.config.split_sections
165
142
 
166
- @tree = Element::Base.visit(@tree) do |elem, dir|
167
- title = elem.title if elem.is_a?(Element::Section)
143
+ return unless max_level
168
144
 
169
- if title && title.level_int <= max_level
170
- if dir == :pre
171
- # In the PRE pass, we build a tree of sections, so that
172
- # we can compute numbers
173
- previous_sections[elem] = parent_sections[title.level_int]
174
- parent_sections[title.level_int] = elem
175
- parent_sections[(title.level_int + 1)..nil] = nil
145
+ sections = {}
146
+ parent_sections = []
147
+ previous_sections = {}
176
148
 
177
- elem
178
- else
179
- # In the POST pass, we replace the sections with their
180
- # include tag.
181
- section_file = "sections/"
182
- section_file += parent_sections[1..title.level_int].map do |parent|
183
- determine_style.(parent) + determine_section_id.(parent)
184
- end.join("/")
185
- section_file += ".adoc"
186
-
187
- sections[section_file] = elem
188
- up = "../" * (title.level_int - 1)
189
- "\ninclude::#{up}#{section_file}[]\n"
149
+ determine_section_id = ->(elem) do
150
+ level = if elem.title.style == "appendix"
151
+ "A"
152
+ else
153
+ 1
154
+ end
155
+
156
+ section = previous_sections[elem]
157
+ while section
158
+ level = level.succ if elem.title.style == section.title.style
159
+ section = previous_sections[section]
160
+ end
161
+ level.is_a?(Integer) ? "%02d" % level : level
190
162
  end
191
- else
192
- elem
193
- end
194
- end
195
163
 
196
- sections[nil] = @tree
197
- @tree = sections
198
- end
164
+ determine_style = ->(elem) do
165
+ style = elem.title.style || "section"
166
+ style += "-"
167
+ style
168
+ end
199
169
 
200
- def process
201
- extract_titles_from_lists
202
- collapse_meaningless_sections
203
- generate_meaningful_sections
204
- # Do it again to simplify the document further.
205
- # Since the structure is changed, we may have new meaningful
206
- # sections as only children of some meaningless sections.
207
- collapse_meaningless_sections
170
+ @tree = Element::Base.visit(@tree) do |elem, dir|
171
+ title = elem.title if elem.is_a?(Element::Section)
172
+
173
+ if title && title.level_int <= max_level
174
+ if dir == :pre
175
+ # In the PRE pass, we build a tree of sections, so that
176
+ # we can compute numbers
177
+ previous_sections[elem] = parent_sections[title.level_int]
178
+ parent_sections[title.level_int] = elem
179
+ parent_sections[(title.level_int + 1)..nil] = nil
180
+
181
+ elem
182
+ else
183
+ # In the POST pass, we replace the sections with their
184
+ # include tag.
185
+ section_file = "sections/"
186
+ section_file += parent_sections[1..title.level_int].map do |parent|
187
+ determine_style.(parent) + determine_section_id.(parent)
188
+ end.join("/")
189
+ section_file += ".adoc"
190
+
191
+ sections[section_file] = elem
192
+ up = "../" * (title.level_int - 1)
193
+ "\ninclude::#{up}#{section_file}[]\n"
194
+ end
195
+ else
196
+ elem
197
+ end
198
+ end
208
199
 
209
- split_sections
200
+ sections[nil] = @tree
201
+ @tree = sections
202
+ end
203
+
204
+ def process
205
+ extract_titles_from_lists
206
+ collapse_meaningless_sections
207
+ generate_meaningful_sections
208
+ # Do it again to simplify the document further.
209
+ # Since the structure is changed, we may have new meaningful
210
+ # sections as only children of some meaningless sections.
211
+ collapse_meaningless_sections
212
+
213
+ split_sections
210
214
 
211
- @tree
215
+ @tree
216
+ end
217
+ end
212
218
  end
213
219
  end
214
220
  end
@@ -13,47 +13,49 @@ require_relative "html/plugin"
13
13
  require_relative "html/postprocessor"
14
14
 
15
15
  module Coradoc
16
- module Input::HTML
17
- def self.convert(input, options = {})
18
- Coradoc::Input::HTML::HtmlConverter.convert(input, options)
19
- end
16
+ module Input
17
+ module Html
18
+ def self.convert(input, options = {})
19
+ Coradoc::Input::Html::HtmlConverter.convert(input, options)
20
+ end
20
21
 
21
- def self.to_coradoc(input, options = {})
22
- Input::HTML::HtmlConverter.to_coradoc(input, options)
23
- end
22
+ def self.to_coradoc(input, options = {})
23
+ Input::Html::HtmlConverter.to_coradoc(input, options)
24
+ end
24
25
 
25
- def self.config
26
- @config ||= Config.new
27
- yield @config if block_given?
28
- @config
29
- end
26
+ def self.config
27
+ @config ||= Config.new
28
+ yield @config if block_given?
29
+ @config
30
+ end
30
31
 
31
- def self.cleaner
32
- @cleaner ||= Cleaner.new
33
- end
32
+ def self.cleaner
33
+ @cleaner ||= Cleaner.new
34
+ end
34
35
 
35
- def self.processor_id
36
- :html
37
- end
36
+ def self.processor_id
37
+ :html
38
+ end
38
39
 
39
- def self.processor_match?(filename)
40
- %w[.html .htm].any? { |i| filename.downcase.end_with?(i) }
41
- end
40
+ def self.processor_match?(filename)
41
+ %w[.html .htm].any? { |i| filename.downcase.end_with?(i) }
42
+ end
42
43
 
43
- def self.processor_execute(input, options = {})
44
- to_coradoc(input, options)
45
- end
44
+ def self.processor_execute(input, options = {})
45
+ to_coradoc(input, options)
46
+ end
46
47
 
47
- def self.processor_postprocess(data, options)
48
- if options[:output_processor] == :adoc
49
- data.transform_values do |v|
50
- Input::HTML::HtmlConverter.cleanup_result(v, options)
48
+ def self.processor_postprocess(data, options)
49
+ if options[:output_processor] == :adoc
50
+ data.transform_values do |v|
51
+ Input::Html::HtmlConverter.cleanup_result(v, options)
52
+ end
53
+ else
54
+ data
51
55
  end
52
- else
53
- data
54
56
  end
55
- end
56
57
 
57
- Coradoc::Input.define(self)
58
+ Coradoc::Input.define(self)
59
+ end
58
60
  end
59
61
  end
data/lib/coradoc/oscal.rb CHANGED
@@ -15,7 +15,7 @@ module Coradoc
15
15
  def to_oscal
16
16
  {
17
17
  "metadata" => _doc.document_attributes.to_hash,
18
- "groups" => sections_as_groups,
18
+ "groups" => sections_as_groups,
19
19
  }
20
20
  end
21
21
 
@@ -37,7 +37,15 @@ module Coradoc
37
37
  sections.map do |section|
38
38
  Hash.new.tap do |hash|
39
39
  hash["id"] = section.id
40
- hash["props"] = build_oscal_props(section.glossaries.items)
40
+ # Use definition lists if present, otherwise fall back to glossaries
41
+ props_items = if section.respond_to?(:definition_lists) && section.definition_lists && !section.definition_lists.empty?
42
+ section.definition_lists.first.items
43
+ elsif section.glossaries && !section.glossaries.empty?
44
+ section.glossaries.items
45
+ else
46
+ []
47
+ end
48
+ hash["props"] = build_oscal_props(props_items)
41
49
  hash["parts"] = build_oscal_parts(section.sections)
42
50
  end
43
51
  end
@@ -71,16 +79,21 @@ module Coradoc
71
79
  end
72
80
 
73
81
  def build_oscal_props(attributes)
82
+ return [] unless attributes.respond_to?(:map)
83
+
74
84
  attributes.map do |attribute|
85
+ next unless attribute.respond_to?(:key) && attribute.respond_to?(:value)
86
+
75
87
  Hash.new.tap do |hash|
76
88
  hash["name"] = attribute.key.to_s.downcase
77
- hash["value"] = attribute.value
89
+ hash["value"] = attribute.value.to_s
78
90
  end
79
- end
91
+ end.compact
80
92
  end
81
93
 
82
94
  def build_oscal_prose(paragraph)
83
- paragraph&.texts&.join(" ")
95
+ return nil unless paragraph.respond_to?(:texts)
96
+ paragraph.texts&.join(" ")
84
97
  end
85
98
  end
86
99
  end
@@ -1,17 +1,19 @@
1
1
  module Coradoc
2
- module Output::Adoc
3
- def self.processor_id
4
- :adoc
5
- end
2
+ module Output
3
+ module Adoc
4
+ def self.processor_id
5
+ :adoc
6
+ end
6
7
 
7
- def self.processor_match?(filename)
8
- %w[.adoc].any? { |i| filename.downcase.end_with?(i) }
9
- end
8
+ def self.processor_match?(filename)
9
+ %w[.adoc].any? { |i| filename.downcase.end_with?(i) }
10
+ end
10
11
 
11
- def self.processor_execute(input, _options = {})
12
- input.transform_values { |i| Coradoc::Generator.gen_adoc(i) }
13
- end
12
+ def self.processor_execute(input, _options = {})
13
+ input.transform_values { |i| Coradoc::Generator.gen_adoc(i) }
14
+ end
14
15
 
15
- Coradoc::Output.define(self)
16
+ Coradoc::Output.define(self)
17
+ end
16
18
  end
17
19
  end
@@ -1,19 +1,21 @@
1
1
  module Coradoc
2
- module Output::CoradocTreeDebug
3
- def self.processor_id
4
- :coradoc_tree_debug
5
- end
2
+ module Output
3
+ module CoradocTreeDebug
4
+ def self.processor_id
5
+ :coradoc_tree_debug
6
+ end
6
7
 
7
- def self.processor_match?(filename)
8
- false
9
- end
8
+ def self.processor_match?(_filename)
9
+ false
10
+ end
10
11
 
11
- def self.processor_execute(input, _options = {})
12
- out = StringIO.new
13
- PP.pp(input, out)
14
- { nil => out.string }
15
- end
12
+ def self.processor_execute(input, _options = {})
13
+ out = StringIO.new
14
+ PP.pp(input, out)
15
+ { nil => out.string }
16
+ end
16
17
 
17
- Coradoc::Output.define(self)
18
+ Coradoc::Output.define(self)
19
+ end
18
20
  end
19
21
  end
@@ -3,20 +3,20 @@ module Coradoc
3
3
  module Asciidoc
4
4
  module Admonition
5
5
  def admonition_type
6
- str('NOTE') | str('TIP') | str('EDITOR') |
7
- str('IMPORTANT') | str('WARNING') | str('CAUTION') |
8
- str('TODO')
6
+ str("NOTE") | str("TIP") | str("EDITOR") |
7
+ str("IMPORTANT") | str("WARNING") | str("CAUTION") |
8
+ str("TODO")
9
9
  # requires atypical syntax for access?
10
10
  # | str('DANGER')
11
11
  # | str('SAFETY PRECAUTION')
12
12
  end
13
+
13
14
  def admonition_line
14
- admonition_type.as(:admonition_type) >> str(': ') >>
15
- (
15
+ admonition_type.as(:admonition_type) >> str(": ") >>
16
16
  (text.as(:text) >>
17
17
  line_ending.as(:line_break)
18
18
  ).repeat(1)
19
- ).as(:content)
19
+ .as(:content)
20
20
  end
21
21
  end
22
22
  end