nist-pubid 0.1.2 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0eda4fda43009a4ec9c9cdd35c0abcada305c5c9868d246b4df0c324f84ea326
4
- data.tar.gz: 1392bed11a8b5d05126e6eb368fa650f013f4aac7a9c78d05f319b6e785bb42f
3
+ metadata.gz: d6cbdcaa4e1cfa7c75b6709f34cfd19670e8a3b2d3bd31473cbc5a5d439843b7
4
+ data.tar.gz: 4dcb0a4b147990872fe4f72c8eecac96ba3a865bcaa477a5158404ab04fc8e42
5
5
  SHA512:
6
- metadata.gz: 13a9854c8b67b0c7fc5202306501d8ec9d61ede0b73de2afbaefc8373fb7f798b7f7baa0caca9e6ab256bd6a929c55f09376ff2728465300d7d6098d929c2cad
7
- data.tar.gz: d6e3685000eea4ccf494fc4b1ade59b5002a561bdc9597c9a11b7ae738d730461f3297b60b2f66a98b23ff4670c1c2cdc899562f409a6063e4c609096f73ea97
6
+ metadata.gz: b6331d9887c149a7dbcf49c46a0ce7c121bf973cd239e3467658065820daf8c18f752e68b977d52e08155dfa2d947d9be5fa80bb431f462453ed337e02fc1616
7
+ data.tar.gz: 35660adeef1ec90862ada64b2150162008d0b25cf01a8e9a7b15f909b6ac64265a04cc2bdf1da7ea9a7d08e99754eb8d49910de9d19119b4548b40f3870876db
@@ -0,0 +1,46 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - '*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ next_version:
10
+ description: |
11
+ Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
12
+ required: true
13
+ default: 'skip'
14
+
15
+ jobs:
16
+ release:
17
+ runs-on: ubuntu-18.04
18
+ steps:
19
+ - uses: actions/checkout@v2
20
+
21
+ - uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: '2.6'
24
+ bundler-cache: true
25
+
26
+ - run: bundle exec rake
27
+
28
+ - run: gem install gem-release
29
+
30
+ - run: |
31
+ git config user.name github-actions
32
+ git config user.email github-actions@github.com
33
+ - if: github.event_name == 'workflow_dispatch' && github.event.inputs.next_version != 'skip'
34
+ run: gem bump --version ${{ github.event.inputs.next_version }} --tag --push
35
+
36
+ - name: Publish to rubygems.org
37
+ env:
38
+ RUBYGEMS_API_KEY: ${{secrets.METANORMA_CI_RUBYGEMS_API_KEY}}
39
+ run: |
40
+ gem install gem-release
41
+ cat > ~/.gem/credentials << EOF
42
+ ---
43
+ :rubygems_api_key: ${RUBYGEMS_API_KEY}
44
+ EOF
45
+ chmod 0600 ~/.gem/credentials
46
+ gem release
data/README.adoc CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  NIST publications are numbered according to an identification scheme.
6
6
 
7
- This gem implements a mechanism to parse and utilize NIST publication identifers
7
+ This gem implements a mechanism to parse and utilize NIST publication identifiers
8
8
  provided in the https://github.com/usnistgov/NIST-Tech-Pubs[NIST-Tech-Pubs]
9
9
  repository.
10
10
 
@@ -296,9 +296,10 @@ A "Part" can also be indicated by an appended alphabetic character to the end.
296
296
  | Section | Sec. | `sec`
297
297
  | Supplement | Suppl. | `sup`
298
298
  | Index | Index | `indx`
299
- | Addendum | Add. | `add` (TBD with NIST)
299
+ | Addendum | Add. | `add` (TBC with NIST)
300
300
  | Insert | Ins. | `ins` (TBC with NIST)
301
301
  | Errata | Err. | `err` (TBC with NIST)
302
+ | Appendix | App. | `app` (TBC with NIST)
302
303
 
303
304
  |===
304
305
 
