coradoc 1.1.8 → 2.0.15

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 +205 -91
  6. data/lib/coradoc/configurable.rb +527 -0
  7. data/lib/coradoc/coradoc.rb +467 -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 +12 -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 +12 -0
  19. data/lib/coradoc/core_model/footnote.rb +92 -0
  20. data/lib/coradoc/core_model/horizontal_rule_block.rb +12 -0
  21. data/lib/coradoc/core_model/id_generator.rb +20 -0
  22. data/lib/coradoc/core_model/image.rb +66 -0
  23. data/lib/coradoc/core_model/inline_element.rb +172 -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 +15 -0
  27. data/lib/coradoc/core_model/literal_block.rb +12 -0
  28. data/lib/coradoc/core_model/metadata.rb +79 -0
  29. data/lib/coradoc/core_model/open_block.rb +12 -0
  30. data/lib/coradoc/core_model/paragraph_block.rb +12 -0
  31. data/lib/coradoc/core_model/pass_block.rb +12 -0
  32. data/lib/coradoc/core_model/quote_block.rb +14 -0
  33. data/lib/coradoc/core_model/reviewer_block.rb +12 -0
  34. data/lib/coradoc/core_model/sidebar_block.rb +12 -0
  35. data/lib/coradoc/core_model/source_block.rb +12 -0
  36. data/lib/coradoc/core_model/structural_element.rb +111 -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 +14 -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 +60 -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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa6087920cf2a472b02e4e44bdf3b984f42e99e39d0290c7621d431629e747f2
4
- data.tar.gz: 1f51521272e4ab8cb514ae1d0dafc7a68f83ecd95637cb7ed0a8c9fdfab7eba4
3
+ metadata.gz: 75ed45610af35c31ab134148781a5e5411ecc2949c443ca5b52d658b157452be
4
+ data.tar.gz: 16442662e51b42a22877f7ec0e7e5557829b529f6f4407a77700be7a2958abde
5
5
  SHA512:
6
- metadata.gz: 58a6a02fe1f0f6515da56c238a7068d18148cb91e3e172a2c8bdf7cc3af03363ba6ee4931a67f3d07ec9eaf5135a1d9092109a2c801aa37e516924a9b011be8d
7
- data.tar.gz: 18ca28c32f330ba3a0457f07e3fd92732f7d91895b555791d5648fa7903f50345cbed89b09fdcb5e6c34537dbddb1ed5ca9c0ea2531044738892ffa9b7fa341c
6
+ metadata.gz: fff4b4fe812e09f3e527a9c424bcaa712e9857cc56900974000a40bbfb50ae859df19e8cebf155d164ac830061f8b594e7d0f8798c91c89f1457146fbde4d2fb
7
+ data.tar.gz: 6141595e393440bf93ecd0248538e4608ab8e6404878c7cbe71ce3d526010241716aa98e4e1c9f830b32615d2a0456d5596da13d4ee13086d7b35eaef3e57ca2
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
+ --require spec_helper
1
2
  --format documentation
2
3
  --color
3
- --require spec_helper
data/Rakefile CHANGED
@@ -1,17 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
-
5
- if File.exist?(".codeclimate")
6
- ENV["CODECLIMATE_REPO_TOKEN"] = File.read(".codeclimate").strip
7
- end
8
-
9
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
10
5
 
11
6
  RSpec::Core::RakeTask.new(:spec)
12
- task default: :spec
13
7
 
14
- desc "Open an irb session preloaded with this library"
15
- task :console do
16
- sh "irb -Ilib -rcoradoc -rcoradoc/reverse_adoc"
17
- end
8
+ task default: :spec
data/exe/coradoc CHANGED
@@ -1,5 +1,24 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "coradoc/cli"
4
+ lib_path = File.expand_path('../lib', __dir__)
5
+ $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
4
6
 
