nistbib 0.1.5 → 0.1.6

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
  SHA1:
3
- metadata.gz: 93e42e10363b0cf5ace10ea2540e20a7d96bacfa
4
- data.tar.gz: 958b66ae4601efb35dbd366a80b5c09ea22a50bd
3
+ metadata.gz: 896a6c8fd4132200e685aa768a3bab6f089f9f4b
4
+ data.tar.gz: f399bbd50fcbe7cb1f70d4dee3fb37619f5b051a
5
5
  SHA512:
6
- metadata.gz: 4fb26a328169066da7e921df16b525a67baa6fc5b8ddebb14fbcb08af41decddd6e27b40a173aa9015972e9a22f844ceea4ee7dd711444600efac36a240a49eb
7
- data.tar.gz: e71f295627f4f640f81432508783365ccbc868cc98f277ecb153e920a9e62339d6cf79f81f64d8ee731b09ede32414d3322a9ab162dce416b543fc040da0055b
6
+ metadata.gz: 28bde9d7d3a30d628a53e0f06a4444859b870aea0a65fcab7ca9315e2330f0a86017b1bce5ea74636ea6b8480e26b294816319f338c1a2081cdaceb0d56b833a
7
+ data.tar.gz: 5ba05e4c1ecb61b89a05a67c042ec4ce32119f23a139aca620c2715c1177d1eb75c4482a433e2dc5913d910f53c12483fad737b4b1c4b3e8aeea694dfa367fb2
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nistbib (0.1.5)
5
- relaton-bib (~> 0.1.1)
4
+ nistbib (0.1.6)
5
+ relaton-bib (~> 0.1.5)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -34,7 +34,7 @@ GEM
34
34
  pry (~> 0.10)
35
35
  public_suffix (3.0.3)
36
36
  rake (10.5.0)
37
- relaton-bib (0.1.3)
37
+ relaton-bib (0.1.5)
38
38
  addressable
39
39
  nokogiri (~> 1.8.4)
40
40
  rspec (3.8.0)
data/README.adoc CHANGED
@@ -48,13 +48,35 @@ hit_collection = NistBib::NistBibliography.search("8200")
48
48
  [source,ruby]
49
49
  ----
50
50
  item.to_xml
51
- => "<nist-standard>
51
+ => "<bibitem id="NISTIR8200(DRAFT)" type="standard">
52
52
  <fetched>2019-05-03</fetched>
53
53
  <title format="text/plain" language="en" script="Latn">
54
54
  Interagency Report on Status of International Cybersecurity Standardization for the Internet of Things (IoT)
55
55
  </title>
56
56
  ...
57
- </nist-standard>"
57
+ <bibitem>"
58
+ ----
59
+ With argument `bibdata: true` it ouputs XML wrapped by `bibdata` element and adds flavour `ext` element.
60
+ [source,ruby]
61
+ ----
62
+ item.to_xml bibdata: true
63
+ => "<bibdata type="standard">
64
+ <fetched>2019-05-17</fetched>
65
+ <title format="text/plain" language="en" script="Latn">
66
+ Interagency Report on Status of International Cybersecurity Standardization for the Internet of Things (IoT)
67
+ </title>
68
+ ...
69
+ <ext>
70
+ <doctype>stadard</doctype>
71
+ <keyword>cybersecurity</keyword>
72
+ <keyword>cybersecurity objectives</keyword>
73
+ ...
74
+ <commentperiod>
75
+ <from>2018-02-01</from>
76
+ <to>2018-04-18</to>
77
+ </commentperiod>
78
+ </ext>
79
+ </bibdata>"
58
80
  ----
59
81
 
60
82
  === Get code, and year
@@ -1,20 +1,11 @@
1
1
  module NistBib
2
- class DocumentStatus
2
+ class DocumentStatus < RelatonBib::DocumentStatus
3
3
  STAGES = %w[
4
4
  draft-internal draft-wip draft-prelim draft-public final final-review
5
5
  ].freeze