data/exe/nist-pubid ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+ require_relative "../lib/nist_pubid"
6
+ require "thor"
7
+ require "csv"
8
+
9
+ class NistPubidCLI < Thor
10
+ desc "report", "Create report for NIST Tech Pubs database (fetches from GitHub)"
11
+ option :csv, type: :boolean, desc: "Export to CSV format"
12
+ def report
13
+ if options[:csv]
14
+ NistPubid::NistTechPubs.status.each do |doc|
15
+ puts [doc[:finalPubId] == doc[:id] && doc[:mr] == doc[:doi] ? "-" : "+",
16
+ doc[:finalPubId], doc[:id], doc[:doi], doc[:mr], doc[:title]]
17
+ .to_csv
18
+ end
19
+ else
20
+ puts "Changed | New PubID | Document ID | DOI | New MR | Title + subtitle"
21
+ NistPubid::NistTechPubs.status.each do |doc|
22
+ puts "#{doc[:finalPubId] == doc[:id] && doc[:mr] == doc[:doi] ? ' -' : '✅'}"\
23
+ " | #{doc[:finalPubId]} | #{doc[:id]} | #{doc[:doi]} | #{doc[:mr]} | #{doc[:title]}"
24
+ end
25
+ end
26
+ end
27
+
28
+ desc "convert", "Convert legacy NIST Tech Pubs ID to NIST PubID"
29
+ option :style, aliases: "-s", type: :string,
30
+ desc: "Convert to PubID style (short|long|mr|abbrev)",
31
+ default: "short"
32
+ option :format, aliases: "-f", type: :string,
33
+ desc: "Render in format (JSON, string)",
34
+ default: "string"
35
+ def convert(code)
36
+ unless %w[mr long short abbrev].include?(options[:style])
37
+ raise "Invalid PubID style"
38
+ end
39
+
40
+ raise "wrong conversion format" unless %w[string json].include? options[:format]
41
+
42
+ unless code.empty?
43
+ if options[:format] == "string"
44
+ puts NistPubid::Document.parse(code).to_s(options[:style].to_sym)
45
+ else
46
+ puts NistPubid::Document.parse(code).to_json
47
+ end
48
+ end
49
+ rescue NistPubid::Errors::ParseError
50
+ puts "[Error] This does not seem to be a valid NIST Tech Pubs legacy identifier"
51
+ end
52
+ end
53
+
54
+ NistPubidCLI.start(ARGV)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require "json"
2
3
 
