relaton-cli 3.0.7 → 3.1.0

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/relaton-cli.rb +4 -16
  3. metadata +11 -123
  4. data/.gitignore +0 -22
  5. data/.hound.yml +0 -3
  6. data/.rspec +0 -1
  7. data/CLAUDE.md +0 -524
  8. data/Gemfile +0 -42
  9. data/Rakefile +0 -21
  10. data/bin/console +0 -11
  11. data/bin/rspec +0 -29
  12. data/bin/setup +0 -8
  13. data/docs/README.adoc +0 -589
  14. data/exe/relaton +0 -20
  15. data/frontend/dist/404.html +0 -18
  16. data/frontend/dist/app.iife.js +0 -1
  17. data/frontend/dist/style.css +0 -3
  18. data/i18n.yaml +0 -1
  19. data/lib/relaton/bibcollection.rb +0 -146
  20. data/lib/relaton/bibdata.rb +0 -92
  21. data/lib/relaton/cli/base_convertor.rb +0 -134
  22. data/lib/relaton/cli/command.rb +0 -390
  23. data/lib/relaton/cli/data_fetcher.rb +0 -20
  24. data/lib/relaton/cli/frontend_assets.rb +0 -58
  25. data/lib/relaton/cli/full_text_search.rb +0 -98
  26. data/lib/relaton/cli/index_item_normalizer.rb +0 -380
  27. data/lib/relaton/cli/index_site_generator.rb +0 -1008
  28. data/lib/relaton/cli/relaton_file.rb +0 -290
  29. data/lib/relaton/cli/subcommand_collection.rb +0 -263
  30. data/lib/relaton/cli/subcommand_db.rb +0 -81
  31. data/lib/relaton/cli/util.rb +0 -8
  32. data/lib/relaton/cli/version.rb +0 -11
  33. data/lib/relaton/cli/xml_convertor.rb +0 -47
  34. data/lib/relaton/cli/xml_to_html_renderer.rb +0 -117
  35. data/lib/relaton/cli/yaml_convertor.rb +0 -102
  36. data/lib/relaton/cli.rb +0 -113
  37. data/lib/relaton/element_finder.rb +0 -29
  38. data/relaton-cli.gemspec +0 -49
  39. data/templates/_document.liquid +0 -111
  40. data/templates/_index.liquid +0 -61
  41. data/templates/index/page.liquid +0 -20
  42. data/templates/index-style.css +0 -1017