5
- Coradoc::CLI.start
7
+ require 'coradoc'
8
+ require 'coradoc/cli'
9
+
10
+ GEM_TO_REQUIRE_PATH = {
11
+ 'coradoc-adoc' => 'coradoc/asciidoc',
12
+ 'coradoc-html' => 'coradoc/html',
13
+ 'coradoc-markdown' => 'coradoc/markdown',
14
+ 'coradoc-docx' => 'coradoc/docx'
15
+ }.freeze
16
+
17
+ GEM_TO_REQUIRE_PATH.each do |gem_name, require_path|
18
+ gem gem_name
19
+ require require_path
20
+ rescue LoadError
21
+ nil
22
+ end
23
+
24
+ Coradoc::CLI.start(ARGV)
data/lib/coradoc/cli.rb CHANGED
@@ -1,104 +1,218 @@
1
- require "coradoc"
2
- require "thor"
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
3
4
 
4
5
  module Coradoc
5
6
  class CLI < Thor
6
- package_name "coradoc"
7
-
8
- desc "convert [FILE]", "Convert document to another format"
9
-
10
- option :output,
11
- type: :string, aliases: "-o",
12
- desc: "Output file to write"
13
-
14
- option :input_format,
15
- type: :string, aliases: "-I",
16
- enum: Input.keys.map(&:to_s), default: nil,
17
- desc: "Define input format (defaults to input file extension)"
18
-
19
- option :output_format,
20
- type: :string, aliases: "-O",
21
- enum: Output.keys.map(&:to_s), default: nil,
22
- desc: "Define output format (defaults to output file extension)"
23
-
24
- at_least_one :output, :output_format
25
-
26
- option :require,
27
- type: :string, aliases: "-r",
28
- repeatable: true,
29
- desc: "Require additional Ruby file (eg. to load a plugin)"
30
-
31
- option :external_images,
32
- type: :boolean, aliases: "-e",
33
- desc: "Extract images from input document"
34
-
35
- option :unknown_tags,
36
- type: :string, aliases: "-u",
37
- enum: %w[pass_through drop bypass raise],
38
- default: "pass_through",
39
- desc: "Unknown tag handling"
40
-
41
- option :mathml2asciimath,
42
- type: :boolean, aliases: "-m",
43
- desc: "Convert MathML to AsciiMath"
44
-
45
- option :track_time,
46
- type: :boolean,
47
- desc: "Track time spent on each step"
48
-
49
- option :split_sections,
50
- type: :numeric,
51
- default: 0, banner: "LEVEL",
52
- desc: "Split sections into separate files up to a provided level"
53
-
54
- def convert(input = nil)
55
- options[:require]&.each { |r| Kernel.require r }
56
-
57
- config = {
58
- input_options: input_options = {},
59
- input_processor: nil,
60
- output_options: {},
61
- output_processor: nil,
62
- }
63
-
64
- config[:input_processor] = options[:input_format]&.to_sym
65
- config[:output_processor] = options[:output_format]&.to_sym
66
-
67
- %i[
68
- external_images
69
- unknown_tags
70
- mathml2asciimath
71
- track_time
72
- split_sections
73
- ].each do |i|
74
- input_options[i] = options[i]
7
+ package_name 'Coradoc'
8
+
9
+ def self.exit_on_failure?
10
+ true
11
+ end
12
+
13
+ desc 'convert FILE', 'Convert a document from one format to another'
14
+ option :to, aliases: '-t', desc: 'Target format (adoc, html, md)', type: :string
15
+ option :output, aliases: '-o', desc: 'Output file path (default: stdout)', type: :string
16
+ option :from, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
17
+ option :theme, desc: 'HTML theme (classic, modern)', type: :string, default: 'classic'
18
+ option :verbose, desc: 'Enable verbose output', type: :boolean, default: false
19
+ option :asset_delivery, desc: 'Asset delivery mode (embedded, external)', type: :string, default: 'embedded'
20
+ option :toc, desc: 'Include table of contents', type: :boolean, default: false
21
+ option :toc_levels, desc: 'TOC depth (1-5)', type: :numeric, default: 2
22
+ option :section_numbers, desc: 'Enable section numbering', type: :boolean, default: false
23
+ option :section_number_levels, desc: 'Section numbering depth (1-6)', type: :numeric, default: 3
24
+ option :lang, desc: 'Document language code', type: :string, default: 'en'
25
+ def convert(file)
26
+ source_format = resolve_format(file, :from)
27
+ target_format = options[:to] ? Coradoc.normalize_format(options[:to]) : Coradoc.resolve_output_format(options[:output])
28
+
29
+ unless source_format && target_format
30
+ error 'Error: Could not determine format. Use --from and --to options.'
31
+ exit 1
75
32
  end