6
6
 
7
7
  SUBSTAGES = %w[active retired withdrawn].freeze
8
8
 
9
- # @return [String]
10
- attr_reader :stage
11
-
12
- # @return [String, NilClass]
13
- attr_reader :substage
14
-
15
- # @return [String, NilClass]
16
- attr_reader :iteration
17
-
18
9
  # @param stage [String]
19
10
  # @param substage [String, NilClass]
20
11
  # @param iteration [String, NilClass]
@@ -27,18 +18,7 @@ module NistBib
27
18
  raise ArgumentError, "invalid argument: substage (#{substage})"
28
19
  end
29
20
 
30
- @stage = stage
31
- @substage = substage
32
- @iteration = iteration
33
- end
34
-
35
- # @param builder [Nokogiri::XML::Builder]
36
- def to_xml(builder)
37
- builder.status do
38
- builder.stage stage
39
- builder.substage substage if substage
40
- builder.iteration iteration if iteration
41
- end
21
+ super
42
22
  end
43
23
  end
44
24
  end
data/lib/nistbib/hit.rb CHANGED
@@ -37,8 +37,8 @@ module NistBib
37
37
  end
38
38
 
39
39
  # @return [String]
40
- def to_xml
41
- fetch.to_xml
40
+ def to_xml(**opts)
41
+ fetch.to_xml **opts
42
42
  end
43
43
  end
44
44
  end
@@ -23,6 +23,7 @@ module NistBib
23
23
  # @param ref_nbr [String]
24
24
  # @param year [String]
25
25
  # @param opts [Hash]
26
+ # @option opts [String] :stage
26
27
  def initialize(ref_nbr, year = nil, opts)
27
28
  @text = ref_nbr
28
29
  @year = year
@@ -35,7 +36,7 @@ module NistBib
35
36
  url = "#{DOMAIN}/publications/search?keywords-lg=#{ref_nbr}"
36
37
  url += "&dateFrom-lg=#{from}" if from
37
38
  url += "&dateTo-lg=#{to}" if to
38
- url += "&status-lg=Draft" if /PD/ =~ opts[:stage]
39
+ url += "&status-lg=Draft,Withdrawn" if /PD/ =~ opts[:stage]
39
40
  doc = Nokogiri::HTML OpenURI.open_uri(::Addressable::URI.parse(url).normalize)
40
41
  hits = doc.css("table.publications-table > tbody > tr").map do |h|
41
42
  link = h.at("td/div/strong/a")
@@ -1,7 +1,7 @@
1
1
  module NistBib
2
2
  class NistBibliographicItem < RelatonBib::BibliographicItem
3
- # @return [NistBib::NistSeries, NilClass]
4
- attr_reader :nistseries
3
+ # @return [String]
4
+ attr_reader :doctype
5
5
 
6
6
  # @return [Array<NistBib::Keyword>]
7
7
  attr_reader :keyword
@@ -29,6 +29,7 @@ module NistBib
29
29
  # @param classification [RelatonBib::Classification, NilClass]
30
30
  # @param validity [RelatonBib:Validity, NilClass]
31
31
  # @param fetched [Date, NilClass] default nil
32
+ # @param doctype [String]
32
33
  # @param keyword [Array<NistBib::Keyword>]
33
34
  # @param commentperiod [NistBib::CommentPeriod]
34
35
  #
@@ -54,21 +55,23 @@ module NistBib
54
55
  # @option relations [String] :type
55
56
  # @option relations [RelatonBib::BibliographicItem] :bibitem
56
57
  # @option relations [Array<RelatonBib::BibItemLocality>] :bib_locality
57
- #
58
- # @param nistseries [Nist::NistSeries, NilClass]
59
58
  def initialize(**args)
60
- @nistseries = args.delete :nistseries
59
+ @doctype = "stadard"
61
60
  @keyword = args.delete(:keyword) || []