@@ -1,290 +0,0 @@
1
- require "nokogiri"
2
- require "pathname"
3
-
4
- module Relaton
5
- module Cli
6
- class RelatonFile
7
- def initialize(source, options = {})
8
- @source = source
9
- @options = options
10
- @outdir = options.fetch(:outdir, nil)
11
- @outfile = options.fetch(:outfile, nil)
12
- end
13
-
14
- def extract
15
- extract_and_write_to_files
16
- end
17
-
18
- def concatenate
19
- concatenate_and_write_to_files
20
- end
21
-
22
- def split
23
- split_and_write_to_files
24
- end
25
-
26
- # Extract files
27
- #
28
- # This interface expect us to provide a source file / directory,
29
- # output directory and custom configuration options. Then it wll
30
- # extract Relaton XML file / files to output directory from the
31
- # source file / directory. During this process it will use custom
32
- # options when available.
33
- #
34
- # @param source [Dir] The source directory for files
35
- # @param outdir [Dir] The output directory for files
36
- # @param options [Hash] Options as hash key value pair
37
- #
38
- def self.extract(source, outdir, options = {})
39
- new(source, options.merge(outdir: outdir)).extract
40
- end
41
-
42
- # Concatenate files
43
- #
44
- # This interface expect us to provide a source directory, output
45
- # file and custom configuration options. Normally, this expect the
46
- # source directory to contain RXL fles, but it also converts any
47
- # YAML files to RXL and then finally combines those together.
48
- #
49
- # This interface also allow us to provdie options like title and
50
- # organization and then it usage those details to generate the
51
- # collection file.
52
- #
53
- # @param source [Dir] The source directory for files
54
- # @param output [String] The collection output file
55
- # @param options [Hash] Options as hash key value pair
56
- #
57
- def self.concatenate(source, outfile, options = {})
58
- new(source, options.merge(outfile: outfile)).concatenate
59
- end
60
-
61
- # Split collection
62
- #
63
- # This interface expects us to provide a Relaton Collection
64
- # file and also an output directory, then it will split that
65
- # collection into multiple files.
66
- #
67
- # By default it usages `rxl` extension for these new files,
68
- # but we can also customize that by providing the correct
69
- # one as `extension` option parameter.
70
- #
71
- # @param source [File] The source collection file
72
- # @param output [Dir] The output directory for files
73
- # @param options [Hash] Options as hash key value pair
74
- #
75
- def self.split(source, outdir = nil, options = {})
76
- new(source, options.merge(outdir: outdir)).split
77
- end
78
-
79
- private
80
-
81
- attr_reader :source, :options, :outdir, :outfile
82
-
83
- def bibcollection
84
- Bibcollection.new(
85
- title: options[:title],
86
- items: concatenate_files,
87
- doctype: options[:doctype],
88
- author: options[:organization],
89
- )
90
- end
91
-
92
- # Turn an XML string into a Nokogiri XML document.
93
- #
94
- # @param document [String] XML
95
- # @param file [String, nil] path to file
96
- # @return [Nokogiri::XML::Document]
97
- def nokogiri_document(document, file = nil)
98
- document ||= File.read(file, encoding: "utf-8")
99
- Nokogiri.XML(document)
100
- end
101
-
102
- def select_source_files
103
- if File.file?(source)
104
- [source]
105
- else
106
- select_files_with("xml")
107
- end
108
- end
109
-
110
- def relaton_collection
111
- @relaton_collection ||= Bibcollection.from_xml(nokogiri_document(nil, source))
112
- end
113
-
114
- def extract_and_write_to_files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
115
- select_source_files.each do |file|
116
- xml = nokogiri_document(nil, file)
117
- xml.remove_namespaces!
118
-
119
- if (bib = xml.at("//bibdata"))
120
- bib = nokogiri_document(bib.to_xml)
121
- elsif (rfc = xml.at("//rfc"))
122
- require "relaton/ietf"
123
- require "relaton/ietf/bibxml_parser"
124
- ietf = Relaton::Ietf::BibXMLParser.parse_rfc rfc.to_xml
125
- bib = nokogiri_document(ietf.to_xml(bibdata: true))
126
- else
127
- next
128
- end
129
-
130
- bib.remove_namespaces!
131
-
132
- bibdata = Relaton::Bibdata.from_xml(bib.root)
133
- if bibdata
134
- build_bibdata_relaton(bibdata, file)
135
-
136
- write_to_file(bibdata.send(output_type), outdir, build_filename(file))
137
- end
138
- end
139
- end
140
-
141
- # Map all relevant files to the corresponding bibdata instances
142
- #
143
- # @return [Array<Relaton::Bibdata>]
144
- def concatenate_files
145
- xml_files = [convert_rxl_to_xml, convert_yamls_to_xml, convert_xml_to_xml]
146
-
147
- xml_files.flatten.reduce([]) do |mem, xml|
148
- doc = nokogiri_document(xml[:content])
149
- if (rfc = doc.at("/rfc"))
150
- require "relaton/ietf"
151
- require "relaton/ietf/bibxml_parser"
152
- ietf = Relaton::Ietf::BibXMLParser.parse_rfc rfc.to_xml
153
- d = nokogiri_document ietf.to_xml(bibdata: true)
154
- mem << bibdata_instance(d, xml[:file])
155
- elsif %w[bibitem bibdata].include? doc&.root&.name
156
- mem << bibdata_instance(doc, xml[:file])
157
- else mem
158
- end
159
- end
160
- end
161
-
162
- def concatenate_and_write_to_files
163
- write_to_file(bibcollection.send(output_type))
164
- end
165
-
166
- def split_and_write_to_files
167
- output_dir = outdir || build_dirname(source)
168
-
169
- relaton_collection.items.each do |content|
170
- name = build_filename(nil, content.docidentifier)
171
- find_available_bibrxl_file(name, output_dir, content)
172
- write_to_file(content.send(output_type), output_dir, name)
173
- end
174
- end
175
-
176
- def find_available_bibrxl_file(name, _ouputdir, content)
177
- if options[:extension] == "yaml" || options[:extension] == "yml"
178
- bib_rxl = Pathname.new([outdir, name].join("/")).sub_ext(".rxl")
179
- content.bib_rxl = bib_rxl.to_s if File.file?(bib_rxl)
180
- end
181
- end
182
-
183
- def output_type(ext = options[:extension])
184
- ext ||= File.extname(outfile)[1..-1] if outfile
185
- case ext
186
- when "rxl", "xml"
187
- :to_xml
188
- when "yml", "yaml"
189
- :to_yaml
190
- else
191
- puts "[relaton-cli] the given extension of '#{ext}' is "\
192
- "not supported. Use 'rxl'."
193
- :to_xml
194
- end
195
- end
196
-
197
- # Create a bibdata instance from the XML document,
198
- # while also adding file paths of related artifacts
199
- # as URI elements to the bibdata instance.
200
- #
201
- # @param document [Nokogiri::XML::Document]
202
- # @param file [String] path to file
203
- # @return [Relaton::Bibdata]
204
- def bibdata_instance(document, file)
205
- document = clean_nokogiri_document(document)
206
- bibdata = Relaton::Bibdata.from_xml document.root
207
- build_bibdata_relaton(bibdata, file) if bibdata
208
-
209
- bibdata
210
- end
211
-
212
- # For each file type, add to the bibdata:
213
- # - a URI element that points to the file of that file type
214
- #
215
- # The URI element generation is skipped if the file does not exist.
216
- #
217
- # @param bibdata [Relaton::Bibdata]
218
- # @param file [String] path to file
219
- def build_bibdata_relaton(bibdata, file)
220
- ["xml", "pdf", "doc", "html", "rxl", "txt"].each do |type|
221
- file = Pathname.new(file).sub_ext(".#{type}")
222
- bibdata.send("#{type}=", file.to_s) if File.file?(file)
223
- end
224
- end
225
-
226
- # Force a namespace otherwise Nokogiri won't parse.
227
- # The reason is we use Bibcollection's from_xml, but that one
228
- # has an xmlns. We don't want to change the code for bibdata
229
- # hence this hack #bibdata_doc.root['xmlns'] = "xmlns"
230
- #
231
- # @param document [Nokogiri::XML::Document]
232
- # @return [Nokogiri::XML::Document]
233
- def clean_nokogiri_document(document)
234
- document.remove_namespaces!
235
- nokogiri_document(document.to_xml)
236
- end
237
-
238
- def convert_rxl_to_xml
239
- select_files_with("{rxl}").map do |file|
240
- { file: file, content: File.read(file, encoding: "utf-8") }
241
- end
242
- end
243
-
244
- def convert_yamls_to_xml
245
- select_files_with("yaml").map do |file|
246
- { file: file, content: YAMLConvertor.to_xml(file, write: false) }
247
- end
248
- end
249
-
250
- def convert_xml_to_xml
251
- select_files_with("{xml}").map do |file|
252
- { file: file, content: File.read(file, encoding: "utf-8") }
253
- end
254
- end
255
-
256
- def select_files_with(extension)
257
- files = File.join(source, "**", "*.#{extension}")
258
- Dir[files].reject { |file| File.directory?(file) }
259
- end
260
-
261
- def write_to_file(content, directory = nil, output_file = nil)
262
- file_with_dir = [directory, output_file || outfile].compact.join("/")
263
- File.open(file_with_dir, "w:utf-8") { |file| file.write(content) }
264
- end
265
-
266
- def build_dirname(filename)
267
- basename = File.basename(filename)&.gsub(/.(xml|rxl)/, "")
268
- directory_name = sanitize_string(basename)
269
- FileUtils.mkdir_p(directory_name) # unless File.exists?(directory_name)
270
-
271
- directory_name
272
- end
273
-
274
- def build_filename(file, identifier = nil, ext = "rxl")
275
- identifier ||= Pathname.new(File.basename(file.to_s, ".xml")).to_s
276
- [sanitize_string(identifier), options[:extension] || ext].join(".")
277
- end
278
-
279
- def sanitize_string(string)
280
- clean_string = replace_bad_characters(string.downcase)
281
- clean_string.gsub(/^\s+/, "").gsub(/\s+$/, "").gsub(/\s+/, "-")
282
- end
283
-
284
- def replace_bad_characters(string)
285
- bad_chars = ["/", "\\", "?", "%", "*", ":", "|", '"', "<", ">", ".", " "]
286
- bad_chars.reduce(string.downcase) { |res, char| res.gsub(char, "-") }
287
- end
288
- end
289
- end
290
- end
@@ -1,263 +0,0 @@
1
- require "pubid"
2
- require "relaton/cli/full_text_search"
3
-
4
- module Relaton
5
- module Cli
6
- class SubcommandCollection < Thor
7
- include Relaton::Cli
8
- class_option :verbose, aliases: :v, type: :boolean, desc: "Output warnings"
9
-
10
- desc "create COLLECTION", "Create collection"
11
- option :dir, aliases: :d, desc: "Directory to store collection. " \
12
- "Default is $HOME/.relaton/collections."
13
- option :author, desc: "Author"
14
- option :title, desc: "Title"
15
- option :doctype, desc: "Documents type"
16
-
17
- def create(file)
18
- dir = directory
19
- file_path = File.join dir, file
20
- col = Relaton::Bibcollection.new options
21
- if File.exist? file_path
22
- Util.warn "Collection `#{file}` aready exist"
23
- else
24
- FileUtils.mkdir_p dir # unless Dir.exist? dir
25
- File.write file_path, col.to_yaml, encoding: "UTF-8"
26
- end
27
- end
28
-
29
- desc "info COLLECTION", "View collection information"
30
- option :dir, aliases: :d, desc: "Directory to store collection. " \
31
- "Default is $HOME/.relaton/collections."
32
-
33
- def info(file) # rubocop:disable Metrics/AbcSize
34
- path = File.join directory, file
35
- puts "Collection: #{File.basename path}"
36
- puts "Last updated: #{File.mtime path}"
37
- puts "File size: #{File.size path}"
38
- col = Relaton::Bibcollection.new YAML.load_file(path)["root"]
39
- puts "Number of items: #{col.items.size}"
40
- puts "Author: #{col.author}"
41
- puts "Title: #{col.title}"
42
- end
43
-
44
- desc "list", "List collections"
45
- option :dir, aliases: :d, desc: "Directory with collections. Default " \
46
- "is $HOME/.relaton/collections."
47
- option :entries, aliases: :e, type: :boolean, desc: "Show entries"
48
-
49
- def list
50
- Dir[File.join(directory, "*")].each do |f|
51
- yml = read_yaml f
52
- if yml && yml["root"]
53
- puts File.basename f
54
- puts_entries yml
55
- end
56
- end
57
- end
58
-
59
- map ls: :list
60
-
61
- desc "get CODE", "Fetch document from collection by ID"
62
- option :collection, aliases: :c, desc: "Collection to fetch document. " \
63
- "By default fetch the first match across all collections."
64
- option :dir, aliases: :d, desc: "Directory with collections. Default " \
65
- "is $HOME/.relaton/collections."
66
- option :format, aliases: :f, desc: "Output format (xml, abb). " \
67
- "If not defined the output in a human-readable form."
68
- option :output, aliases: :o, desc: "Output to the specified file. The " \
69
- " file's extension (abb, xml) defines output format."
70
-
71
- def get(docid)
72
- collections.each do |col|
73
- col[:collection].items.each do |item|
74
- if item.docidentifier == docid
75
- output_item(item)
76
- return
77
- end
78
- end
79
- end
80
- end
81
-
82
- desc "find TEXT", "Full-text search"
83
- option :collection, aliases: :c, desc: "Collection to search text. " \
84
- "By default search across all collections."
85
- option :dir, aliases: :d, desc: "Directory with collections. Default is " \
86
- "$HOME/.relaton/collections."
87
-
88
- def find(text)
89
- collections.each do |col|
90
- searcher = Relaton::FullTextSeatch.new(col[:collection])
91
- searcher.search text
92
- if searcher.any?
93
- puts "Collection: #{File.basename(col[:file])}"
94
- searcher.print_results
95
- end
96
- end
97
- end
98
-
99
- map search: :find
100
-
101
- desc "fetch CODE", "Fetch a document and store it into a collection"
102
- option :type, aliases: :t, required: true,
103
- desc: "Type of standard to get bibliographic entry for"
104
- option :year, aliases: :y, type: :numeric,
105
- desc: "Year the standard was published"
106
- option :"publication-date-before",
107
- desc: "Fetch only documents published before the specified date " \
108
- "(e.g. 2008, 2008-02, or 2008-02-02)"
109
- option :"publication-date-after",
110
- desc: "Fetch only documents published after the specified date " \
111
- "(e.g. 2002, 2002-01, or 2002-01-01)"
112
- option :collection, aliases: :c, required: true,
113
- desc: "Collection to store a document"
114
- option :dir, aliases: :d, desc: "Directory with collections. Default is " \
115
- "$HOME/.relaton/collections."
116
-
117
- def fetch(code) # rubocop:disable Metrics/AbcSize
118
- opts = {}
119
- if options[:"publication-date-before"]
120
- opts[:publication_date_before] = parse_date_option(options[:"publication-date-before"], "--publication-date-before")
121
- end
122
- if options[:"publication-date-after"]
123
- opts[:publication_date_after] = parse_date_option(options[:"publication-date-after"], "--publication-date-after")
124
- end
125
- validate_date_range opts[:publication_date_after], opts[:publication_date_before]
126
- doc = Relaton.db.fetch(code, options[:year]&.to_s, **opts)
127
- if doc
128
- colfile = File.join directory, options[:collection]
129
- coll = read_collection colfile
130
- coll << doc
131
- File.write colfile, coll.to_yaml, encoding: "UTF-8"
132
- else Util.info "No matching bibliographic entry found"
133
- end
134
- rescue Relaton::UnknownReferenceError => e
135
- Util.warn e.message
136
- rescue Pubid::Errors::Error
137
- Util.error %("#{code}" is not a recognized standards identifier)
138
- end
139
-
140
- desc "import FILE", "Import document or collection from an XML file " \
141
- "into another collection"
142
- option :collection, aliases: :c, required: true,
143
- desc: "Collection to store a document. If " \
144
- "collection doesn't exist then it'll be created."
145
- option :dir, aliases: :d, desc: "Directory with collections. Default is " \
146
- "$HOME/.relaton/collections."
147
-
148
- def import(file) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
149
- collfile = File.join directory, options[:collection]
150
- coll = read_collection collfile
151
- xml = Nokogiri::XML File.read(file, encoding: "UTF-8")
152
- xml.remove_namespaces!
153
- if xml.at "relaton-collection"
154
- imported = import_collection(xml)
155
- if coll
156
- coll << imported
157
- else
158
- coll = imported
159
- end
160
- else
161
- coll ||= Relaton::Bibcollection.new({})
162
- coll << Relaton::Bibdata.from_xml(xml)
163
- end
164
- File.write collfile, coll.to_yaml, encoding: "UTF-8"
165
- end
166
-
167
- desc "export COLLECTION", "Export collection into XML file"
168
- option :dir, aliases: :d, desc: "Directory with collections. Default is " \
169
- "$HOME/.relaton/collections."
170
-
171
- def export(file)
172
- coll = read_collection File.join(directory, file)
173
- outfile = "#{file.sub(/\.\w+$/, '')}.xml"
174
- File.write outfile, coll.to_xml(bibdata: true), encoding: "UTF-8"
175
- end
176
-
177
- private
178
-
179
- # Parse a namespace-free collection XML document.
180
- # Bibcollection.from_xml expects namespaced docs (via apply_namespace),
181
- # so we use plain XPath on the namespace-stripped document instead.
182
- def import_collection(xml)
183
- title = xml.at("relaton-collection/title")&.text
184
- author = xml.at_xpath(
185
- "./relaton-collection/contributor[role/@type='author']"\
186
- "/organization/name",
187
- )&.text
188
- items = xml.xpath("relaton-collection/relation").map do |rel|
189
- el = rel.at("bibdata") || rel.at("bibitem")
190
- Relaton::Bibdata.from_xml(el || rel)
191
- end.compact
192
- Relaton::Bibcollection.new(title: title, author: author, items: items)
193
- end
194
-
195
- # @return [String]
196
- def directory
197
- options.fetch :dir, File.join(Dir.home, ".relaton/collections")
198
- end
199
-
200
- # @param file [String]
201
- # @return [Hash, nil]
202
- def read_yaml(file)
203
- YAML.load_file file if File.file? file
204
- rescue Psych::SyntaxError
205
- Util.error "the file `#{file}` isn't a collection."
206
- nil
207
- end
208
-
209
- # @param file [String]
210
- # @return [Relaton::Bibcollection, nil]
211
- def read_collection(file)
212
- return unless File.file?(file)
213
-
214
- Relaton::Bibcollection.new YAML.load_file(file)["root"]
215
- end
216
-
217
- # @return [Array<Hash>]
218
- def collections
219
- file = options.fetch :collection, "*"
220
- Dir[File.join directory, file].reduce([]) do |m, f|
221
- yml = read_yaml f
222
- if yml && yml["root"]
223
- m << { collection: Relaton::Bibcollection.new(yml["root"]),
224
- file: f }
225
- end
226
- m
227
- end
228
- end
229
-
230
- # Puts document IDs for each item in tthe cokllection
231
- # @param hash [Hash] Relaton collection
232
- def puts_entries(hash)
233
- return unless options[:entries]
234
-
235
- Relaton::Bibcollection.new(hash["root"]).items.each do |b|
236
- puts " #{b.docidentifier}"
237
- end
238
- end
239
-
240
- # @param item [Relaton::Bibdata]
241
- def output_item(item)
242
- case options[:format]
243
- when "xml" then puts item.to_xml bibdata: true
244
- when "abb" then puts item.to_asciibib
245
- else puts_human_readable_item item
246
- end
247
- out = case options[:output]
248
- when /\.abb$/ then item.to_asciibib
249
- when /\.xml$/ then item.to_xml bibitem: true
250
- end
251
- File.write options[:output], out, encoding: "UTF-8" if out
252
- end
253
-
254
- # @param item [Relaton::Bibdata]
255
- def puts_human_readable_item(item) # rubocop:disable Metrics/AbcSize
256
- puts "Document identifier: #{item.docidentifier}"
257
- puts "Title: #{item.title.first.content}"
258
- puts "Status: #{item.status.stage}"
259
- item.date.each { |d| puts "Date #{d.type}: #{d.at || d.from}" }
260
- end
261
- end
262
- end
263
- end
@@ -1,81 +0,0 @@
1
- module Relaton
2
- module Cli
3
- class SubcommandDb < Thor
4
- include Relaton::Cli
5
- class_option :verbose, aliases: :v, type: :boolean, desc: "Output warnings"
6
-
7
- desc "create DIR", "Create new cache DB. Default DIR is " \
8
- "/home/user/.relaon/cache/"
9
-
10
- def create(dir = nil)
11
- db = Relaton.db (dir && File.expand_path(dir))
12
- path = db.instance_variable_get(:@db).dir
13
- Util.warn "Cache DB is in `#{path}`"
14
- end
15
-
16
- desc "mv DIR", "Move cache DB to a new directory"
17
-
18
- def mv(dir)
19
- new_path = File.expand_path dir
20
- path = Relaton.db.mv new_path
21
- if path
22
- File.write Cli::RelatonDb::DBCONF, path, encoding: "UTF-8"
23
- Util.warn "Cache DB is moved to `#{path}`"
24
- end
25
- end
26
-
27
- desc "clear", "Clear cache DB"
28
-
29
- def clear
30
- db = Relaton.db
31
- db.clear
32
- Util.warn "Cache DB is cleared"
33
- end
34
-
35
- desc "fetch CODE", "Fetch Relaton XML for Standard identifier CODE " \
36
- "from cache DB"
37
- option :type, aliases: :t, desc: "Type of standard to " \
38
- "get bibliographic entry for"
39
- option :format, aliases: :f, desc: "Output format (xml, yaml, bibtex). " \
40
- "Default xml."
41
- option :year, aliases: :y, type: :numeric, desc: "Year the standard " \
42
- "was published"
43
- option :"publication-date-before",
44
- desc: "Fetch only documents published before the specified date " \
45
- "(e.g. 2008, 2008-02, or 2008-02-02)"
46
- option :"publication-date-after",
47
- desc: "Fetch only documents published after the specified date " \
48
- "(e.g. 2002, 2002-01, or 2002-01-01)"
49
-
50
- def fetch(code)
51
- io = IO.new($stdout.fcntl(::Fcntl::F_DUPFD), mode: "w:UTF-8")
52
- opts = options.merge(fetch_db: true)
53
- io.puts(fetch_document(code, opts) || supported_type_message)
54
- end
55
-
56
- desc "fetch_all TEXT", "Query for all documents in a cache DB for a " \
57
- "certain string"
58
- option :edition, aliases: :e, desc: "Filter entries by edition"
59
- option :year, aliases: :y, desc: "Filter entries by year"
60
- option :format, aliases: :f, desc: "Output format (xml, yaml, bibtex). " \
61
- "Default xml."
62
-
63
- def fetch_all(text = nil) # rubocop:disable Metrics/AbcSize
64
- io = IO.new($stdout.fcntl(::Fcntl::F_DUPFD), mode: "w:UTF-8")
65
- opts = options.each_with_object({}) do |(k, v), o|
66
- o[k.to_sym] = v unless k == "format"
67
- end
68
- Relaton.db.fetch_all(text, **opts).each do |doc|
69
- io.puts serialize(doc, options[:format])
70
- end
71
- end
72
-
73
- desc "doctype REF", "Detect document type from REF"
74
-
75
- def doctype(ref)
76
- io = IO.new($stdout.fcntl(::Fcntl::F_DUPFD), mode: "w:UTF-8")
77
- io.puts Relaton.db.docid_type(ref)
78
- end
79
- end
80
- end
81
- end
@@ -1,8 +0,0 @@
1
- module Relaton
2
- module Cli
3
- module Util
4
- extend Relaton::Bib::Util
5
- PROGNAME = "relaton-cli".freeze
6
- end
7
- end
8
- end
@@ -1,11 +0,0 @@
1
- # relaton-cli ships in lockstep with the combined `relaton` gem, so its version
2
- # is that gem's version — the single source of truth in Relaton::VERSION. relaton
3
- # is a hard runtime dependency, so requiring its lightweight version file always
4
- # resolves. Don't hardcode a string here; it would silently drift on a bump.
5
- require "relaton/version"
6
-
7
- module Relaton
8
- module Cli
9
- VERSION = Relaton::VERSION
10
- end
11
- end