llms-txt-ruby 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59e6ef21e4d8e7cfad82d91a1d0c6eede9528850622efef8738b718bbbe0ea43
4
- data.tar.gz: 0247ceaaed63bea7ba5d86753cd77e19e032ec31561ab6fbfe35874d875cbda6
3
+ metadata.gz: 678093f3878f75c9f39c21f009b279e95e20c62a7dcbbc72de5499305a73bf6f
4
+ data.tar.gz: a2406c0e8fada1bf1e0134acae4adfe3859d1af83d4d5286cb4207d2dde92f64
5
5
  SHA512:
6
- metadata.gz: 13bcd98389bbfd2193e1d21b3b5372bd1656145aec325a0f1456ce95cb699106008c35914cdab9c6ed4e7cefa4c955791347179e003def2a8569ab267c387abc
7
- data.tar.gz: 4115db81602c0137224f7e5c8b9c536b5684776c3398e04893d6f1e0b2a327af71918d34c661d83eae9e773654ef282947fcd231af0a3c4cfe8263f085455381
6
+ metadata.gz: dc062480b41973112b8e0e860b1605cd4b51a3f9d8b41af490fee57ae3b286722dcfac1fe07bfe80baca624647dde37e7fffbf7f2a34e9d2ca2b32b25550f2e1
7
+ data.tar.gz: b7600d18d1ecded87cd64c6e5022a20915abe02d716fd53d033abfd35136b7514b4b7f7c4e1b9e3f9018cb6c2358ac0692c4cdd5b8d115788e8287d836af5268
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2 (2025-10-07)
4
+ - [Fix] Fixed CLI error handling to use correct `LlmsTxt::Errors::BaseError` instead of non-existent `LlmsTxt::Error`.
5
+ - [Enhancement] Extracted CLI class to `lib/llms_txt/cli.rb` for better testability.
6
+ - [Enhancement] Added comprehensive CLI error handling specs.
7
+
3
8
  ## 0.1.1 (2025-10-07)
4
9
  - [Change] Updated repository metadata to use `master` branch instead of `main`.
5
10
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- llms-txt-ruby (0.1.1)
4
+ llms-txt-ruby (0.1.2)
5
5
  zeitwerk (~> 2.6)
6
6
 
7
7
  GEM
data/bin/llms-txt CHANGED
@@ -1,242 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'optparse'
5
4
  require 'llms_txt'
5
+ require 'llms_txt/cli'
6
6
 