62
61
  @commentperiod = args.delete :commentperiod
63
62
  super
64
63
  end
65
64
 
66
65
  # @param builder [Nokogiri::XML::Builder]
67
- def to_xml(builder = nil)
68
- super builder, root: :bibitem, date_format: :short do |b|
69
- nistseries&.to_xml b
70
- keyword.each { |kw| kw.to_xml b }
71
- commentperiod&.to_xml b
66
+ def to_xml(builder = nil, **opts)
67
+ super builder, date_format: :short, **opts do |b|
68
+ if opts[:bibdata]
69
+ b.ext do
70
+ b.doctype doctype
71
+ keyword.each { |kw| kw.to_xml b }
72
+ commentperiod&.to_xml b
73
+ end
74
+ end
72
75
  end
73
76
  end
74
77
  end
@@ -2,7 +2,6 @@ require "relaton_bib"
2
2
  require "nistbib/nist_bibliographic_item"
3
3
  require "nistbib/scrapper"
4
4
  require "nistbib/hit_collection"
5
- require "nistbib/nist_series"
6
5
  require "nistbib/xml_parser"
7
6
  require "nistbib/keyword"
8
7
  require "nistbib/comment_period"
@@ -22,10 +21,15 @@ module NistBib
22
21
 
23
22
  # @param code [String] the NIST standard Code to look up (e..g "8200")
24
23
  # @param year [String] the year the standard was published (optional)
25
- # @param opts [Hash] options; restricted to :all_parts if all-parts reference is required
24
+ #
25
+ # @param opts [Hash] options
26
+ # @option opts [TrueClass, FalseClass] :all_parts restricted to all parts
27
+ # if all-parts reference is required
28
+ # @option opts [TrueClass, FalseClass] :bibdata
29
+ #
26
30
  # @return [String] Relaton XML serialisation of reference
27
31
  def get(code, year = nil, opts = {})