76
33
 
77
- output = options[:output]
78
-
79
- begin
80
- Coradoc::Converter.(input, output, **config)
81
- rescue Converter::NoInputPathError => e
82
- warn "You must provide INPUT file as a file for this optionset."
83
- warn "Detail: #{e.message}"
84
- rescue Converter::NoOutputPathError => e
85
- warn "You must provide OUTPUT file as a file for this optionset."
86
- warn "Detail: #{e.message}"
87
- rescue Converter::NoProcessorError => e
88
- warn "No processor found for given input/output."
89
- warn "Hint: set -I/--input-format or -O/--output-format option."
90
- warn "Detail: #{e.message}"
34
+ unless Coradoc.serialize_format?(target_format)
35
+ error "Error: Converting to #{target_format} is not yet supported."
36
+ exit 1
91
37
  end
38
+
39
+ verbose_log "Converting #{file} (#{source_format}) to #{target_format}"
40
+
41
+ opts = build_convert_options
42
+ result = Coradoc.convert_file(file, from: source_format, to: target_format, **opts)
43
+ write_output(result, options[:output])
44
+ rescue Coradoc::Error => e
45
+ error "Error: #{e.message}"
46
+ exit 1
47
+ rescue StandardError => e
48
+ error "Error: #{e.message}"
49
+ verbose_log e.backtrace.join("\n") if options[:verbose]
50
+ exit 1
51
+ end
52
+
53
+ desc 'formats', 'List supported formats'
54
+ def formats
55
+ caps = Coradoc.format_capabilities
56
+
57
+ puts 'Supported formats:'
58
+ puts ''
59
+ puts ' Source formats (can read):'
60
+ caps.each { |name, c| puts " - #{name}" if c[:parse] }
61
+ puts ''
62
+ puts ' Target formats (can write):'
63
+ caps.each { |name, c| puts " - #{name}" if c[:serialize] }
92
64
  end
93
65
 
94
- desc "version", "display version information"
66
+ desc 'version', 'Display Coradoc version'
95
67
  def version
96
- puts "Coradoc: v#{Coradoc::VERSION}"
97
- puts "[dependency] WordToMarkdown: v#{WordToMarkdown::VERSION}"
98
- if Gem.win_platform?
99
- puts "[dependency] LibreOffice: version not available on Windows"
68
+ puts "Coradoc #{Coradoc::VERSION}"
69
+ end
70
+
71
+ desc 'validate FILE', 'Validate a document against its schema'
72
+ option :format, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
73
+ option :strict, desc: 'Enable strict validation mode', type: :boolean, default: false
74
+ def validate(file)
75
+ source_format = resolve_format(file)
76
+ unless source_format
77
+ error 'Error: Could not determine format. Use --format option.'
78
+ exit 1
79
+ end
80
+
81
+ verbose_log "Validating #{file} (#{source_format})"
82
+
83
+ result = Coradoc.validate_file(file, format: source_format)
84
+
85
+ if result.valid?
86
+ puts '✓ Document is valid'
87
+ else
88
+ error "✗ #{result}"
89
+ exit 1
90
+ end
91
+ rescue Coradoc::Error => e
92
+ error "Error: #{e.message}"
93
+ exit 1
94
+ rescue StandardError => e
95
+ error "Error: #{e.message}"
96
+ verbose_log e.backtrace.join("\n") if options[:verbose]
97
+ exit 1
98
+ end
99
+
100
+ desc 'query FILE SELECTOR', 'Query document elements using CSS-like selectors'
101
+ option :format, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
102
+ option :output, aliases: '-o', desc: 'Output format (text, json)', type: :string, default: 'text'
103
+ def query(file, selector)
104
+ source_format = resolve_format(file)
105
+ unless source_format
106
+ error 'Error: Could not determine format. Use --format option.'
107
+ exit 1
108
+ end
109
+
110
+ verbose_log "Querying #{file} with selector: #{selector}"
111
+
112
+ doc = Coradoc.parse_file(file, format: source_format)
113
+ results = Coradoc::Query.query(doc, selector)
114
+
115
+ if results.empty?
116
+ puts "No elements found matching: #{selector}"
100
117
  else