3
4
  REVISION_DESC = {
4
5
  long: ", Revision ",
@@ -35,47 +36,200 @@ EDITION_DESC = {
35
36
  mr: "e",
36
37
  }.freeze
37
38
 
39
+ SUPPLEMENT_DESC = {
40
+ long: " Supplement ",
41
+ abbrev: " Suppl. ",
42
+ short: "sup",
43
+ mr: "sup",
44
+ }.freeze
45
+
46
+ SECTION_DESC = {
47
+ long: " Section ",
48
+ abbrev: " Sec. ",
49
+ short: "sec",
50
+ mr: "sec",
51
+ }.freeze
52
+
53
+ APPENDIX_DESC = {
54
+ long: " Appendix ",
55
+ abbrev: " App. ",
56
+ short: "app",
57
+ mr: "app",
58
+ }.freeze
59
+
60
+ ERRATA_DESC = {
61
+ long: " Errata ",
62
+ abbrev: " Err. ",
63
+ short: "err",
64
+ mr: "err",
65
+ }.freeze
66
+
67
+ INDEX_DESC = {
68
+ long: " Index ",
69
+ abbrev: " Index. ",
70
+ short: "indx",
71
+ mr: "indx",
72
+ }.freeze
73
+
74
+ INSERT_DESC = {
75
+ long: " Insert ",
76
+ abbrev: " Ins. ",
77
+ short: "ins",
78
+ mr: "ins",
79
+ }.freeze
80
+
38
81
  module NistPubid
39
82
  class Document
40
83
  attr_accessor :serie, :code, :revision, :publisher, :version, :volume,
41
- :part, :addendum, :stage, :translation, :update, :edition
84
+ :part, :addendum, :stage, :translation, :update_number,
85
+ :edition, :supplement, :update_year, :section, :appendix,
86
+ :errata, :index, :insert
42
87
 
43
- def initialize(publisher:, serie:, docnumber:, stage: nil, **opts)
88
+ def initialize(publisher:, serie:, docnumber:, **opts)
44
89
  @publisher = Publisher.new(publisher: publisher)
45
90
  @serie = Serie.new(serie: serie)
46
91
  @code = docnumber
47
- @stage = Stage.new(stage: stage)
48
92
  opts.each { |key, value| send("#{key}=", value) }
49
93
  end
50
94
 
95
+ # returns weight based on amount of defined attributes
96
+ def weight
97
+ instance_variables.inject(0) do |sum, var|
98
+ sum + (instance_variable_get(var).nil? ? 0 : 1)
99
+ end
100
+ end
101
+
102
+ def merge(document)
103
+ instance_variables.each do |var|
104
+ val = document.instance_variable_get(var)
105
+ instance_variable_set(var, val) unless val.nil?
106
+ end
107
+
108
+ self
109
+ end
110
+
111
+ def self.update_old_code(code)
112
+ code = code.gsub("FIPS", "FIPS PUB") unless code.include?("FIPS PUB")
113
+ code.gsub("NBS MONO", "NBS MN").gsub("NIST MONO", "NIST MN")
114
+ .gsub("NIST MP", "NBS MP")
115
+ .gsub("NIST SP 304a-2017", "NIST SP 304A-2017")
116
+ .gsub("NIST SP 260-162 2006ed.", "NIST SP 260-162e2006")
117
+ .gsub("NBS CIRC 154suprev", "NBS CIRC 154r1sup")
118
+ .gsub("NIST SP 260-126 rev 2013", "NIST SP 260-126r2013")
119
+ .gsub("NIST CSWP", "NIST CSRC White Paper")
120
+ .gsub("NIST.CSWP.01162020pt", "NIST.CSWP.01162020(por)")
121
+ .gsub(/(?<=NBS MP )(\d+)\((\d+)\)/, '\1e\2')
122
+ .gsub(/(?<=\d)es/, "(spa)")
123
+ .gsub(/(?<=\d)chi/, "(zho)")
124
+ .gsub(/(?<=\d)viet/, "(vie)")
125
+ .gsub(/(?<=\d)port/, "(por)")
126
+ # .gsub(/^LCIRC/, "NBS LC")
127
+ end
128
+
51
129
  def self.parse(code)
130
+ code = update_old_code(code)
52
131
  matches = {
53
132
  publisher: match(Publisher.regexp, code) || "NIST",
54
- serie: match(Serie.regexp, code)&.gsub(/\./, " "),
55
- stage: match(Stage.regexp, code),
56
- docnumber: match(/(?<=\.|\s)[0-9-]{3,}[A-Z]?/, code),
57
- part: /(?<=(\.))?pt(?(1)-)([A-Z\d]+)/.match(code)&.[](2),
58
- volume: /(?<=(\.))?v(?(1)-)(\d+)/.match(code)&.[](2),
59
- version: match(/(?<=(\.))?ver(?(1)[-\d]|[.\d])+/, code)&.gsub(/-/, "."),
60
- revision: /(?<=[^a-z])(?<=(\.))?(?:r(?(1)-)|Rev\.\s)(\d+)/
61
- .match(code)&.[](2),
62
- addendum: match(/(?<=(\.))?(add(?(1)-)\d+|Addendum)/, code),
63
- translation: match(/(?<=\()\w{3}(?=\))/, code),
64
- update: match(/(?<=Upd\s)([\d:]+)/, code),
65
- edition: /(?<=[^a-z])(?<=(\.))?(?:e(?(1)-)|Ed\.\s)(\d+)/
133
+ serie: match(Serie.regexp, code),
134
+ stage: Stage.parse(code),
135
+ part: /(?<=(\.))?(?<![a-z])+(?:pt|Pt|p)(?(1)-)([A-Z\d]+)/.match(code)
136
+ &.[](2),
137
+ version:
138
+ /(?<=\.)?(?:(?:ver)((?(1)[-\d]|[.\d])+|\d+)|(?:v)(\d+\.[.\d]+))/
139
+ .match(code).to_a[1..-1]&.compact&.first&.gsub(/-/, "."),
140
+ revision: /[\da](?:r|Rev\.\s|([0-9]+[A-Za-z]*-[0-9]+[A-Za-z]*-))([\da]+)/
66
141
  .match(code)&.[](2),
142
+ addendum: match(/(?<=(\.))?(add(?:-\d+)?|Addendum)/, code),
143
+ edition: /(?<=[^a-z])(?<=\.)?(?:e(?(1)-)|Ed\.\s)(\d+)|
144
+ NBS\sFIPS\sPUB\s[0-9]+[A-Za-z]*-[0-9]+[A-Za-z]*-([A-Za-z\d]+)
145
+ /x.match(code)&.captures&.join,
146
+ section: /(?<=sec)\d+/.match(code)&.to_s,
147
+ appendix: /\d+app/.match(code)&.to_s,
148
+ errata: /-errata|\d+err(?:ata)?/.match(code)&.to_s,
149
+ index: /\d+index|\d+indx/.match(code)&.to_s,
150
+ insert: /\d+ins(?:ert)?/.match(code)&.to_s
67
151
  }
152
+ supplement = /(?:(?:supp?)-?(\d*)|Supplement|Suppl.)/
153
+ .match(code)
154
+ unless supplement.nil?
155
+ matches[:supplement] = supplement[1].nil? ? "" : supplement[1]
156
+ end
157
+
158
+ update = code.scan(/((?<=Upd)\s?[\d:]+|-upd)-?(\d*)/).first
159
+
160
+ (matches[:update_number], matches[:update_year]) = update if update
161
+
162
+ unless matches[:serie]
163
+ raise Errors::ParseError.new("failed to parse serie for #{code}")
164
+ end
165
+
166
+ unless matches[:stage].nil?
167
+ code = code.gsub(matches[:stage].original_code, "")
168
+ end
169
+
170
+ unless ["NBS CSM", "NBS CS"].include?(matches[:serie])
171
+ matches[:volume] = /(?<=(\.))?v(?(1)-)(\d+)(?!\.\d+)/.match(code)&.[](2)
172
+ end
173
+
174
+ matches[:revision] = nil if matches[:addendum]
175
+
176
+ matches[:docnumber] = parse_docnumber(matches[:serie], code)
177
+
178
+ matches[:serie] = SERIES["mr"].invert[matches[:serie]] || matches[:serie]
179
+ # matches[:serie].gsub!(/\./, " ")
180
+ matches[:translation] = match(/(?<=\()\w{3}(?=\))/, code)
181
+
68
182
  new(**matches)
69
183
  end
70
184
 
185
+ def self.parse_docnumber(serie, code)
186
+ localities = "[Pp]t\\d+|r(?:\\d+|[A-Za-z]?)|e\\d+|p|v|sec\\d+|inde?x|err(?:ata)?|ins(?:ert)?"
187
+ excluded_parts = "(?!#{localities}|supp?)"
188
+
189
+ if ["NBS CSM", "NBS CS"].include?(serie)
190
+ docnumber = /v(\d+)n(\d+)/.match(code).to_a[1..-1]&.join("-")
191
+ else
192
+ # match docnumbers with localities in the first part, like NBS CIRC 11e2-1915
193
+ docnumber =
194
+ /(?:#{serie.gsub(" ", "\s|\.")})(?:\s|\.)?([0-9]+)(?:#{localities})(-[0-9]+)?/
195
+ .match(code)&.captures&.join
196
+
197
+ docnumber ||=
198
+ /(?:#{serie.gsub(" ", "\s|\.")})(?:\s|\.)? # match serie
199
+ ([0-9]+ # first part of report number
200
+ (?:#{excluded_parts}[A-Za-z]+)? # with letter but without localities
201
+ (?:-m)? # for NBS CRPL 4-m-5
202
+ (?:-[A-Za]+)? # for NIST SP 1075-NCNR, NIST SP 1113-BFRL, NIST IR 6529-a
203
+ (?:-[0-9.]+)? # second part
204
+ (?:
205
+ (?: # only big letter
206
+ (#{excluded_parts}[A-Z]|(?![a-z]))+|#{excluded_parts}[a-z]?|#{excluded_parts}[a-z]+
207
+ )? # or small letter but without localities
208
+ )
209
+ )/x
210
+ .match(code)&.[](1)&.upcase
211
+ end
212
+
213
+ unless docnumber
214
+ raise Errors::ParseError.new(
215
+ "failed to parse document identifier for #{code}",
216
+ )
217
+ end
218
+
219
+ docnumber
220
+ end
221
+
71
222
  def self.match(regex, code)
72
223
  regex.match(code)&.to_s
73
224
  end
74
225
 
75
- def to_s(format)
76
- result = "#{render_serie(format)}#{stage.to_s(format)}"\
77
- "#{code}#{render_part(format)}#{render_edition(format)}"\
78
- "#{render_update(format)}#{render_translation(format)}"
226
+ def to_s(format = :short)
227
+ result = render_serie(format)
228
+ result += " " unless format == :short || stage.nil?
229
+ result += "#{stage&.to_s(format)}"\
230
+ " #{code}#{render_part(format)}#{render_edition(format)}"\
231
+ "#{render_localities(format)}"\
232
+ "#{render_update(format)}#{render_translation(format)}"
79
233
  result = render_addendum(result, format)
80
234
 
81
235
  return result.gsub(" ", ".") if format == :mr
@@ -83,14 +237,32 @@ module NistPubid
83
237
  result
84
238
  end
85
239
 
240
+ def to_json(*args)
241
+ result = {
242
+ styles: {
243
+ short: to_s(:short),
244
+ abbrev: to_s(:abbrev),
245
+ long: to_s(:long),
246
+ mr: to_s(:mr),
247
+ }
248
+ }
249
+
250
+ instance_variables.each do |var|
251
+ val = instance_variable_get(var)
252
+ result[var.to_s.gsub('@', '')] = val unless val.nil?
253
+ end
254
+ result.to_json(*args)
255
+ end
256
+
86
257
  def render_serie(format)
87
- return "#{serie.to_s(format)} " if %i[mr short].include?(format)
258
+ if serie.to_s(format).include?(publisher.to_s(format))
259
+ return serie.to_s(format)
260
+ end
88
261
 
89
- "#{publisher.to_s(format)} #{serie.to_s(format)} "
262
+ "#{publisher.to_s(format)} #{serie.to_s(format)}"
90
263
  end
91
264
 
92
265
  def render_part(format)
93
- # TODO: Section, Supplement, Index, Insert, Errata
94
266
  result = ""
95
267
  result += "#{VOLUME_DESC[format]}#{volume}" unless volume.nil?
96
268
  result += "#{PART_DESC[format]}#{part}" unless part.nil?
@@ -99,24 +271,44 @@ module NistPubid
99
271
 
100
272
  def render_edition(format)
101
273
  result = ""
102
- result += "#{REVISION_DESC[format]}#{revision}" unless revision.nil?
274
+
275
+ result += "#{REVISION_DESC[format]}#{revision.to_s.upcase}" if revision
103
276
  result += "#{VERSION_DESC[format]}#{version}" unless version.nil?
104
277
  result += "#{EDITION_DESC[format]}#{edition}" unless edition.nil?
105
278
  result
106
279
  end
107
280
 
281
+ def render_localities(format)
282
+ result = ""
283
+ result += "#{SUPPLEMENT_DESC[format]}#{supplement}" unless supplement.nil?
284
+ result += "#{SECTION_DESC[format]}#{section}" unless section.nil?
285
+ result += "#{APPENDIX_DESC[format]}" unless appendix.nil?
286
+ result += "#{ERRATA_DESC[format]}" unless errata.nil?
287
+ result += INDEX_DESC[format] unless index.nil?
288
+ result += INSERT_DESC[format] unless insert.nil?
289
+
290
+ result
291
+ end
292
+
108
293
  def render_update(format)
109
- return "" if update.nil?
294
+ return "" if update_year.nil?
295
+
296
+ if update_number.match?(/\d+/)
297
+ update_text = update_number
298
+ update_text += "-#{update_year}" if update_year
299
+ else
300
+ update_text = "1"
301
+ end
110
302
 
111
303
  case format
112
304
  when :long
113
- " Update #{update}"
305
+ " Update #{update_text}"
114
306
  when :abbrev
115
- " Upd. #{update}"
307
+ " Upd. #{update_text}"
116
308
  when :short
117
- "/Upd #{update}"
309
+ "/Upd#{update_text}"
118
310
  when :mr
119
- ".u#{update.gsub(":", "-")}"
311
+ ".u#{update_text}"
120
312
  end
121
313
  end
122
314
 
@@ -0,0 +1,5 @@
1
+ module NistPubid
2
+ module Errors
3
+ class ParseError < StandardError; end
4
+ end
5
+ end
@@ -0,0 +1,104 @@
1
+ require "relaton_nist/data_fetcher"
2
+ require "nokogiri"
3
+ require "open-uri"
4
+
5
+ module NistPubid
6
+ class NistTechPubs
7
+ URL = "https://raw.githubusercontent.com/usnistgov/NIST-Tech-Pubs/nist-pages/xml/allrecords.xml".freeze
8
+
9
+ @converted_id = @converted_doi = {}
10
+
11
+ class << self
12
+
13
+ attr_accessor :documents, :converted_id, :converted_doi
14
+
15
+ def fetch
16
+ @documents ||= Nokogiri::XML(URI.open(URL))
17
+ .xpath("/body/query/doi_record/report-paper/report-paper_metadata")
18
+ .map { |doc| parse_docid doc }
19
+ rescue StandardError => e
20
+ warn e.message
21
+ []
22
+ end
23
+
24
+ def convert(doc)
25
+ id = @converted_id[doc[:id]] ||= NistPubid::Document.parse(doc[:id])
26
+ return id unless doc.key?(:doi)
27
+
28
+ begin
29
+ doi = @converted_doi[doc[:doi]] ||=
30
+ NistPubid::Document.parse(doc[:doi])
31
+ rescue Errors::ParseError
32
+ return id
33
+ end
34
+ # return more complete pubid
35
+ id.merge(doi)
36
+ rescue Errors::ParseError
37
+ @converted_doi[doc[:doi]] ||= NistPubid::Document.parse(doc[:doi])
38
+ end
39
+
40
+ def parse_docid(doc)
41
+ id = doc.at("publisher_item/item_number", "publisher_item/identifier")
42
+ .text.sub(%r{^/}, "")
43
+ doi = doc.at("doi_data/doi").text.gsub("10.6028/", "")
44
+ title = doc.at("titles/title").text
45
+ title += " #{doc.at('titles/subtitle').text}" if doc.at("titles/subtitle")
46
+ case doi
47
+ when "10.6028/NBS.CIRC.12e2revjune" then id.sub!("13e", "12e")
48
+ when "10.6028/NBS.CIRC.36e2" then id.sub!("46e", "36e")
49
+ when "10.6028/NBS.HB.67suppJune1967" then id.sub!("1965", "1967")
50
+ when "10.6028/NBS.HB.105-1r1990" then id.sub!("105-1-1990", "105-1r1990")
51
+ when "10.6028/NIST.HB.150-10-1995" then id.sub!(/150-10$/, "150-10-1995")
52
+ end
53
+
54
+ { id: id, doi: doi, title: title }
55
+ end
56
+
57
+ def comply_with_pubid
58
+ fetch.select do |doc|
59
+ convert(doc).to_s == doc[:id]
60
+ rescue Errors::ParseError
61
+ false
62
+ end
63
+ end
64
+
65
+ def different_with_pubid
66
+ fetch.reject do |doc|
67
+ convert(doc).to_s == doc[:id]
68
+ rescue Errors::ParseError
69
+ true
70
+ end
71
+ end
72
+
73
+ def parse_fail_with_pubid
74
+ fetch.select do |doc|
75
+ convert(doc).to_s && false
76
+ rescue Errors::ParseError
77
+ true
78
+ end
79
+ end
80
+
81
+ # returning current document id, doi, title and final PubID
82
+ def status
83
+ fetch.map do |doc|
84
+ final_doc = convert(doc)
85
+ {
86
+ id: doc[:id],
87
+ doi: doc[:doi],
88
+ title: doc[:title],
89
+ finalPubId: final_doc.to_s,
90
+ mr: final_doc.to_s(:mr),
91
+ }
92
+ rescue Errors::ParseError
93
+ {
94
+ id: doc[:id],
95
+ doi: doc[:doi],
96
+ title: doc[:title],
97
+ finalPubId: "parse error",
98
+ mr: "parse_error"
99
+ }
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -9,7 +9,7 @@ module NistPubid
9
9
  @publisher = publisher
10
10
  end
11
11
 
12
- def to_s(format)
12
+ def to_s(format = :short)
13
13
  return @publisher if %i[short mr].include?(format)
14
14
 
15
15
  PUBLISHERS[format.to_s][@publisher]
@@ -8,7 +8,7 @@ module NistPubid
8
8
  @serie = serie == "NISTIR" ? "NIST IR" : serie
9
9
  end
10
10
 
11
- def to_s(format)
11
+ def to_s(format = :short)
12
12
  return @serie if %i[short mr].include?(format)
13
13
 
14
14
  result = SERIES[format.to_s][@serie]
@@ -18,7 +18,9 @@ module NistPubid
18
18
  end
19
19
 
20
20
  def self.regexp
21
- /(#{(SERIES["long"].keys + SERIES["mr"].values + ["NISTIR"]).join('|')})(?=\.|\s)/
21
+ /(#{(SERIES["long"].keys + SERIES["mr"].values
22
+ .map { |v| v.gsub(".", '\.') } + ["NISTIR"])
23
+ .sort_by(&:length).reverse.join('|')})/
22
24
  end
23
25
  end
24
26
  end
@@ -2,21 +2,36 @@ STAGES = YAML.load_file(File.join(File.dirname(__FILE__), "../../stages.yaml"))
2
2
 
3
3
  module NistPubid
4
4
  class Stage
5
- attr_accessor :stage
5
+ attr_accessor :stage, :original_code
6
6
 
7
- def initialize(stage:)
8
- @stage = stage
7
+ def initialize(original_code)
8
+ self.original_code = original_code
9
+ @stage = self.class.regexp.match(original_code)&.[](1)
9
10
  end
10
11
 
11
- def to_s(format)
12
- return "" if @stage.nil?
13
- return "#{@stage} " if %i[short mr].include?(format)
12
+ def to_s(format = :short)
13
+ return "" if nil?
14
14
 
15
- "#{STAGES[@stage]} "
15
+ case format
16
+ when :short
17
+ "(#{@stage})"
18
+ when :mr
19
+ @stage
20
+ else
21
+ STAGES[@stage]
22
+ end
23
+ end
24
+
25
+ def self.parse(code)
26
+ new(regexp.match(code)&.to_s)
16
27
  end
17
28
 
18
29
  def self.regexp
19
- /(#{STAGES.keys.join('|')})(?=\.|\s)/
30
+ /\((#{STAGES.keys.join('|')})\)/
31
+ end
32
+
33
+ def nil?
34
+ @stage.nil?
20
35
  end
21
36
  end
22
37
  end
@@ -1,3 +1,3 @@
1
1
  module NistPubid
2
- VERSION = "0.1.2".freeze
2
+ VERSION = "0.1.6".freeze
3
3
  end
data/lib/nist_pubid.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "yaml"
4
- require "nist_pubid/document"
5
- require "nist_pubid/publisher"
6
- require "nist_pubid/serie"
7
- require "nist_pubid/stage"
4
+ require_relative "nist_pubid/document"
5
+ require_relative "nist_pubid/publisher"
6
+ require_relative "nist_pubid/serie"
7
+ require_relative "nist_pubid/stage"
8
+ require_relative "nist_pubid/errors"
9
+ require_relative "nist_pubid/nist_tech_pubs"
data/nist_pubid.gemspec CHANGED
@@ -28,4 +28,10 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  spec.add_development_dependency "rake", "~> 13.0"
30
30
  spec.add_development_dependency "rspec", "~> 3.0"
31
+ spec.add_development_dependency "vcr"
32
+ spec.add_development_dependency "webmock"
33
+
34
+ spec.add_dependency "relaton-nist"
35
+ spec.add_dependency "nokogiri"
36
+ spec.add_dependency "thor"
31
37
  end
data/series.yaml CHANGED
@@ -87,7 +87,7 @@ mr:
87
87
  NBS BH: NBS.BH
88
88
  NBS CRPL: NBS.CRPL
89
89
  NBS CRPL-F-A: NBS.CRPL-F-A
90
- NBS CRPL-F-B: NBS CRPL-F-B245
90
+ NBS CRPL-F-B: NBS CRPL-F-B
91
91
  NBS IP: NBS.IP
92
92
  NBS CIRC: NBS.CIRC
93
93
  NBS CIS: NBS.CIS
data/stages.yaml CHANGED
@@ -2,4 +2,4 @@ IPD: Initial Public Draft
2
2
  2PD: Second Public Draft
3
3
  FPD: Final Public Draft
4
4
  WD: Work-in-Progress Draft
5
- PreD: Preliminary Draft
5
+ PRD: Preliminary Draft
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nist-pubid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-08 00:00:00.000000000 Z
11
+ date: 2022-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,24 +38,99 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: vcr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: relaton-nist
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: nokogiri
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: thor
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
41
111
  description: Library to generate, parse and manipulate NIST PubID.
42
112
  email:
43
113
  - open.source@ribose.com
44
- executables: []
114
+ executables:
115
+ - nist-pubid
45
116
  extensions: []
46
117
  extra_rdoc_files:
47
118
  - README.adoc
48
119
  - LICENSE.txt
49
120
  files:
50
121
  - ".github/workflows/rake.yml"
122
+ - ".github/workflows/release.yml"
51
123
  - ".rspec"
52
124
  - ".rubocop.yml"
53
125
  - Gemfile
54
126
  - LICENSE.txt
55
127
  - README.adoc
56
128
  - Rakefile
129
+ - exe/nist-pubid
57
130
  - lib/nist_pubid.rb
58
131
  - lib/nist_pubid/document.rb
132
+ - lib/nist_pubid/errors.rb
133
+ - lib/nist_pubid/nist_tech_pubs.rb
59
134
  - lib/nist_pubid/publisher.rb
60
135
  - lib/nist_pubid/serie.rb
61
136
  - lib/nist_pubid/stage.rb
@@ -83,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
158
  - !ruby/object:Gem::Version
84
159
  version: '0'
85
160
  requirements: []
86
- rubygems_version: 3.1.4
161
+ rubygems_version: 3.3.3
87
162
  signing_key:
88
163
  specification_version: 4
89
164
  summary: Library to generate, parse and manipulate NIST PubID.