7
- module LlmsTxt
8
- class CLI
9
- def self.run(argv = ARGV)
10
- new.run(argv)
11
- end
12
-
13
- def run(argv)
14
- options = parse_options(argv)
15
-
16
- case options[:command]
17
- when 'generate', nil
18
- generate(options)
19
- when 'transform'
20
- transform(options)
21
- when 'bulk-transform'
22
- bulk_transform(options)
23
- when 'parse'
24
- parse(options)
25
- when 'validate'
26
- validate(options)
27
- when 'version'
28
- show_version
29
- else
30
- puts "Unknown command: #{options[:command]}"
31
- puts "Run 'llms-txt --help' for usage information"
32
- exit 1
33
- end
34
- rescue LlmsTxt::Error => e
35
- puts "Error: #{e.message}"
36
- exit 1
37
- rescue StandardError => e
38
- puts "Unexpected error: #{e.message}"
39
- puts e.backtrace.join("\n") if options&.fetch(:verbose, false)
40
- exit 1
41
- end
42
-
43
- private
44
-
45
- def parse_options(argv)
46
- options = {
47
- command: argv.first&.match?(/^[a-z-]+$/) ? argv.shift : nil
48
- }
49
-
50
- OptionParser.new do |opts|
51
- opts.banner = "llms-txt - Simple tool for generating llms.txt from markdown documentation\n\nUsage: llms-txt [command] [options]\n\nFor advanced configuration (base_url, title, description, convert_urls), use a config file."
52
-
53
- opts.separator ''
54
- opts.separator 'Commands:'
55
- opts.separator ' generate Generate llms.txt from documentation (default)'
56
- opts.separator ' transform Transform a markdown file to be AI-friendly'
57
- opts.separator ' bulk-transform Transform all markdown files in directory'
58
- opts.separator ' parse Parse existing llms.txt file'
59
- opts.separator ' validate Validate llms.txt file'
60
- opts.separator ' version Show version'
61
-
62
- opts.separator ''
63
- opts.separator 'Options:'
64
-
65
- opts.on('-c', '--config PATH', 'Configuration file path (default: llms-txt.yml)') do |path|
66
- options[:config] = path
67
- end
68
-
69
- opts.on('-d', '--docs PATH', 'Path to documentation directory or file') do |path|
70
- options[:docs] = path
71
- end
72
-
73
- opts.on('-o', '--output PATH', 'Output file path') do |path|
74
- options[:output] = path
75
- end
76
-
77
- opts.on('-v', '--verbose', 'Verbose output') do
78
- options[:verbose] = true
79
- end
80
-
81
- opts.on('-h', '--help', 'Show this message') do
82
- puts opts
83
- exit
84
- end
85
-
86
- opts.on('--version', 'Show version') do
87
- show_version
88
- exit
89
- end
90
- end.parse!(argv)
91
-
92
- options[:file_path] = argv.first if argv.any?
93
- options
94
- end
95
-
96
- def generate(options)
97
- # Load config and merge with CLI options
98
- config = LlmsTxt::Config.new(options[:config])
99
- merged_options = config.merge_with_options(options)
100
-
101
- docs_path = merged_options[:docs]
102
-
103
- unless File.exist?(docs_path)
104
- puts "Documentation path not found: #{docs_path}"
105
- exit 1
106
- end
107
-
108
- puts "Generating llms.txt from #{docs_path}..." if merged_options[:verbose]
109
-
110
- content = LlmsTxt.generate_from_docs(docs_path, merged_options)
111
- output_path = merged_options[:output]
112
-
113
- File.write(output_path, content)
114
- puts "Successfully generated #{output_path}"
115
-
116
- if merged_options[:verbose]
117
- validator = LlmsTxt::Validator.new(content)
118
- if validator.valid?
119
- puts "Valid llms.txt format"
120
- else
121
- puts "Validation warnings:"
122
- validator.errors.each { |error| puts " - #{error}" }
123
- end
124
- end
125
- end
126
-
127
- def transform(options)
128
- # Load config and merge with CLI options
129
- config = LlmsTxt::Config.new(options[:config])
130
- merged_options = config.merge_with_options(options)
131
-
132
- file_path = options[:file_path]
133
-
134
- unless file_path
135
- puts "File path required for transform command"
136
- exit 1
137
- end
138
-
139
- unless File.exist?(file_path)
140
- puts "File not found: #{file_path}"
141
- exit 1
142
- end
143
-
144
- puts "Transforming #{file_path}..." if merged_options[:verbose]
145
-
146
- content = LlmsTxt.transform_markdown(file_path, merged_options)
147
-
148
- if merged_options[:output] && merged_options[:output] != 'llms.txt'
149
- File.write(merged_options[:output], content)
150
- puts "Transformed content saved to #{merged_options[:output]}"
151
- else
152
- puts content
153
- end
154
- end
155
-
156
- def bulk_transform(options)
157
- # Load config and merge with CLI options
158
- config = LlmsTxt::Config.new(options[:config])
159
- merged_options = config.merge_with_options(options)
160
-
161
- docs_path = merged_options[:docs]
162
-
163
- unless File.exist?(docs_path)
164
- puts "Documentation path not found: #{docs_path}"
165
- exit 1
166
- end
167
-
168
- unless File.directory?(docs_path)
169
- puts "Path must be a directory for bulk transformation: #{docs_path}"
170
- exit 1
171
- end
172
-
173
- puts "Bulk transforming markdown files in #{docs_path}..." if merged_options[:verbose]
174
- puts "Using suffix: #{merged_options[:suffix]}" if merged_options[:verbose]
175
- puts "Excludes: #{merged_options[:excludes].join(', ')}" if merged_options[:verbose] && !merged_options[:excludes].empty?
176
-
177
- begin
178
- transformed_files = LlmsTxt.bulk_transform(docs_path, merged_options)
179
-
180
- if transformed_files.empty?
181
- puts "No markdown files found to transform"
182
- else
183
- puts "Successfully transformed #{transformed_files.size} files:"
184
- transformed_files.each { |file| puts " #{file}" } unless merged_options[:verbose] # verbose mode already shows progress
185
- end
186
- rescue LlmsTxt::Error => e
187
- puts "Error during bulk transformation: #{e.message}"
188
- exit 1
189
- end
190
- end
191
-
192
- def parse(options)
193
- file_path = options[:file_path] || 'llms.txt'
194
-
195
- unless File.exist?(file_path)
196
- puts "File not found: #{file_path}"
197
- exit 1
198
- end
199
-
200
- parsed = LlmsTxt.parse(file_path)
201
-
202
- if options[:verbose]
203
- puts "Title: #{parsed.title}"
204
- puts "Description: #{parsed.description}"
205
- puts "Documentation Links: #{parsed.documentation_links.size}"
206
- puts "Example Links: #{parsed.example_links.size}" if parsed.respond_to?(:example_links)
207
- puts "Optional Links: #{parsed.optional_links.size}" if parsed.respond_to?(:optional_links)
208
- else
209
- puts parsed.to_xml if parsed.respond_to?(:to_xml)
210
- end
211
- end
212
-
213
- def validate(options)
214
- file_path = options[:file_path] || 'llms.txt'
215
-
216
- unless File.exist?(file_path)
217
- puts "File not found: #{file_path}"
218
- exit 1
219
- end
220
-
221
- content = File.read(file_path)
222
- valid = LlmsTxt.validate(content)
223
-
224
- if valid
225
- puts 'Valid llms.txt file'
226
- else
227
- puts 'Invalid llms.txt file'
228
- puts "\nErrors:"
229
- LlmsTxt::Validator.new(content).errors.each do |error|
230
- puts " - #{error}"
231
- end
232
- exit 1
233
- end
234
- end
235
-
236
- def show_version
237
- puts "llms-txt version #{LlmsTxt::VERSION}"
238
- end
239
- end
240
- end
241
-
242
- LlmsTxt::CLI.run # if $PROGRAM_NAME == __FILE__
7
+ LlmsTxt::CLI.run
@@ -0,0 +1,238 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+
5
+ module LlmsTxt
6
+ class CLI
7
+ def self.run(argv = ARGV)
8
+ new.run(argv)
9
+ end
10
+
11
+ def run(argv)
12
+ options = parse_options(argv)
13
+
14
+ case options[:command]
15
+ when 'generate', nil
16
+ generate(options)
17
+ when 'transform'
18
+ transform(options)
19
+ when 'bulk-transform'
20
+ bulk_transform(options)
21
+ when 'parse'
22
+ parse(options)
23
+ when 'validate'
24
+ validate(options)
25
+ when 'version'
26
+ show_version
27
+ else
28
+ puts "Unknown command: #{options[:command]}"
29
+ puts "Run 'llms-txt --help' for usage information"
30
+ exit 1
31
+ end
32
+ rescue LlmsTxt::Errors::BaseError => e
33
+ puts "Error: #{e.message}"
34
+ exit 1
35
+ rescue StandardError => e
36
+ puts "Unexpected error: #{e.message}"
37
+ puts e.backtrace.join("\n") if options&.fetch(:verbose, false)
38
+ exit 1
39
+ end
40
+
41
+ private
42
+
43
+ def parse_options(argv)
44
+ options = {
45
+ command: argv.first&.match?(/^[a-z-]+$/) ? argv.shift : nil
46
+ }
47
+
48
+ OptionParser.new do |opts|
49
+ opts.banner = "llms-txt - Simple tool for generating llms.txt from markdown documentation\n\nUsage: llms-txt [command] [options]\n\nFor advanced configuration (base_url, title, description, convert_urls), use a config file."
50
+
51
+ opts.separator ''
52
+ opts.separator 'Commands:'
53
+ opts.separator ' generate Generate llms.txt from documentation (default)'
54
+ opts.separator ' transform Transform a markdown file to be AI-friendly'
55
+ opts.separator ' bulk-transform Transform all markdown files in directory'
56
+ opts.separator ' parse Parse existing llms.txt file'
57
+ opts.separator ' validate Validate llms.txt file'
58
+ opts.separator ' version Show version'
59
+
60
+ opts.separator ''
61
+ opts.separator 'Options:'
62
+
63
+ opts.on('-c', '--config PATH', 'Configuration file path (default: llms-txt.yml)') do |path|
64
+ options[:config] = path
65
+ end
66
+
67
+ opts.on('-d', '--docs PATH', 'Path to documentation directory or file') do |path|
68
+ options[:docs] = path
69
+ end
70
+
71
+ opts.on('-o', '--output PATH', 'Output file path') do |path|
72
+ options[:output] = path
73
+ end
74
+
75
+ opts.on('-v', '--verbose', 'Verbose output') do
76
+ options[:verbose] = true
77
+ end
78
+
79
+ opts.on('-h', '--help', 'Show this message') do
80
+ puts opts
81
+ exit
82
+ end
83
+
84
+ opts.on('--version', 'Show version') do
85
+ show_version
86
+ exit
87
+ end
88
+ end.parse!(argv)
89
+
90
+ options[:file_path] = argv.first if argv.any?
91
+ options
92
+ end
93
+
94
+ def generate(options)
95
+ # Load config and merge with CLI options
96
+ config = LlmsTxt::Config.new(options[:config])
97
+ merged_options = config.merge_with_options(options)
98
+
99
+ docs_path = merged_options[:docs]
100
+
101
+ unless File.exist?(docs_path)
102
+ puts "Documentation path not found: #{docs_path}"
103
+ exit 1
104
+ end
105
+
106
+ puts "Generating llms.txt from #{docs_path}..." if merged_options[:verbose]
107
+
108
+ content = LlmsTxt.generate_from_docs(docs_path, merged_options)
109
+ output_path = merged_options[:output]
110
+
111
+ File.write(output_path, content)
112
+ puts "Successfully generated #{output_path}"
113
+
114
+ if merged_options[:verbose]
115
+ validator = LlmsTxt::Validator.new(content)
116
+ if validator.valid?
117
+ puts "Valid llms.txt format"
118
+ else
119
+ puts "Validation warnings:"
120
+ validator.errors.each { |error| puts " - #{error}" }
121
+ end
122
+ end
123
+ end
124
+
125
+ def transform(options)
126
+ # Load config and merge with CLI options
127
+ config = LlmsTxt::Config.new(options[:config])
128
+ merged_options = config.merge_with_options(options)
129
+
130
+ file_path = options[:file_path]
131
+
132
+ unless file_path
133
+ puts "File path required for transform command"
134
+ exit 1
135
+ end
136
+
137
+ unless File.exist?(file_path)
138
+ puts "File not found: #{file_path}"
139
+ exit 1
140
+ end
141
+
142
+ puts "Transforming #{file_path}..." if merged_options[:verbose]
143
+
144
+ content = LlmsTxt.transform_markdown(file_path, merged_options)
145
+
146
+ if merged_options[:output] && merged_options[:output] != 'llms.txt'
147
+ File.write(merged_options[:output], content)
148
+ puts "Transformed content saved to #{merged_options[:output]}"
149
+ else
150
+ puts content
151
+ end
152
+ end
153
+
154
+ def bulk_transform(options)
155
+ # Load config and merge with CLI options
156
+ config = LlmsTxt::Config.new(options[:config])
157
+ merged_options = config.merge_with_options(options)
158
+
159
+ docs_path = merged_options[:docs]
160
+
161
+ unless File.exist?(docs_path)
162
+ puts "Documentation path not found: #{docs_path}"
163
+ exit 1
164
+ end
165
+
166
+ unless File.directory?(docs_path)
167
+ puts "Path must be a directory for bulk transformation: #{docs_path}"
168
+ exit 1
169
+ end
170
+
171
+ puts "Bulk transforming markdown files in #{docs_path}..." if merged_options[:verbose]
172
+ puts "Using suffix: #{merged_options[:suffix]}" if merged_options[:verbose]
173
+ puts "Excludes: #{merged_options[:excludes].join(', ')}" if merged_options[:verbose] && !merged_options[:excludes].empty?
174
+
175
+ begin
176
+ transformed_files = LlmsTxt.bulk_transform(docs_path, merged_options)
177
+
178
+ if transformed_files.empty?
179
+ puts "No markdown files found to transform"
180
+ else
181
+ puts "Successfully transformed #{transformed_files.size} files:"
182
+ transformed_files.each { |file| puts " #{file}" } unless merged_options[:verbose] # verbose mode already shows progress
183
+ end
184
+ rescue LlmsTxt::Errors::BaseError => e
185
+ puts "Error during bulk transformation: #{e.message}"
186
+ exit 1
187
+ end
188
+ end
189
+
190
+ def parse(options)
191
+ file_path = options[:file_path] || 'llms.txt'
192
+
193
+ unless File.exist?(file_path)
194
+ puts "File not found: #{file_path}"
195
+ exit 1
196
+ end
197
+
198
+ parsed = LlmsTxt.parse(file_path)
199
+
200
+ if options[:verbose]
201
+ puts "Title: #{parsed.title}"
202
+ puts "Description: #{parsed.description}"
203
+ puts "Documentation Links: #{parsed.documentation_links.size}"
204
+ puts "Example Links: #{parsed.example_links.size}" if parsed.respond_to?(:example_links)
205
+ puts "Optional Links: #{parsed.optional_links.size}" if parsed.respond_to?(:optional_links)
206
+ else
207
+ puts parsed.to_xml if parsed.respond_to?(:to_xml)
208
+ end
209
+ end
210
+
211
+ def validate(options)
212
+ file_path = options[:file_path] || 'llms.txt'
213
+
214
+ unless File.exist?(file_path)
215
+ puts "File not found: #{file_path}"
216
+ exit 1
217
+ end
218
+
219
+ content = File.read(file_path)
220
+ valid = LlmsTxt.validate(content)
221
+
222
+ if valid
223
+ puts 'Valid llms.txt file'
224
+ else
225
+ puts 'Invalid llms.txt file'
226
+ puts "\nErrors:"
227
+ LlmsTxt::Validator.new(content).errors.each do |error|
228
+ puts " - #{error}"
229
+ end
230
+ exit 1
231
+ end
232
+ end
233
+
234
+ def show_version
235
+ puts "llms-txt version #{LlmsTxt::VERSION}"
236
+ end
237
+ end
238
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module LlmsTxt
4
4
  # Current version of the LlmsTxt gem
5
- VERSION = '0.1.1'
5
+ VERSION = '0.1.2'
6
6
  end
data/lib/llms_txt.rb CHANGED
@@ -5,6 +5,7 @@ require 'pathname'
5
5
  require 'find'
6
6
 
7
7
  loader = Zeitwerk::Loader.for_gem
8
+ loader.inflector.inflect('cli' => 'CLI')
8
9
  loader.setup
9
10
 
10
11
  module LlmsTxt
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: llms-txt-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -121,6 +121,7 @@ files:
121
121
  - bin/llms-txt
122
122
  - lib/llms_txt.rb
123
123
  - lib/llms_txt/bulk_transformer.rb
124
+ - lib/llms_txt/cli.rb
124
125
  - lib/llms_txt/config.rb
125
126
  - lib/llms_txt/errors.rb
126
127
  - lib/llms_txt/generator.rb