101
- puts "[dependency] LibreOffice: v#{WordToMarkdown.soffice.version}"
118
+ case options[:output]
119
+ when 'json'
120
+ require 'json'
121
+ puts JSON.pretty_generate(results.map { |r| Coradoc.describe_element(r) })
122
+ else
123
+ puts "Found #{results.length} element(s):"
124
+ results.each_with_index do |elem, i|
125
+ puts " #{i + 1}. #{Coradoc.describe_element(elem)}"
126
+ end
127
+ end
128
+ end
129
+ rescue Coradoc::Error => e
130
+ error "Error: #{e.message}"
131
+ exit 1
132
+ rescue StandardError => e
133
+ error "Error: #{e.message}"
134
+ verbose_log e.backtrace.join("\n") if options[:verbose]
135
+ exit 1
136
+ end
137
+
138
+ desc 'info FILE', 'Display document metadata and statistics'
139
+ option :format, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
140
+ def info(file)
141
+ source_format = resolve_format(file)
142
+ unless source_format
143
+ error 'Error: Could not determine format. Use --format option.'
144
+ exit 1
145
+ end
146
+
147
+ verbose_log "Analyzing #{file} (#{source_format})"
148
+
149
+ doc = Coradoc.parse_file(file, format: source_format)
150
+ stats = Coradoc.document_stats(doc)
151
+ fi = Coradoc.file_info(file)
152
+
153
+ puts 'Document Information'
154
+ puts '=' * 40
155
+ puts "Format: #{source_format}"
156
+ puts "File size: #{fi[:size]} bytes"
157
+ puts "Line count: #{fi[:lines]}" if fi[:lines]
158
+ puts "Title: #{stats[:title]}" if stats[:title]
159
+ puts "Child elements: #{stats[:child_count]}" if stats[:child_count]
160
+
161
+ if stats[:element_counts]&.any?
162
+ puts ''
163
+ puts 'Element Counts:'
164
+ stats[:element_counts].each { |type, count| puts " #{type}: #{count}" }
165
+ end
166
+ rescue Coradoc::Error => e
167
+ error "Error: #{e.message}"
168
+ exit 1
169
+ rescue StandardError => e
170
+ error "Error: #{e.message}"
171
+ verbose_log e.backtrace.join("\n") if options[:verbose]
172
+ exit 1
173
+ end
174
+
175
+ map '-v' => :version, '--version' => :version
176
+
177
+ private
178
+
179
+ def resolve_format(file, option_key = :format)
180
+ raw = options[option_key]
181
+ raw ? Coradoc.normalize_format(raw) : Coradoc.detect_format(file)
182
+ end
183
+
184
+ def write_output(content, output_file)
185
+ if output_file
186
+ File.write(output_file, content)
187
+ verbose_log "Written to: #{output_file}"
188
+ else
189
+ puts content
190
+ end
191
+ end
192
+
193
+ def verbose_log(message)
194
+ warn "[verbose] #{message}" if options[:verbose]
195
+ end
196
+
197
+ def error(message)
198
+ warn message
199
+ end
200
+
201
+ CONVERT_OPTIONS = %i[
202
+ toc toc_levels section_numbers section_number_levels
203
+ lang theme asset_delivery
204
+ ].freeze
205
+ private_constant :CONVERT_OPTIONS
206
+
207
+ SYMBOL_OPTIONS = %i[theme asset_delivery].freeze
208
+ private_constant :SYMBOL_OPTIONS
209
+
210
+ def build_convert_options
211
+ CONVERT_OPTIONS.each_with_object({}) do |key, opts|
212
+ value = options[key]
213
+ next unless value
214
+
215
+ opts[key] = SYMBOL_OPTIONS.include?(key) ? value.to_sym : value
102
216
  end
103
217
  end
104
218
  end