coradoc 1.1.8 → 2.0.12

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 +185 -91
  6. data/lib/coradoc/configurable.rb +527 -0
  7. data/lib/coradoc/coradoc.rb +463 -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 +10 -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 +10 -0
  19. data/lib/coradoc/core_model/footnote.rb +92 -0
  20. data/lib/coradoc/core_model/horizontal_rule_block.rb +10 -0
  21. data/lib/coradoc/core_model/id_generator.rb +16 -0
  22. data/lib/coradoc/core_model/image.rb +66 -0
  23. data/lib/coradoc/core_model/inline_element.rb +140 -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 +13 -0
  27. data/lib/coradoc/core_model/literal_block.rb +10 -0
  28. data/lib/coradoc/core_model/metadata.rb +79 -0
  29. data/lib/coradoc/core_model/open_block.rb +10 -0
  30. data/lib/coradoc/core_model/paragraph_block.rb +10 -0
  31. data/lib/coradoc/core_model/pass_block.rb +10 -0
  32. data/lib/coradoc/core_model/quote_block.rb +12 -0
  33. data/lib/coradoc/core_model/reviewer_block.rb +10 -0
  34. data/lib/coradoc/core_model/sidebar_block.rb +10 -0
  35. data/lib/coradoc/core_model/source_block.rb +10 -0
  36. data/lib/coradoc/core_model/structural_element.rb +94 -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 +12 -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 +49 -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: 6828a80bfe7322793f21da830475a7fe98af2dec11d72ef985ed215b64018d75
4
+ data.tar.gz: 317a34a26bbd9587a4e13c76ff0e59b89e5bf9961916cad341c213d42537e817
5
5
  SHA512:
6
- metadata.gz: 58a6a02fe1f0f6515da56c238a7068d18148cb91e3e172a2c8bdf7cc3af03363ba6ee4931a67f3d07ec9eaf5135a1d9092109a2c801aa37e516924a9b011be8d
7
- data.tar.gz: 18ca28c32f330ba3a0457f07e3fd92732f7d91895b555791d5648fa7903f50345cbed89b09fdcb5e6c34537dbddb1ed5ca9c0ea2531044738892ffa9b7fa341c
6
+ metadata.gz: ceee0f035da234907f3b31848ee5646d20dcc586e46b0ed6f76c6b6630b3aaefbf5020b8d019dd8e97b5a2e4ac7313ab4c30ab15d316dc788745bc37a4970e85
7
+ data.tar.gz: d7c1007737f72a87dfd0cb929bd6ef693783548960f5468603960c5b73a15eb93005fd2f7335446eb94fa8d9ff92eb3412632f04fb7796c4e197a8364bc7a5df
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,105 +1,199 @@
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
+ def convert(file)
21
+ source_format = resolve_format(file, :from)
22
+ target_format = options[:to] ? Coradoc.normalize_format(options[:to]) : Coradoc.resolve_output_format(options[:output])
23
+
24
+ unless source_format && target_format
25
+ error 'Error: Could not determine format. Use --from and --to options.'
26
+ exit 1
75
27
  end
76
28
 
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}"
29
+ unless Coradoc.serialize_format?(target_format)
30
+ error "Error: Converting to #{target_format} is not yet supported."
31
+ exit 1
91
32
  end
33
+
34
+ verbose_log "Converting #{file} (#{source_format}) to #{target_format}"
35
+
36
+ opts = {}
37
+ opts[:theme] = options[:theme].to_sym if options[:theme]
38
+ opts[:asset_delivery] = options[:"asset-delivery"].to_sym if options[:"asset-delivery"]
39
+
40
+ result = Coradoc.convert_file(file, from: source_format, to: target_format, **opts)
41
+ write_output(result, options[:output])
42
+ rescue Coradoc::Error => e
43
+ error "Error: #{e.message}"
44
+ exit 1
45
+ rescue StandardError => e
46
+ error "Error: #{e.message}"
47
+ verbose_log e.backtrace.join("\n") if options[:verbose]
48
+ exit 1
92
49
  end
93
50
 
94
- desc "version", "display version information"
51
+ desc 'formats', 'List supported formats'
52
+ def formats
53
+ caps = Coradoc.format_capabilities
54
+
55
+ puts 'Supported formats:'
56
+ puts ''
57
+ puts ' Source formats (can read):'
58
+ caps.each { |name, c| puts " - #{name}" if c[:parse] }
59
+ puts ''
60
+ puts ' Target formats (can write):'
61
+ caps.each { |name, c| puts " - #{name}" if c[:serialize] }
62
+ end
63
+
64
+ desc 'version', 'Display Coradoc version'
95
65
  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"
