coradoc 2.0.1 → 2.0.3
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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +77 -146
- data/coradoc-adoc/lib/coradoc/asciidoc/model/base.rb +4 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/model/document.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/model/include.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/model/resolver.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/model/serialization/asciidoc_transform.rb +3 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/model/table_row.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/model/text_element.rb +4 -8
- data/coradoc-adoc/lib/coradoc/asciidoc/parse_error.rb +6 -6
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/adoc_serializer.rb +5 -10
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/formatter.rb +4 -3
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/base.rb +8 -20
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/block/core.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/document.rb +3 -6
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/inline/strikethrough.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/serializer/serializers/list/item.rb +5 -9
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model.rb +26 -34
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/from_core_model_registrations.rb +18 -18
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model.rb +96 -123
- data/coradoc-adoc/lib/coradoc/asciidoc/transform/to_core_model_registrations.rb +10 -6
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/header_rules.rb +5 -5
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/list_rules.rb +2 -2
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer/structural_rules.rb +1 -1
- data/coradoc-adoc/lib/coradoc/asciidoc/transformer.rb +5 -5
- data/coradoc-adoc/lib/coradoc/asciidoc.rb +1 -1
- data/coradoc-adoc/lib/coradoc/util/asciidoc.rb +4 -3
- data/coradoc-adoc/spec/coradoc/asciidoc/transform/from_core_model_spec.rb +4 -2
- data/coradoc-docx/lib/coradoc/docx/transform/context.rb +1 -1
- data/coradoc-docx/lib/coradoc/docx/transform/from_core_model.rb +13 -6
- data/coradoc-docx/lib/coradoc/docx/transform/numbering_resolver.rb +9 -7
- data/coradoc-docx/lib/coradoc/docx/transform/ordered_content.rb +2 -2
- data/coradoc-docx/lib/coradoc/docx/transform/rules/image_rule.rb +4 -1
- data/coradoc-docx/lib/coradoc/docx/transform/rules/math_rule.rb +2 -1
- data/coradoc-docx/lib/coradoc/docx/transform/rules/run_rule.rb +20 -30
- data/coradoc-docx/lib/coradoc/docx/transform/rules/simple_field_rule.rb +7 -5
- data/coradoc-docx/lib/coradoc/docx/transform/rules/table_rule.rb +3 -5
- data/coradoc-docx/lib/coradoc/docx/transform/style_resolver.rb +19 -24
- data/coradoc-docx/lib/coradoc/docx/transform/to_core_model.rb +18 -11
- data/coradoc-docx/lib/coradoc/docx.rb +6 -4
- data/coradoc-docx/spec/coradoc/docx/transform/from_core_model_spec.rb +5 -2
- data/coradoc-docx/spec/coradoc/docx/transform/rules/rule_unit_spec.rb +27 -7
- data/coradoc-docx/spec/coradoc/docx/transform/to_core_model_spec.rb +6 -2
- data/coradoc-html/lib/coradoc/html/base.rb +3 -7
- data/coradoc-html/lib/coradoc/html/converter_base.rb +5 -15
- data/coradoc-html/lib/coradoc/html/converters/base.rb +22 -28
- data/coradoc-html/lib/coradoc/html/converters/comment_line.rb +2 -2
- data/coradoc-html/lib/coradoc/html/converters/link.rb +1 -1
- data/coradoc-html/lib/coradoc/html/converters/list_item.rb +3 -3
- data/coradoc-html/lib/coradoc/html/converters/ordered.rb +1 -1
- data/coradoc-html/lib/coradoc/html/converters/span.rb +2 -2
- data/coradoc-html/lib/coradoc/html/converters/table.rb +3 -3
- data/coradoc-html/lib/coradoc/html/converters/table_cell.rb +14 -28
- data/coradoc-html/lib/coradoc/html/converters/table_row.rb +2 -2
- data/coradoc-html/lib/coradoc/html/converters/text_element.rb +1 -5
- data/coradoc-html/lib/coradoc/html/input/converters/a.rb +2 -2
- data/coradoc-html/lib/coradoc/html/input/converters/dl.rb +1 -1
- data/coradoc-html/lib/coradoc/html/input/converters/figure.rb +2 -2
- data/coradoc-html/lib/coradoc/html/input/converters/markup.rb +3 -3
- data/coradoc-html/lib/coradoc/html/input/converters/p.rb +1 -1
- data/coradoc-html/lib/coradoc/html/input/converters/td.rb +1 -1
- data/coradoc-html/lib/coradoc/html/input/converters.rb +1 -2
- data/coradoc-html/lib/coradoc/html/input/html_converter.rb +3 -3
- data/coradoc-html/lib/coradoc/html/input/plugin.rb +2 -2
- data/coradoc-html/lib/coradoc/html/renderer.rb +4 -6
- data/coradoc-html/lib/coradoc/html/theme/base.rb +2 -3
- data/coradoc-html/lib/coradoc/html/theme/classic_renderer.rb +9 -12
- data/coradoc-html/lib/coradoc/html/theme/modern/serializers/document_serializer.rb +3 -3
- data/coradoc-html/lib/coradoc/html.rb +1 -1
- data/coradoc-markdown/lib/coradoc/markdown/model/base.rb +6 -5
- data/coradoc-markdown/lib/coradoc/markdown/serializer.rb +2 -2
- data/coradoc-markdown/lib/coradoc/markdown/toc_generator.rb +4 -5
- data/coradoc-markdown/lib/coradoc/markdown/transform/from_core_model.rb +2 -2
- data/coradoc-markdown/lib/coradoc/markdown/transformer.rb +5 -3
- data/coradoc-markdown/lib/coradoc/markdown.rb +1 -1
- data/lib/coradoc/configurable.rb +6 -2
- data/lib/coradoc/coradoc.rb +18 -16
- data/lib/coradoc/core_model/base.rb +3 -3
- data/lib/coradoc/core_model/list_item.rb +3 -3
- data/lib/coradoc/core_model/toc_generator.rb +1 -1
- data/lib/coradoc/document_manipulator.rb +9 -13
- data/lib/coradoc/format_module.rb +16 -4
- data/lib/coradoc/input.rb +1 -1
- data/lib/coradoc/output.rb +1 -1
- data/lib/coradoc/query.rb +38 -186
- data/lib/coradoc/registry.rb +5 -7
- data/lib/coradoc/serializer/registry.rb +3 -5
- data/lib/coradoc/validation.rb +40 -21
- data/lib/coradoc/version.rb +1 -1
- metadata +1 -1
data/lib/coradoc/coradoc.rb
CHANGED
|
@@ -67,6 +67,7 @@ module Coradoc
|
|
|
67
67
|
# @param options [Hash] optional configuration (e.g., extensions: [])
|
|
68
68
|
# @return [void]
|
|
69
69
|
def register_format(format_name, format_module, **options)
|
|
70
|
+
format_module.extend(FormatModule::Interface) unless format_module.is_a?(FormatModule::Interface)
|
|
70
71
|
registry.register(format_name, format_module, options)
|
|
71
72
|
FormatModule.validate!(format_module, format_name)
|
|
72
73
|
end
|
|
@@ -148,7 +149,7 @@ module Coradoc
|
|
|
148
149
|
return model if model.is_a?(CoreModel::Base)
|
|
149
150
|
|
|
150
151
|
registry.each_value do |format_module|
|
|
151
|
-
next unless format_module.
|
|
152
|
+
next unless format_module.handles_model?(model)
|
|
152
153
|
|
|
153
154
|
return format_module.to_core(model)
|
|
154
155
|
end
|
|
@@ -195,7 +196,7 @@ module Coradoc
|
|
|
195
196
|
# Coradoc.detect_format("file.md") # => :markdown
|
|
196
197
|
def detect_format(filename)
|
|
197
198
|
ext = File.extname(filename).downcase
|
|
198
|
-
registry.
|
|
199
|
+
registry.each_key do |name|
|
|
199
200
|
opts = registry.options_for(name)
|
|
200
201
|
return name if opts[:extensions]&.include?(ext)
|
|
201
202
|
end
|
|
@@ -243,7 +244,7 @@ module Coradoc
|
|
|
243
244
|
# @example
|
|
244
245
|
# html = Coradoc.convert_file("document.adoc", to: :html)
|
|
245
246
|
# adoc = Coradoc.convert_file("report.docx", to: :asciidoc)
|
|
246
|
-
def convert_file(path, from: nil,
|
|
247
|
+
def convert_file(path, to:, from: nil, **options)
|
|
247
248
|
source_format = from || detect_format(path)
|
|
248
249
|
raise UnsupportedFormatError, "Could not detect format for: #{path}" unless source_format
|
|
249
250
|
|
|
@@ -270,7 +271,7 @@ module Coradoc
|
|
|
270
271
|
return nil unless name
|
|
271
272
|
|
|
272
273
|
key = name.to_s.downcase
|
|
273
|
-
registry.
|
|
274
|
+
registry.each_key do |fmt_name|
|
|
274
275
|
opts = registry.options_for(fmt_name)
|
|
275
276
|
return fmt_name if opts[:aliases]&.include?(key)
|
|
276
277
|
end
|
|
@@ -285,9 +286,7 @@ module Coradoc
|
|
|
285
286
|
mod = get_format(format)
|
|
286
287
|
return false unless mod
|
|
287
288
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
true
|
|
289
|
+
mod.serialize?
|
|
291
290
|
end
|
|
292
291
|
|
|
293
292
|
# Check if a format supports parsing (reading input)
|
|
@@ -296,7 +295,9 @@ module Coradoc
|
|
|
296
295
|
# @return [Boolean] true if the format can parse
|
|
297
296
|
def parse_format?(format)
|
|
298
297
|
mod = get_format(format)
|
|
299
|
-
|
|
298
|
+
return false unless mod
|
|
299
|
+
|
|
300
|
+
mod.public_methods.include?(:parse_to_core) || mod.public_methods.include?(:parse)
|
|
300
301
|
end
|
|
301
302
|
|
|
302
303
|
# Get capability summary for all registered formats
|
|
@@ -361,9 +362,9 @@ module Coradoc
|
|
|
361
362
|
def document_stats(doc)
|
|
362
363
|
stats = {}
|
|
363
364
|
|
|
364
|
-
stats[:title] = doc.title if doc.
|
|
365
|
+
stats[:title] = doc.title if doc.title
|
|
365
366
|
|
|
366
|
-
if doc.
|
|
367
|
+
if doc.is_a?(CoreModel::StructuralElement)
|
|
367
368
|
stats[:child_count] = count_elements(doc)
|
|
368
369
|
stats[:element_counts] = count_element_types(doc)
|
|
369
370
|
end
|
|
@@ -379,9 +380,9 @@ module Coradoc
|
|
|
379
380
|
return elem.to_s unless elem.is_a?(CoreModel::Base)
|
|
380
381
|
|
|
381
382
|
type = elem.class.name.split('::').last
|
|
382
|
-
if elem.
|
|
383
|
+
if elem.title
|
|
383
384
|
"#{type}: #{elem.title}"
|
|
384
|
-
elsif elem.
|
|
385
|
+
elsif elem.is_a?(CoreModel::Block) && elem.content
|
|
385
386
|
preview = elem.content.to_s[0..50]
|
|
386
387
|
preview += '...' if elem.content.to_s.length > 50
|
|
387
388
|
"#{type}: #{preview}"
|
|
@@ -411,10 +412,10 @@ module Coradoc
|
|
|
411
412
|
private
|
|
412
413
|
|
|
413
414
|
def count_elements(doc)
|
|
414
|
-
return 0 unless doc.
|
|
415
|
+
return 0 unless doc.is_a?(CoreModel::StructuralElement)
|
|
415
416
|
|
|
416
417
|
doc.children.sum do |child|
|
|
417
|
-
1 + (child.
|
|
418
|
+
1 + (child.is_a?(CoreModel::StructuralElement) ? count_elements(child) : 0)
|
|
418
419
|
end
|
|
419
420
|
end
|
|
420
421
|
|
|
@@ -423,11 +424,12 @@ module Coradoc
|
|
|
423
424
|
visitor = Class.new(Visitor::Base) do
|
|
424
425
|
define_method(:visit) do |element|
|
|
425
426
|
if element.is_a?(CoreModel::Base)
|
|
426
|
-
|
|
427
|
+
has_element_type = element.is_a?(CoreModel::StructuralElement) || element.is_a?(CoreModel::Block)
|
|
428
|
+
type_key = if has_element_type && element.element_type
|
|
427
429
|
element.element_type
|
|
428
430
|
else
|
|
429
431
|
element.class.name.split('::').last
|
|
430
|
-
|
|
432
|
+
.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, '')
|
|
431
433
|
end
|
|
432
434
|
counts[type_key] += 1
|
|
433
435
|
end
|
|
@@ -136,7 +136,7 @@ module Coradoc
|
|
|
136
136
|
children_arr.map do |child|
|
|
137
137
|
if child.is_a?(String)
|
|
138
138
|
child
|
|
139
|
-
elsif child.
|
|
139
|
+
elsif child.is_a?(Lutaml::Model::Serializable)
|
|
140
140
|
child.to_hash
|
|
141
141
|
else
|
|
142
142
|
child.to_s
|
|
@@ -156,8 +156,8 @@ module Coradoc
|
|
|
156
156
|
|
|
157
157
|
# Compare a single attribute between this model and another
|
|
158
158
|
def compare_attribute(attr, other)
|
|
159
|
-
self_value =
|
|
160
|
-
other_value = other.
|
|
159
|
+
self_value = public_send(attr)
|
|
160
|
+
other_value = other.public_send(attr)
|
|
161
161
|
|
|
162
162
|
case self_value
|
|
163
163
|
when Array
|
|
@@ -45,13 +45,13 @@ module Coradoc
|
|
|
45
45
|
|
|
46
46
|
# Delegate nested to nested_list (lutaml attribute added by list_block.rb)
|
|
47
47
|
def nested
|
|
48
|
-
nested_list
|
|
48
|
+
nested_list
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# Set nested list
|
|
52
52
|
# @param value [ListBlock, nil] nested list block
|
|
53
53
|
def nested=(value)
|
|
54
|
-
self.nested_list = value
|
|
54
|
+
self.nested_list = value
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
# Convert to hash representation
|
|
@@ -62,7 +62,7 @@ module Coradoc
|
|
|
62
62
|
marker: marker,
|
|
63
63
|
content: content,
|
|
64
64
|
nested_list: nested&.to_h,
|
|
65
|
-
children: children&.map { |child| child.
|
|
65
|
+
children: children&.map { |child| child.is_a?(CoreModel::Base) ? child.to_h : child }
|
|
66
66
|
}.compact
|
|
67
67
|
end
|
|
68
68
|
|
|
@@ -71,7 +71,7 @@ module Coradoc
|
|
|
71
71
|
# Find all sections in the document within level range
|
|
72
72
|
def find_sections(element, min_level, max_level)
|
|
73
73
|
sections = []
|
|
74
|
-
return sections unless element.
|
|
74
|
+
return sections unless element.is_a?(CoreModel::StructuralElement)
|
|
75
75
|
|
|
76
76
|
Array(element.children).each do |child|
|
|
77
77
|
next unless child.is_a?(CoreModel::StructuralElement)
|
|
@@ -22,7 +22,7 @@ module Coradoc
|
|
|
22
22
|
DocumentManipulator.new(filtered)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def transform_text
|
|
25
|
+
def transform_text
|
|
26
26
|
return self unless block_given?
|
|
27
27
|
|
|
28
28
|
Visitor::Transformer.new do |element|
|
|
@@ -36,13 +36,11 @@ module Coradoc
|
|
|
36
36
|
self
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
def transform_headings
|
|
39
|
+
def transform_headings
|
|
40
40
|
return self unless block_given?
|
|
41
41
|
|
|
42
42
|
Visitor::Transformer.new do |element|
|
|
43
|
-
if element.is_a?(CoreModel::StructuralElement) && element.title.is_a?(String)
|
|
44
|
-
element.title = yield(element.title)
|
|
45
|
-
end
|
|
43
|
+
element.title = yield(element.title) if element.is_a?(CoreModel::StructuralElement) && element.title.is_a?(String)
|
|
46
44
|
end.visit(@document)
|
|
47
45
|
self
|
|
48
46
|
end
|
|
@@ -64,7 +62,7 @@ module Coradoc
|
|
|
64
62
|
|
|
65
63
|
def remove_elements(element_type)
|
|
66
64
|
Visitor::Transformer.new do |element|
|
|
67
|
-
next unless element.
|
|
65
|
+
next unless element.is_a?(CoreModel::StructuralElement) && element.children
|
|
68
66
|
|
|
69
67
|
element.children.reject! do |child|
|
|
70
68
|
match_element_type?(child, element_type)
|
|
@@ -128,15 +126,13 @@ module Coradoc
|
|
|
128
126
|
end
|
|
129
127
|
|
|
130
128
|
def filter_sections(element, level: nil, title: nil)
|
|
131
|
-
if element.
|
|
129
|
+
if element.is_a?(CoreModel::StructuralElement) && element.children
|
|
132
130
|
element.children = element.children
|
|
133
131
|
.map { |child| filter_sections(child, level: level, title: title) }
|
|
134
132
|
.compact
|
|
135
133
|
end
|
|
136
134
|
|
|
137
|
-
if element.is_a?(CoreModel::StructuralElement) && element.section? && !element.document?
|
|
138
|
-
return nil unless section_matches?(element, level: level, title: title)
|
|
139
|
-
end
|
|
135
|
+
return nil if element.is_a?(CoreModel::StructuralElement) && element.section? && !element.document? && !section_matches?(element, level: level, title: title)
|
|
140
136
|
|
|
141
137
|
element
|
|
142
138
|
end
|
|
@@ -154,7 +150,7 @@ module Coradoc
|
|
|
154
150
|
element_title = section.title || ''
|
|
155
151
|
case title
|
|
156
152
|
when String then return false unless element_title.include?(title)
|
|
157
|
-
when Regexp then return false unless element_title
|
|
153
|
+
when Regexp then return false unless element_title&.match?(title)
|
|
158
154
|
end
|
|
159
155
|
end
|
|
160
156
|
|
|
@@ -163,7 +159,7 @@ module Coradoc
|
|
|
163
159
|
|
|
164
160
|
def collect_sections(element, max_level: 3, current_level: 1)
|
|
165
161
|
sections = []
|
|
166
|
-
return sections unless element.
|
|
162
|
+
return sections unless element.is_a?(CoreModel::StructuralElement)
|
|
167
163
|
|
|
168
164
|
element.children.each do |child|
|
|
169
165
|
next unless child.is_a?(CoreModel::StructuralElement) &&
|
|
@@ -186,7 +182,7 @@ module Coradoc
|
|
|
186
182
|
when CoreModel::Base
|
|
187
183
|
cloned = element.class.new
|
|
188
184
|
element.class.attributes.each_key do |name|
|
|
189
|
-
cloned.
|
|
185
|
+
cloned.public_send("#{name}=", deep_clone(element.public_send(name)))
|
|
190
186
|
end
|
|
191
187
|
cloned
|
|
192
188
|
when Array
|
|
@@ -19,17 +19,29 @@ module Coradoc
|
|
|
19
19
|
MINIMUM_PARSE_METHODS = %i[parse_to_core parse].freeze
|
|
20
20
|
REQUIRED_METHODS = %i[serialize].freeze
|
|
21
21
|
|
|
22
|
+
# Default implementations for optional format module methods.
|
|
23
|
+
# Format modules are auto-extended with this during registration.
|
|
24
|
+
module Interface
|
|
25
|
+
def handles_model?(_model)
|
|
26
|
+
false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def serialize?
|
|
30
|
+
true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
22
34
|
# Validate that a format module implements the minimum interface.
|
|
23
35
|
# Warns to $stderr if methods are missing. Returns true if valid.
|
|
24
36
|
def self.validate!(format_module, format_name)
|
|
25
|
-
has_parse = MINIMUM_PARSE_METHODS.any? { |m| format_module.
|
|
26
|
-
has_serialize = REQUIRED_METHODS.all? { |m| format_module.
|
|
37
|
+
has_parse = MINIMUM_PARSE_METHODS.any? { |m| format_module.public_methods.include?(m) }
|
|
38
|
+
has_serialize = REQUIRED_METHODS.all? { |m| format_module.public_methods.include?(m) }
|
|
27
39
|
|
|
28
40
|
return true if has_parse && has_serialize
|
|
29
41
|
|
|
30
42
|
missing = []
|
|
31
|
-
missing <<
|
|
32
|
-
missing <<
|
|
43
|
+
missing << 'parse_to_core or parse' unless has_parse
|
|
44
|
+
missing << 'serialize' unless has_serialize
|
|
33
45
|
warn "Coradoc: format :#{format_name} (#{format_module}) missing: #{missing.join(', ')}"
|
|
34
46
|
false
|
|
35
47
|
end
|
data/lib/coradoc/input.rb
CHANGED