28
- /^(?<code2>[^\(]+)\((?<date2>\w+\s(\d{2},\s)?\d{4})\)(\s\()?(?<stage>[^\)]+)?/ =~ code
32
+ /^(?<code2>[^\(]+)(\((?<date2>\w+\s(\d{2},\s)?\d{4})\))?\s?\(?((?<=\()(?<stage>[^\)]+))?/ =~ code
29
33
  if code2
30
34
  code = code2.strip
31
35
  if date2
@@ -57,7 +61,7 @@ module NistBib
57
61
  private
58
62
 
59
63
  def nistbib_get1(code, year, opts)
60
- result = nistbib_search_filter(code, year, opts) or return nil
64
+ result = nistbib_search_filter(code, year, opts) || (return nil)
61
65
  ret = nistbib_results_filter(result, year, opts)
62
66
  return ret[:ret] if ret[:ret]
63
67
 
@@ -70,19 +74,35 @@ module NistBib
70
74
  # Only expects the first page of results to be populated.
71
75
  # Does not match corrigenda etc (e.g. ISO 3166-1:2006/Cor 1:2007)
72
76
  # If no match, returns any years which caused mismatch, for error reporting
77
+ #
78
+ # @param opts [Hash] options
79
+ # @option opts [Time] :issued_date
80
+ # @option opts [Time] :issued_date
81
+ # @option opts [String] :stage
82
+ #
83
+ # @retur [Hash]
73
84
  def nistbib_results_filter(result, year, opts)
74
85
  missed_years = []
75
86
  result.each_slice(3) do |s| # ISO website only allows 3 connections
76
87
  fetch_pages(s, 3).each_with_index do |r, _i|
77
88
  if opts[:issued_date]
78
89
  r.dates.select { |d| d.type == "issued" }.each do |d|
79
- return { ret: r } if opts[:issued_date] == d.on
90
+ next unless opts[:issued_date] == d.on
80
91
  end
81
92
  elsif opts[:updated_date]
82
93
  r.dates.select { |d| d.type == "published" }.each do |d|
83
- return { ret: r } if opts[:updated_date] == d.on
94
+ next unless opts[:updated_date] == d.on
84
95
  end
85
96
  end
97
+ if opts[:stage]
98
+ iter = opts[:stage][-3]
99
+ iteration = case iter
100
+ when "I" then 1
101
+ when "F" then "final"
102
+ else iter.to_i
103
+ end
104
+ next if iter && r.status.iteration != iteration
105
+ end
86
106
  return { ret: r } if !year
87
107
 
88
108
  r.dates.select { |d| d.type == "published" }.each do |d|
@@ -15,20 +15,20 @@ module NistBib
15
15
  NistBibliographicItem.new(
16
16
  fetched: Date.today.to_s,
17
17
  type: "standard",
18
- id: fetch_id(doc),
18
+ # id: fetch_id(doc),
19
19
  titles: fetch_titles(hit_data),
20
20
  link: fetch_link(doc),
21
21
  docid: fetch_docid(doc),
22
22
  dates: fetch_dates(doc, hit_data[:release_date]),
23
23
  contributors: fetch_contributors(doc),
24
- edition: nil,
24
+ edition: fetch_edition(hit_data[:code]),
25
25
  language: ["en"],
26
26
  script: ["Latn"],
27
27
  abstract: fetch_abstract(doc),
28
28
  docstatus: fetch_status(doc, hit_data[:status]),
29
29
  copyright: fetch_copyright(doc),
30
30
  relations: fetch_relations(doc),
31
- nistseries: fetch_nistseries(doc),
31
+ series: fetch_series(doc),
32
32
  keyword: fetch_keywords(doc),
33
33
  commentperiod: fetch_commentperiod(doc),
34
34
  )
@@ -47,7 +47,7 @@ module NistBib
47
47
 
48
48
  # Fetch docid.
49
49
  # @param doc [Nokogiri::HTML::Document]
50
- # @return [Hash]
50
+ # @return [Array<RelatonBib::DocumentIdentifier>]
51
51
  def fetch_docid(doc)
52
52
  item_ref = doc.at("//div[contains(@class, 'publications-detail')]/h3").
53
53
  text.strip
@@ -59,10 +59,10 @@ module NistBib
59
59
  # Fetch id.
60
60
  # @param doc [Nokogiri::HTML::Document]
61
61
  # @return [String]
62
- def fetch_id(doc)
63
- doc.at("//div[contains(@class, 'publications-detail')]/h3").text.
64
- strip.gsub(/\s/, "")
65
- end
62
+ # def fetch_id(doc)
63
+ # doc.at("//div[contains(@class, 'publications-detail')]/h3").text.
64
+ # strip.gsub(/\s/, "")
65
+ # end
66
66
 
67
67
  # Fetch status.
68
68
  # @param doc [Nokogiri::HTML::Document]
@@ -72,19 +72,36 @@ module NistBib
72
72
  case status
73
73
  when "draft (withdrawn)"
74
74
  stage = "draft-public"
75
- substage = "withdrawn"
75
+ subst = "withdrawn"
76
76
  when "retired draft"
77
77
  stage = "draft-public"
78
- substage = "retired"
78
+ subst = "retired"
79
79
  when "withdrawn"
80
80
  stage = "final"
81
- substage = "withdrawn"
81
+ subst = "withdrawn"
82
82
  when "draft"
83
83
  stage = "draft-public"
84
- substage = "active"
84
+ subst = "active"
85
85
  else
86
86
  stage = status
87
- substage = "active"
87
+ subst = "active"
88
+ end
89
+
90
+ iter = nil
91
+ if stage.include? "draft"
92
+ iter = 1
93
+ history = doc.xpath("//span[@id='pub-history-container']/a"\
94
+ "|//span[@id='pub-history-container']/span")
95
+ history.each_with_index do |h, idx|
96
+ next if h.name == "a"
97
+
98
+ iter = idx + 1 if idx.positive?
99
+ # iter = if lsif idx < (history.size - 1) && !history.last.text.include?("Draft")
100
+ # "final"
101
+ # elsif idx.positive? then idx + 1
102
+ # end
103
+ break
104
+ end
88
105
  end
89
106
 
90
107
  # if doc.at "//p/strong[text()='Withdrawn:']"
@@ -97,7 +114,7 @@ module NistBib
97
114
  # wip = item_ref.match(/(?<=\()\w+/).to_s
98
115
  # stage = "draft-public" if wip == "DRAFT"
99
116
  # end
100
- NistBib::DocumentStatus.new(stage: stage, substage: substage)
117
+ NistBib::DocumentStatus.new stage: stage, substage: subst, iteration: iter
101
118
  end
102
119
 
103
120
  # Fetch titles.
@@ -140,6 +157,7 @@ module NistBib
140
157
  contribs + contributors(editors, "editor")
141
158
  end
142
159
 
160
+ # rubocop:disable Metrics/CyclomaticComplexity
143
161
  def contributors(doc, role)
144
162
  return [] if doc.nil?
145
163
 
@@ -171,6 +189,13 @@ module NistBib
171
189
  RelatonBib::ContributionInfo.new entity: entity, role: [role]
172
190
  end
173
191
  end
192
+ # rubocop:enable Metrics/CyclomaticComplexity
193
+
194
+ def fetch_edition(code)
195
+ return unless /(?<=Rev\.\s)(?<rev>\d+)/ =~ code
196
+
197
+ "Revision #{rev}"
198
+ end
174
199
 
175
200
  # Fetch abstracts.
176
201
  # @param doc [Nokigiri::HTML::Document]
@@ -238,13 +263,28 @@ module NistBib
238
263
  )
239
264
  end
240
265
 
241
- def fetch_nistseries(doc)
242
- doc.xpath("//p/strong[.='Document History:']/following-sibling::*[not(self::br)]").each do |s|
243
- NistSeries::ABBREVIATIONS.each do |k, _v|
244
- return NistSeries.new k if s.text.include? k
245
- end
246
- end
247
- nil
266
+ def fetch_series(doc)
267
+ series = doc.xpath "//span[@id='pub-history-container']/a"\
268
+ "|//span[@id='pub-history-container']/span"
269
+ series.map.with_index do |s, idx|
270
+ next if s.name == "span"
271
+
272
+ iter = if idx.zero? then "I"
273
+ # elsif status == "final" && idx == (series.size - 1) then "F"
274
+ else idx + 1
275
+ end
276
+
277
+ content = s.text.match(/^[^\(]+/).to_s.strip.gsub " ", " "
278
+
279
+ ref = case content.match(/\w+/).to_s
280
+ when "Draft" then content.match(/(?<=Draft\s).+/).to_s + " (#{iter}PD)"
281
+ end
282
+
283
+ fref = RelatonBib::FormattedRef.new(
284
+ content: ref, language: "en", script: "Latn", format: "text/plain",
285
+ )
286
+ RelatonBib::Series.new(formattedref: fref)
287
+ end.select { |s| s }
248
288
  end
249
289
 
250
290
  def fetch_keywords(doc)
@@ -1,3 +1,3 @@
1
1
  module NistBib
2
- VERSION = "0.1.5".freeze
2
+ VERSION = "0.1.6".freeze
3
3
  end
@@ -3,7 +3,7 @@ module NistBib
3
3
  class << self
4
4
  def from_xml(xml)
5
5
  doc = Nokogiri::XML xml
6
- nistitem = doc.at("/bibitem") || doc.at("/bibdata")
6
+ nistitem = doc.at("/bibitem|/bibdata")
7
7
  NistBibliographicItem.new(item_data(nistitem))
8
8
  end
9
9
 
@@ -11,10 +11,11 @@ module NistBib
11
11
 
12
12
  def item_data(nistitem)
13
13
  data = super
14
- data.delete :series
15
- data[:nistseries] = fetch_nistseries(nistitem)
16
- data[:keyword] = fetch_keyword(nistitem)
17
- data[:commentperiod] = fetch_commentperiod(nistitem)
14
+ ext = nistitem.at "./ext"
15
+ return data unless ext
16
+
17
+ data[:keyword] = fetch_keyword(ext)
18
+ data[:commentperiod] = fetch_commentperiod(ext)
18
19
  data
19
20
  end
20
21
 
@@ -25,7 +26,7 @@ module NistBib
25
26
  DocumentStatus.new(
26
27
  stage: status.at("stage")&.text,
27
28
  substage: status.at("substage")&.text,
28
- iteration: status.at("iteraton")&.text,
29
+ iteration: status.at("iteration")&.text,
29
30
  )
30
31
  end
31
32
 
@@ -41,13 +42,6 @@ module NistBib
41
42
  Keyword.new kw.children.first.to_xml
42
43
  end
43
44
  end
44
-
45
- def fetch_nistseries(item)
46
- series = item.at "./series"
47
- return unless series
48
-
49
- NistSeries.new series.at("./abbreviation").text.upcase.gsub("-", " ")
50
- end
51
45
  end
52
46
  end
53
47
  end
@@ -11,7 +11,7 @@ module Relaton
11
11
  @idtype = "NIST"
12
12
  end
13
13
 
14
- def get(code, date, opts)
14
+ def get(code, date = nil, opts = {})
15
15
  ::NistBib::NistBibliography.get(code, date, opts)
16
16
  end
17
17
 
data/nistbib.gemspec CHANGED
@@ -34,5 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "vcr"
35
35
  spec.add_development_dependency "webmock"
36
36
 
37
- spec.add_dependency "relaton-bib", "~> 0.1.1"
37
+ spec.add_dependency "relaton-bib", "~> 0.1.5"
38
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nistbib
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
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: 2019-05-13 00:00:00.000000000 Z
11
+ date: 2019-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 0.1.1
173
+ version: 0.1.5
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 0.1.1
180
+ version: 0.1.5
181
181
  description: 'NistBib: retrive NIST standards.'
182
182
  email:
183
183
  - open.source@ribose.com
@@ -205,7 +205,6 @@ files:
205
205
  - lib/nistbib/keyword.rb
206
206
  - lib/nistbib/nist_bibliographic_item.rb
207
207
  - lib/nistbib/nist_bibliography.rb
208
- - lib/nistbib/nist_series.rb
209
208
  - lib/nistbib/scrapper.rb
210
209
  - lib/nistbib/version.rb
211
210
  - lib/nistbib/workers_pool.rb
@@ -1,35 +0,0 @@
1
- module NistBib
2
- class NistSeries
3
- ABBREVIATIONS = {
4
- "NISTIR" => "NIST Interagency/Internal Report",
5
- "NIST SP" => "NIST Special Publication",
6
- "NIST FIPS" => "NIST Federal Information Processing Standards",
7
- }.freeze
8
-
9
- # @return [String]
10
- attr_reader :type
11
-
12
- # @return [String]
13
- attr_reader :title
14
-
15
- # @return [RalatonBib::LocalizedString, NilClass]
16
- attr_reader :abbreviation
17
-
18
- # @param abbreviation [RelatonBib::LocalizedString, NilClass]
19
- def initialize(abbreviation)
20
- @type = "main"
21
- @abbreviation = RelatonBib::LocalizedString.new(
22
- abbreviation.downcase.gsub(" ", "-"), "en", "Latn"
23
- )
24
- @title = ABBREVIATIONS[abbreviation]
25
- end
26
-
27
- # @param builder [Nokogiri::XML::Builder]
28
- def to_xml(builder)
29
- builder.series type: type do
30
- builder.title title
31
- builder.abbreviation { abbreviation.to_xml builder } if abbreviation
32
- end
33
- end
34
- end
35
- end