66
+ puts "Coradoc #{Coradoc::VERSION}"
67
+ end
68
+
69
+ desc 'validate FILE', 'Validate a document against its schema'
70
+ option :format, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
71
+ option :strict, desc: 'Enable strict validation mode', type: :boolean, default: false
72
+ def validate(file)
73
+ source_format = resolve_format(file)
74
+ unless source_format
75
+ error 'Error: Could not determine format. Use --format option.'
76
+ exit 1
77
+ end
78
+
79
+ verbose_log "Validating #{file} (#{source_format})"
80
+
81
+ result = Coradoc.validate_file(file, format: source_format)
82
+
83
+ if result.valid?
84
+ puts '✓ Document is valid'
85
+ else
86
+ error "✗ #{result}"
87
+ exit 1
88
+ end
89
+ rescue Coradoc::Error => e
90
+ error "Error: #{e.message}"
91
+ exit 1
92
+ rescue StandardError => e
93
+ error "Error: #{e.message}"
94
+ verbose_log e.backtrace.join("\n") if options[:verbose]
95
+ exit 1
96
+ end
97
+
98
+ desc 'query FILE SELECTOR', 'Query document elements using CSS-like selectors'
99
+ option :format, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
100
+ option :output, aliases: '-o', desc: 'Output format (text, json)', type: :string, default: 'text'
101
+ def query(file, selector)
102
+ source_format = resolve_format(file)
103
+ unless source_format
104
+ error 'Error: Could not determine format. Use --format option.'
105
+ exit 1
106
+ end
107
+
108
+ verbose_log "Querying #{file} with selector: #{selector}"
109
+
110
+ doc = Coradoc.parse_file(file, format: source_format)
111
+ results = Coradoc::Query.query(doc, selector)
112
+
113
+ if results.empty?
114
+ puts "No elements found matching: #{selector}"
100
115
  else
101
- puts "[dependency] LibreOffice: v#{WordToMarkdown.soffice.version}"
116
+ case options[:output]
117
+ when 'json'
118
+ require 'json'
119
+ puts JSON.pretty_generate(results.map { |r| Coradoc.describe_element(r) })
120
+ else
121
+ puts "Found #{results.length} element(s):"
122
+ results.each_with_index do |elem, i|
123
+ puts " #{i + 1}. #{Coradoc.describe_element(elem)}"
124
+ end
125
+ end
102
126
  end
127
+ rescue Coradoc::Error => e
128
+ error "Error: #{e.message}"
129
+ exit 1
130
+ rescue StandardError => e
131
+ error "Error: #{e.message}"
132
+ verbose_log e.backtrace.join("\n") if options[:verbose]
133
+ exit 1
134
+ end
135
+
136
+ desc 'info FILE', 'Display document metadata and statistics'
137
+ option :format, aliases: '-f', desc: 'Source format (auto-detected from extension)', type: :string
138
+ def info(file)
139
+ source_format = resolve_format(file)
140
+ unless source_format
141
+ error 'Error: Could not determine format. Use --format option.'
142
+ exit 1
143
+ end
144
+
145
+ verbose_log "Analyzing #{file} (#{source_format})"
146
+
147
+ doc = Coradoc.parse_file(file, format: source_format)
148
+ stats = Coradoc.document_stats(doc)
149
+ fi = Coradoc.file_info(file)
150
+
151
+ puts 'Document Information'
152
+ puts '=' * 40
153
+ puts "Format: #{source_format}"
154
+ puts "File size: #{fi[:size]} bytes"
155
+ puts "Line count: #{fi[:lines]}" if fi[:lines]
156
+ puts "Title: #{stats[:title]}" if stats[:title]
157
+ puts "Child elements: #{stats[:child_count]}" if stats[:child_count]
158
+
159
+ if stats[:element_counts]&.any?
160
+ puts ''
161
+ puts 'Element Counts:'
162
+ stats[:element_counts].each { |type, count| puts " #{type}: #{count}" }
163
+ end
164
+ rescue Coradoc::Error => e
165
+ error "Error: #{e.message}"
166
+ exit 1
167
+ rescue StandardError => e
168
+ error "Error: #{e.message}"
169
+ verbose_log e.backtrace.join("\n") if options[:verbose]
170
+ exit 1
171
+ end
172
+
173
+ map '-v' => :version, '--version' => :version
174
+
175
+ private
176
+
177
+ def resolve_format(file, option_key = :format)
178
+ raw = options[option_key]
179
+ raw ? Coradoc.normalize_format(raw) : Coradoc.detect_format(file)
180
+ end
181
+
182
+ def write_output(content, output_file)
183
+ if output_file
184
+ File.write(output_file, content)
185
+ verbose_log "Written to: #{output_file}"
186
+ else
187
+ puts content
188
+ end
189
+ end
190
+
191
+ def verbose_log(message)
192
+ warn "[verbose] #{message}" if options[:verbose]
193
+ end
194
+
195
+ def error(message)
196
+ warn message
103
197
  end
104
198
  end
105
199
  end