relaton 3.0.0.pre.alpha.16 → 3.0.0.pre.alpha.18

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/data/equivalence/adoption-chains.yaml +38 -0
  3. data/lib/relaton/3gpp/CLAUDE.md +187 -0
  4. data/lib/relaton/3gpp/README.adoc +149 -0
  5. data/lib/relaton/adobe/CLAUDE.md +104 -0
  6. data/lib/relaton/bib/CLAUDE.md +130 -0
  7. data/lib/relaton/bib/README.adoc +330 -0
  8. data/lib/relaton/bib/model/series.rb +1 -1
  9. data/lib/relaton/bipm/CLAUDE.md +173 -0
  10. data/lib/relaton/bipm/README.adoc +352 -0
  11. data/lib/relaton/bipm/data_fetcher.rb +3 -2
  12. data/lib/relaton/bsi/CLAUDE.md +35 -0
  13. data/lib/relaton/bsi/README.adoc +112 -0
  14. data/lib/relaton/calconnect/CLAUDE.md +177 -0
  15. data/lib/relaton/calconnect/README.adoc +140 -0
  16. data/lib/relaton/ccsds/CLAUDE.md +74 -0
  17. data/lib/relaton/ccsds/README.adoc +154 -0
  18. data/lib/relaton/cen/CLAUDE.md +219 -0
  19. data/lib/relaton/cen/README.adoc +155 -0
  20. data/lib/relaton/cie/CLAUDE.md +90 -0
  21. data/lib/relaton/cie/README.adoc +121 -0
  22. data/lib/relaton/core/CLAUDE.md +140 -0
  23. data/lib/relaton/core/README.adoc +64 -0
  24. data/lib/relaton/core/data_fetcher.rb +50 -3
  25. data/lib/relaton/db/CLAUDE.md +373 -0
  26. data/lib/relaton/db.rb +19 -1
  27. data/lib/relaton/doi/CLAUDE.md +105 -0
  28. data/lib/relaton/doi/README.adoc +89 -0
  29. data/lib/relaton/easc/CLAUDE.md +85 -0
  30. data/lib/relaton/ecma/CLAUDE.md +217 -0
  31. data/lib/relaton/ecma/README.adoc +178 -0
  32. data/lib/relaton/equivalence.rb +89 -0
  33. data/lib/relaton/etsi/CLAUDE.md +219 -0
  34. data/lib/relaton/etsi/README.adoc +137 -0
  35. data/lib/relaton/evs/CLAUDE.md +120 -0
  36. data/lib/relaton/evs/README.adoc +27 -0
  37. data/lib/relaton/gb/CLAUDE.md +47 -0
  38. data/lib/relaton/gb/README.adoc +169 -0
  39. data/lib/relaton/gost/CLAUDE.md +100 -0
  40. data/lib/relaton/iala/CLAUDE.md +97 -0
  41. data/lib/relaton/iana/CLAUDE.md +105 -0
  42. data/lib/relaton/iana/README.adoc +107 -0
  43. data/lib/relaton/iec/CLAUDE.md +13 -0
  44. data/lib/relaton/iec/README.adoc +280 -0
  45. data/lib/relaton/iec/data_fetcher.rb +24 -8
  46. data/lib/relaton/iec/project_fetcher.rb +48 -0
  47. data/lib/relaton/iec/project_parser.rb +111 -0
  48. data/lib/relaton/iec.rb +5 -0
  49. data/lib/relaton/ieee/CLAUDE.md +176 -0
  50. data/lib/relaton/ieee/README.adoc +131 -0
  51. data/lib/relaton/ietf/CLAUDE.md +357 -0
  52. data/lib/relaton/ietf/README.adoc +167 -0
  53. data/lib/relaton/iho/CLAUDE.md +70 -0
  54. data/lib/relaton/iho/README.adoc +119 -0
  55. data/lib/relaton/index/CLAUDE.md +207 -0
  56. data/lib/relaton/index/README.adoc +221 -0
  57. data/lib/relaton/index/dataset_lock.rb +122 -0
  58. data/lib/relaton/index/family.rb +63 -0
  59. data/lib/relaton/index/type.rb +32 -0
  60. data/lib/relaton/index.rb +3 -0
  61. data/lib/relaton/isbn/CLAUDE.md +47 -0
  62. data/lib/relaton/isbn/README.adoc +91 -0
  63. data/lib/relaton/iso/CLAUDE.md +38 -0
  64. data/lib/relaton/iso/README.adoc +370 -0
  65. data/lib/relaton/iso/data_fetcher.rb +16 -1
  66. data/lib/relaton/itu/CLAUDE.md +685 -0
  67. data/lib/relaton/itu/README.adoc +188 -0
  68. data/lib/relaton/jcgm/CLAUDE.md +107 -0
  69. data/lib/relaton/jis/CLAUDE.md +64 -0
  70. data/lib/relaton/jis/README.adoc +167 -0
  71. data/lib/relaton/logger/CLAUDE.md +37 -0
  72. data/lib/relaton/logger/README.adoc +120 -0
  73. data/lib/relaton/nist/CLAUDE.md +180 -0
  74. data/lib/relaton/nist/README.adoc +389 -0
  75. data/lib/relaton/nist/bibliography.rb +17 -1
  76. data/lib/relaton/nist/data_fetcher.rb +60 -4
  77. data/lib/relaton/nist/hit_collection.rb +121 -59
  78. data/lib/relaton/nist/scraper.rb +21 -7
  79. data/lib/relaton/oasis/CLAUDE.md +251 -0
  80. data/lib/relaton/oasis/README.adoc +132 -0
  81. data/lib/relaton/ogc/CLAUDE.md +242 -0
  82. data/lib/relaton/ogc/README.adoc +134 -0
  83. data/lib/relaton/oiml/CLAUDE.md +47 -0
  84. data/lib/relaton/oiml/README.adoc +70 -0
  85. data/lib/relaton/omg/CLAUDE.md +137 -0
  86. data/lib/relaton/omg/README.adoc +101 -0
  87. data/lib/relaton/plateau/CLAUDE.md +126 -0
  88. data/lib/relaton/plateau/README.adoc +139 -0
  89. data/lib/relaton/sdo/CLAUDE.md +81 -0
  90. data/lib/relaton/un/CLAUDE.md +91 -0
  91. data/lib/relaton/un/README.adoc +125 -0
  92. data/lib/relaton/version.rb +1 -1
  93. data/lib/relaton/w3c/CLAUDE.md +369 -0
  94. data/lib/relaton/w3c/README.adoc +140 -0
  95. data/lib/relaton/w3c/data_fetcher.rb +1 -1
  96. data/lib/relaton/xsf/CLAUDE.md +189 -0
  97. data/lib/relaton/xsf/README.adoc +127 -0
  98. data/lib/relaton.rb +1 -0
  99. metadata +83 -2
@@ -0,0 +1,352 @@
1
+ = RelatonBipm: retrieve BIPM Standards for bibliographic use using the BibliographicItem model
2
+
3
+ RelatonBipm is a Ruby gem that implements the https://github.com/metanorma/metanorma-model-iso#iso-bibliographic-item[IsoBibliographicItem model].
4
+
5
+ You can use it to retrieve metadata of BIPM Standards from https://www.bipm.org, and access such metadata through the `BipmBibliographicItem` object.
6
+
7
+ == Usage
8
+
9
+ === Search for a standard using keywords
10
+
11
+ ==== References for Si-Brochure documents
12
+
13
+ `BIPM {DOCUMENT_NAME}`
14
+
15
+ Allowed document names are:
16
+
17
+ - CCEM-GD-RSI-1
18
+ - CCL-GD-MeP-1
19
+ - CCL-GD-MeP-2
20
+ - CCL-GD-MeP-3
21
+ - CCM-GD-RSI-1
22
+ - CCM-GD-RSI-2
23
+ - SI MEP A1
24
+ - SI MEP Cd1
25
+ - Rapport BIPM-2019/05
26
+ - SI MEP KUPRTM
27
+ - SI MEP KAPRT
28
+ - SI MEP K1
29
+ - SI MEP KLJNT
30
+ - SI MEP KRPRT
31
+ - SI MEP Kg1
32
+ - SI MEP M1
33
+ - SI MEP Mol1
34
+ - SI MEP S1
35
+ - SI Brochure
36
+ - SI Brochure, Appendix 4
37
+
38
+ ==== Reference structure for Metrologia documents
39
+
40
+ `BIPM Metrologia {JOURNAL} {VOLUME} {ISSUE}`
41
+
42
+ - `{JOURNAL}` - journal number, optional
43
+ - `{VOLUME}` - volume number, optional
44
+ - `{ISSUE}` - issue number, optional
45
+
46
+ ==== Reference structures for Outcomes documents
47
+
48
+ ===== Basic pattern
49
+
50
+ ----
51
+ Long:
52
+ {group name} -- {type} {number} ({year})
53
+ {group name} {type} {number} ({year})
54
+ {group name} {type} {year}-{zero_leading_number}
55
+
56
+ Short:
57
+ {group name} -- {type-abbrev} {number} ({year}, {lang})
58
+ {group name} {type-abbrev} {number} ({year}, {lang})
59
+ ----
60
+
61
+ - `group name` - a name of the group, required. A full list of group names is available https://github.com/metanorma/bipm-editor-guides/blob/main/sources/bipm-references-en.adoc#appendix-a-bipm-groups-and-codes[here].
62
+ - `type` - a type of document, required. A list of types is: Resolution (Résolution), Recommendation (Recommandation), Decision (Décision), Meeting (Réunion), Declaration (Déclaration).
63
+ - `type-abbrev` - an abbreviation of the type, required. A list of abbreviations: RES (Resolution), REC (Recommendation), DECN (Decision).
64
+ - `number` - a number of the document, optional. Can be with part, e.g. `1-2`.
65
+ - `zero_leading_number` - a number of the document with a leading zero, required. Can be used when a document has a 1 or 2 digits number. It's `00` for documents without a number.
66
+ - `year` - a year of the document, optional.
67
+ - `lang` - a language of the document, optional. Can be `EN` or `FR`.
68
+
69
+ ===== Special case pattern
70
+
71
+ The basic pattern works fine for all, except for these 2 cases:
72
+
73
+ - Decisions of the CIPM (since 2012)
74
+ - Recommendations/Resolutions/Decisions of the JCRB
75
+
76
+ Where the committee name is part of the outcome identifier. +
77
+ Special cases:
78
+
79
+ ----
80
+ Decision CIPM/111-10 (2022) / Décision CIPM/111-10 (2022)
81
+ Recommendation JCRB/43-1 (2021) / Recommandation JCRB/43-1 (2021)
82
+ ----
83
+
84
+ ===== Single language version (English)
85
+
86
+ `type` can be:
87
+
88
+ - Resolution (RES)
89
+ - Recommendation (REC)
90
+ - Decision (DECN)
91
+ - Statement (DECL)
92
+
93
+ e.g.
94
+
95
+ ----
96
+ CCTF -- Recommendation 2 (1970)
97
+ CCTF -- REC 2 (1970, EN)
98
+ ----
99
+
100
+ Special cases:
101
+
102
+ ----
103
+ Decision CIPM/111-10 (2022)
104
+ CIPM DECN CIPM/111-10 (2022, EN)
105
+ Recommendation JCRB/43-1 (2021)
106
+ JCRB REC JCRB/43-1 (2021, EN)
107
+ ----
108
+
109
+ ===== Single language version (French)
110
+
111
+ `type` can be:
112
+
113
+ - Résolution (RES)
114
+ - Recommandation (REC)
115
+ - Décision (DECN)
116
+ - Déclaration (DECL)
117
+
118
+ e.g.
119
+
120
+ ----
121
+ CCTF -- Recommandation 2 (1970)
122
+ CCTF -- REC 2 (1970, FR)
123
+ ----
124
+
125
+ Special cases:
126
+
127
+ ----
128
+ Décision CIPM/111-10 (2022)
129
+ CIPM DECN CIPM/111-10 (2022, FR)
130
+ Recommandation JCRB/43-1 (2021)
131
+ JCRB REC JCRB/43-1 (2021, FR)
132
+ ----
133
+
134
+ ===== Dual language version (language independent version)
135
+
136
+ `type` can be in their respective languages or the following abbreviations:
137
+
138
+ - RES
139
+ - REC
140
+ - DECN
141
+ - DECL
142
+
143
+ ----
144
+ CCTF -- Recommandation 2 (1970) / Recommendation 2 (1970)
145
+ CCTF REC 2 (1970)
146
+ ----
147
+
148
+ Special cases:
149
+
150
+ ----
151
+ Decision CIPM/110-10 (2022) / Décision CIPM/111-10 (2022)
152
+ CIPM DECN CIPM/110-10 (2022)
153
+ Recommendation JCRB/43-1 (2021) / Recommandation JCRB/43-1 (2021)
154
+ JCRB REC JCRB/43-1 (2021)
155
+ ----
156
+
157
+ ==== Examples
158
+
159
+ [source,ruby]
160
+ ----
161
+ require "relaton_bipm"
162
+ => true
163
+
164
+ # get BIPM brochure
165
+ item = RelatonBipm::BipmBibliography.get "BIPM SI Brochure"
166
+ [relaton-bipm] (BIPM SI Brochure) Fetching from Relaton repository ...
167
+ [relaton-bipm] (BIPM SI Brochure) Found: `BIPM SI Brochure`
168
+ => #<RelatonBipm::BipmBibliographicItem:0x007ffb83982fe8
169
+ ...
170
+
171
+ # get BIPM Metrologia page
172
+ bib = RelatonBipm::BipmBibliography.get "BIPM Metrologia 29 6 001"
173
+ [relaton-bipm] (BIPM Metrologia 29 6 001) Fetching from Relaton repository ...
174
+ [relaton-bipm] (BIPM Metrologia 29 6 001) Found: `Metrologia 29 6 001`
175
+ => #<RelatonBipm::BipmBibliographicItem:0x007f8857f94d40
176
+ ...
177
+
178
+ # get CGPM meetings
179
+ RelatonBipm::BipmBibliography.get "CGPM 1st Meeting (1889)"
180
+ [relaton-bipm] (CGPM 1st Meeting (1889)) Fetching from Relaton repository ...
181
+ [relaton-bipm] (CGPM 1st Meeting (1889)) Found: `CGPM 1th meeting (1889)`
182
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f7fd02aba28
183
+ ...
184
+
185
+ # get CGPM resolutions
186
+ RelatonBipm::BipmBibliography.get "CGPM RES (1889, E)"
187
+ [relaton-bipm] (CGPM RES (1889, E)) Fetching from Relaton repository ...
188
+ [relaton-bipm] (CGPM RES (1889, E)) Found: `CGPM RES (1889)`
189
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f80421f93d8
190
+ ...
191
+
192
+ RelatonBipm::BipmBibliography.get "CGPM Resolution (1889)"
193
+ [relaton-bipm] (CGPM Resolution (1889)) Fetching from Relaton repository ...
194
+ [relaton-bipm] (CGPM Resolution (1889)) Found: `CGPM RES (1889)`
195
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f8017f60c18
196
+ ...
197
+
198
+ RelatonBipm::BipmBibliography.get "CGPM Résolution (1889)"
199
+ [relaton-bipm] (CGPM Résolution (1889)) Fetching from Relaton repository ...
200
+ [relaton-bipm] (CGPM Résolution (1889)) Found: `CGPM RES (1889)`
201
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f8017f492e8
202
+ ...
203
+
204
+ # get CIPM decision by year and decision number
205
+ RelatonBipm::BipmBibliography.get "BIPM Decision CIPM/101-1 (2012)"
206
+ [relaton-bipm] (BIPM Decision CIPM/101-1 (2012)) Fetching from Relaton repository ...
207
+ [relaton-bipm] (BIPM Decision CIPM/101-1 (2012)) Found: `CIPM DECN 101-1 (2012)`
208
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f8017f2bd88
209
+ ...
210
+
211
+ RelatonBipm::BipmBibliography.get "BIPM DECN CIPM/101-1 (2012, E)"
212
+ [relaton-bipm] (BIPM DECN CIPM/101-1 (2012, E)) Fetching from Relaton repository ...
213
+ [relaton-bipm] (BIPM DECN CIPM/101-1 (2012, E)) Found: `CIPM DECN 101-1 (2012)`
214
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f8017f39438
215
+ ...
216
+
217
+ # get CIPM recommendation
218
+ RelatonBipm::BipmBibliography.get "CIPM Recommendation 1 (2005)"
219
+ [relaton-bipm] (CIPM Recommendation 1 (2005)) Fetching from Relaton repository ...
220
+ [relaton-bipm] (CIPM Recommendation 1 (2005)) Found: `CIPM REC 1 (2005)`
221
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f8017f31da0
222
+ ...
223
+
224
+ RelatonBipm::BipmBibliography.get "CIPM REC 1 (2005, FR)"
225
+ [relaton-bipm] (CIPM REC 1 (2005, FR)) Fetching from Relaton repository ...
226
+ [relaton-bipm] (CIPM REC 1 (2005, FR)) Found: `CIPM REC 1 (2005)`
227
+ => #<RelatonBipm::BipmBibliographicItem:0x00007f80422100d8
228
+ ...
229
+ ----
230
+
231
+ === XML serialization
232
+
233
+ [source,ruby]
234
+ ----
235
+ item.to_xml
236
+ => "<bibitem id="BIPMSIBrochurePart1" type="standard" schema-version="v1.2.1">
237
+ <fetched>2022-12-02</fetched>
238
+ <title type="main" format="text/plain" language="en">The International System of Units</title>
239
+ <title type="cover" format="text/plain" language="en">The International System of Units (SI)</title>
240
+ <title type="main" format="text/plain" language="fr">Le Système international d’unités</title>
241
+ <title type="cover" format="text/plain" language="fr">Le Système international d’unités (SI)</title>
242
+ <docidentifier type="BIPM" primary="true">BIPM SI Brochure</docidentifier>
243
+ ...
244
+ </bibitem>"
245
+ ----
246
+
247
+ With argument `bibdata: true` it outputs XML wrapped by `bibdata` element and adds flavor `ext` element.
248
+
249
+ [source,ruby]
250
+ ----
251
+ item.to_xml bibdata: true
252
+ => "<bibdata type="standard" schema-version="v1.2.1">
253
+ <fetched>2022-12-02</fetched>
254
+ <title type="main" format="text/plain" language="en">The International System of Units</title>
255
+ <title type="cover" format="text/plain" language="en">The International System of Units (SI)</title>
256
+ <title type="main" format="text/plain" language="fr">Le Système international d’unités</title>
257
+ <title type="cover" format="text/plain" language="fr">Le Système international d’unités (SI)</title>
258
+ <docidentifier type="BIPM" primary="true">BIPM SI Brochure</docidentifier>
259
+ ...
260
+ <ext schema-version="v1.0.0">
261
+ <doctype>brochure</doctype>
262
+ ...
263
+ </ext>
264
+ </bibdata>"
265
+ ----
266
+
267
+ === Typed links
268
+
269
+ Each BIPM document has `src` type link and an optional `doi` type link.
270
+
271
+ [source,ruby]
272
+ ----
273
+ bib.link
274
+ => [#<RelatonBib::TypedUri:0x00007fa6d6a51728 @content=#<Addressable::URI:0xc29c URI:https://iopscience.iop.org/article/10.1088/0026-1394/29/6/001>, @type="src">,
275
+ #<RelatonBib::TypedUri:0x00007fa6d6a29250 @content=#<Addressable::URI:0xc2b0 URI:https://doi.org/10.1088/0026-1394/29/6/001>, @type="doi">]
276
+ ----
277
+
278
+ === Create a bibliographic item from XML
279
+
280
+ [source,ruby]
281
+ ----
282
+ RelatonBipm::XMLParser.from_xml File.read('spec/fixtures/bipm_item.xml')
283
+ => #<RelatonBipm::BipmBibliographicItem:0x007ffb83827a90
284
+ ...
285
+ ----
286
+
287
+ === Create a bibliographic item from YAML
288
+ [source,ruby]
289
+ ----
290
+ hash = YAML.load_file 'spec/fixtures/bipm_item.yml'
291
+ => {"id"=>"Draft-Agenda-NMI-Dir-Meeting-2017-v10",
292
+ ...
293
+
294
+ RelatonBipm::BipmBibliographicItem.from_hash hash
295
+ => #<RelatonBipm::BipmBibliographicItem:0x007ffb668755a0
296
+ ...
297
+ ----
298
+
299
+ === Fetch data
300
+
301
+ This gem uses the following datasets as data sources:
302
+ - `bipm-data-outcomes` - looking for a local directory with the repository https://github.com/metanorma/bipm-data-outcomes
303
+ - `bipm-si-brochute` - looking for a local directory with the repository https://github.com/metanorma/bipm-si-brochure
304
+ - `rawdata-bipm-metrologia` - looking for a local directory with the repository https://github.com/relaton/rawdata-bipm-metrologia
305
+
306
+ The method `RelatonBipm::DataFetcher.fetch(source, output: "data", format: "yaml")` fetches all the documents from the dataset and saves them to the `./data` folder in YAML format.
307
+ Arguments:
308
+
309
+ - `source` - the name of the source dataset
310
+ - `output` - folder to save documents (default './data').
311
+ - `format` - the format in which the documents are saved. Possible formats are: `yaml`, `xml`, `bibxxml` (default `yaml`).
312
+
313
+ [source,ruby]
314
+ ----
315
+ RelatonBipm::DataFetcher.fetch "bipm-data-outcomes"
316
+ Started at: 2022-06-23 09:36:55 +0200
317
+ Stopped at: 2022-06-23 09:36:58 +0200
318
+ Done in: 2 sec.
319
+ => nil
320
+
321
+ RelatonBipm::DataFetcher.fetch "bipm-si-brochure"
322
+ Started at: 2022-06-23 09:37:12 +0200
323
+ Stopped at: 2022-06-23 09:37:12 +0200
324
+ Done in: 0 sec.
325
+ => nil
326
+
327
+ RelatonBipm::DataFetcher.fetch "rawdata-bipm-metrologia"
328
+ Started at: 2022-06-23 09:39:12 +0200
329
+ Stopped at: 2022-06-23 09:40:34 +0200
330
+ Done in: 82 sec.
331
+ => nil
332
+ ----
333
+
334
+ === Logging
335
+
336
+ RelatonBipm uses the relaton-logger gem for logging. By default, it logs to STDOUT. To change the log levels and add other loggers, read the https://github.com/relaton/relaton-logger#usage[relaton-logger] documentation.
337
+
338
+ == Development
339
+
340
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
341
+
342
+ To update the index test fixture (used by tests), run `rake spec:update_index`. This downloads the latest `index-v1.zip` from the https://github.com/relaton/relaton-data-bipm[relaton-data-bipm] repository.
343
+
344
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
345
+
346
+ == Contributing
347
+
348
+ Bug reports and pull requests are welcome on GitHub at https://github.com/relaton/relaton-bipm.
349
+
350
+ == License
351
+
352
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -63,13 +63,14 @@ module Relaton::Bipm
63
63
  # @param [Boolean, nil] warn_duplicate Warn if document already exists
64
64
  #
65
65
  def write_file(path, item, warn_duplicate: true)
66
- content = serialize item
67
66
  if @files.include?(path)
68
67
  Util.warn "File #{path} already exists" if warn_duplicate
69
68
  else
70
69
  @files << path
71
70
  end
72
- File.write path, content, encoding: "UTF-8"
71
+ # Byte-identical writes are skipped and the run records the file, so
72
+ # the core prune lifecycle can keep the tree between crawls.
73
+ force_write path, serialize(item)
73
74
  end
74
75
 
75
76
  def to_xml(item) = item.to_xml bibdata: true
@@ -0,0 +1,35 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ relaton-bsi retrieves British Standards Institution (BSI) bibliographic data using the Relaton model. Unlike index-backed flavors, it searches the BSI Shopify storefront: an **Algolia** product index finds candidate standards, then a **GraphQL** query against the Shopify storefront API fetches full metadata (titles, dates, ISBNs, committee info). Depends on relaton-iso for its ISO-based item/extension models.
8
+
9
+ ## Development
10
+
11
+ ```bash
12
+ bundle exec rake # default task → rspec
13
+ bundle exec rspec spec/relaton/bsi/bibliography_spec.rb # single file
14
+ ```
15
+
16
+ (No gem-local rubocop config; the monorepo root config applies.)
17
+
18
+ ## Architecture
19
+
20
+ Namespace: `Relaton::Bsi`. Retrieval flow:
21
+
22
+ 1. **Bibliography** (`lib/relaton/bsi/bibliography.rb`) — `get(code, year, opts)` / `search` entry points. Reference handling is **entirely `Pubid::Bsi`** (from the unified `pubid` gem) with **no hand-rolled identifier regex**: `parse` wraps `Pubid::Bsi::Identifier.parse` and **raises** on an unparseable query (only `Hit#pubid` rescues to nil — the Algolia catalogue carries codes such as `BS 381C SET:1996 (R2002)`, and one such row must not abort the search), `publication_year` reads `pubid.root.year` (not `base_document.year`: pubid holds an adopted standard such as `BS EN ISO 8848:2021` in `base`, so its `base_document.year` is nil; over pubid's 1,536 parseable BSI fixture ids `root.year` equals the old reader on 1,529 and fills in the base year on the other 7), and `same_reference?(query, hit, skip_rest:, drop_amd:)` decides whether a query and a candidate hit denote the same document. `same_reference?` uses only pubid's typed API — `#base_document` (peels supplements + Expert-commentary / Flex-version wrappers), `#matches?(other, ignore: %i[date month])` for the base-document comparison (`:month` is excluded alongside `:date` because Flex stores the month separately, so `exclude(:date)` alone leaves them unequal), and the `Amendment`/`Corrigendum` `#supplement_type`, `#number` and `#year` (amendment year optional when the query omits it). pubid removes the `#supplement_number`/`#supplement_year` aliases, but the locked pubid still has them and leaves a BSI supplement's `#number`/`#year` nil, so the private `supplement_number`/`supplement_year` helpers read the alias while it exists. Remove that fallback once pubid `main` has no alias. A canonical `rest_marker` (`:expert_commentary` / `:"flex_<edition>"`) makes an `ExComm` query match an `Expert Commentary` hit. `search` still lightly normalizes the **Algolia query text** (drops `BSI `, abbreviates the Expert-commentary suffix) — search-engine tuning, not identifier parsing. This depends on the `pubid` `feat/bsi-parse-gaps` work (see `HANDOFFS/metanorma__pubid.md`): the three parse/exclude gaps **plus** the Phase-2 API (`#base_document`, `exclude(:amendment|:supplement|:edition)`, uniform supplement accessors, `#matches?`).
23
+ 2. **HitCollection** (`lib/relaton/bsi/hit_collection.rb`, extends `Relaton::Core::HitCollection`) — queries the Algolia index (`shopify_products`) and filters hits by parsing each hit code and calling `Bibliography.same_reference?` against the parsed query, in three passes: exact → `skip_rest` (ignore the ExComm/Flex-version suffix) → `drop_amd` (compare base documents only, and rewrite the hit id to `hit.base_document.to_s`). Algolia keys are public/client-side.
24
+ 3. **Hit** (`lib/relaton/bsi/hit.rb`, extends `Relaton::Core::Hit`) — `item` lazy-loads the full document via the scraper; `pubid` memoizes the hit code parsed with `Pubid::Bsi` (like `Relaton::Iso::Hit#pubid`) so the three filter passes don't re-parse it, and is nil for a code pubid cannot parse. `Bibliography#results_filter` reads the year from this memoized pubid too, not from the (possibly `drop_amd`-rewritten) `hit[:code]`.
25
+ 4. **Scraper** (`lib/relaton/bsi/scraper.rb`) — GraphQL client; runs schema-based queries against the Shopify storefront GraphQL endpoint to build a full record (titles split on em-dash into intro/main/part, dates, contributors, ICS, source URI).
26
+ 5. **ItemData / Model::Item** (`item_data.rb`, `model/`) — `Relaton::Bsi::ItemData` extends `Relaton::Iso::ItemData`; `Ext` adds doctype, ICS, and a structured identifier. **Docidentifier** (`model/docidentifier.rb`) keeps the parsed `Pubid::Bsi::Identifier` as the **single stored value** of `content` (via the flavor-agnostic `Iso::Type::Pubid` lutaml type, which preserves the instance in and stringifies it out) — one source of truth: `#pubid` returns the instance, `#content` renders it to a string. `#remove_date!` → `pubid.exclude(:date, :month)`, `#remove_part!` → `pubid.exclude(:part, :subpart)`. `#to_all_parts!` wraps `pubid` in pubid's `AllParts` (`self.content = pubid.exclude(:supplement_year).to_all_parts`) — since BSI has no dedicated pubid `AllParts` subclass, the wrapper is the generic `Pubid::AllPartsIdentifier`, whose `#to_s` DOES print a "(all parts)" marker (unlike BSI's own renderer, which never had one). The `exclude(:supplement_year)` pre-step matters on a consolidated id (`BS 7273-4:2015+A1:2021`): pubid protects an `Amendment`/`Corrigendum`'s own date from a bare `exclude(:date)` — the same protection `#remove_date!` relies on to drop the base year while keeping the amendment's — but `to_all_parts`'s identity computation is built on that same `exclude`, so without the explicit `:supplement_year` key the amendment's year survives into the "(all parts)" form, distinguishing editions that marker is meant to collapse (`BS 7273+A1 (all parts)`, not `BS 7273+A1:2021 (all parts)`). Because `content` and `#pubid` are the same stored value here, both now show the "(all parts)" marker after `#to_all_parts!` — unlike flavors with a separately cached content string, which keep `content` marker-less on purpose. `#pubid`'s type check is widened to also accept `::Pubid::AllParts` (not just `Pubid::Bsi::Identifier`) for this reason. All three no-op when `#pubid` is nil. Non-BSI identifiers (e.g. ISBN) and anything pubid can't parse are stored verbatim as plain strings.
27
+ 6. **Processor** (`lib/relaton/bsi/processor.rb`) — registry integration; lazy-`require_relative`s `../bsi` in its methods.
28
+
29
+ ## External dependencies
30
+
31
+ `algolia ~> 2.3.0`, `graphql ~> 2.3`, `graphql-client ~> 0.23`, `faraday-net_http_persistent ~> 2.0`, `relaton-core`, `relaton-iso`.
32
+
33
+ ## Testing
34
+
35
+ RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`, record `:once`, 7-day re-record). Network is blocked via WebMock. No index fixture — BSI has no curated index; `spec/fixtures/` holds XML/YAML round-trip data.
@@ -0,0 +1,112 @@
1
+ = Relaton::Bsi retrieve BSI Standards for bibliographic use using the BibliographicItem model
2
+
3
+ Relaton::Bsi is a Ruby gem that implements the https://github.com/metanorma/metanorma-model-iso#iso-bibliographic-item[IsoBibliographicItem model].
4
+
5
+ == Usage
6
+
7
+ === Search for a standard using keywords
8
+
9
+ [source,ruby]
10
+ ----
11
+ require 'relaton/bsi'
12
+ => true
13
+
14
+ hit_collection = Relaton::Bsi::Bibliography.search("BS EN ISO 8848")
15
+ => <Relaton::Bsi::HitCollection:0x007fead49fe1f8 @ref=BS EN ISO 8848 @fetched=false>
16
+
17
+ item = hit_collection[1].item
18
+ => #<Relaton::Bsi::ItemData:0x000000012ac6c9a8
19
+ ...
20
+ ----
21
+
22
+ === XML serialization
23
+ [source,ruby]
24
+ ----
25
+ item.to_xml
26
+ => "<bibitem id="BSENISO88482021" type="standard" schema-version="v1.5.6">
27
+ <fetched>2025-10-18</fetched>
28
+ <title language="en" script="Latn" type="title-main">Small craft. Remote mechanical steering systems</title>
29
+ <title language="en" script="Latn" type="main">Small craft. Remote mechanical steering systems</title>
30
+ <uri type="src">https://shop.bsigroup.com/products/small-craft-remote-mechanical-steering-systems</uri>
31
+ <docidentifier type="BSI" primary="true">BS EN ISO 8848:2021</docidentifier>
32
+ ...
33
+ </bibitem>"
34
+ ----
35
+
36
+ === Typed links
37
+
38
+ Each BSI document has `src` type link.
39
+
40
+ [source,ruby]
41
+ ----
42
+ item.source[0].type
43
+ => "src"
44
+
45
+ item.source[0].content
46
+ => "https://shop.bsigroup.com/products/small-craft-remote-mechanical-steering-systems"
47
+ ----
48
+
49
+ With `bibdata: true` option XML output wrapped with `bibdata` element and `ext` element added.
50
+ [source,ruby]
51
+ ----
52
+ item.to_xml bibdata: true
53
+ => "<bibdata type="standard" schema-version="v1.5.6">
54
+ <fetched>2025-10-18</fetched>
55
+ <title language="en" script="Latn" type="title-main">Small craft. Remote mechanical steering systems</title>
56
+ ...
57
+ <ext schema-version="v1.1.3">
58
+ <doctype>standard</doctype>
59
+ ...
60
+ </ext>
61
+ </bibdata>"
62
+ ----
63
+
64
+ === Get standard by code and year
65
+ [source,ruby]
66
+ ----
67
+ Relaton::Bsi::Bibliography.get "BS EN ISO 8848:2021"
68
+ [relaton-bsi] INFO: (BS EN ISO 8848:2021) Fetching from shop.bsigroup.com ...
69
+ [relaton-bsi] INFO: (BS EN ISO 8848:2021) Found: `BS EN ISO 8848:2021`
70
+ => #<Relaton::Bsi::ItemData:0x000000011f19b688
71
+ ...
72
+
73
+ Relaton::Bsi::Bibliography.get "BS EN ISO 8848", "2021"
74
+ [relaton-bsi] INFO: (BS EN ISO 8848) Fetching from shop.bsigroup.com ...
75
+ [relaton-bsi] INFO: (BS EN ISO 8848) Found: `BS EN ISO 8848:2021`
76
+ => #<Relaton::Bsi::ItemData:0x000000011f1bdc10
77
+ ...
78
+ ----
79
+
80
+ === Create bibliographic item form YAML
81
+ [source,ruby]
82
+ ----
83
+ Relaton::Bsi::Item.from_yaml File.read("spec/fixtures/item.yaml", encoding: "UTF-8")
84
+ => #<Relaton::Bsi::ItemData:0x0000000104dd0dd8
85
+ ...
86
+ ----
87
+
88
+ === Create bibliographic item from XML
89
+ [source,ruby]
90
+ ----
91
+ Relaton::Bsi::Item.from_xml File.read("spec/fixtures/bibdata.xml", encoding: "UTF-8")
92
+ => #<Relaton::Bsi::ItemData:0x0000000104178c20
93
+ ...
94
+ ----
95
+
96
+ === Logging
97
+
98
+ Relaton::Bsi uses the relaton-logger gem for logging. By default, it logs to STDOUT. To change the log levels and add other loggers, read the https://github.com/relaton/relaton-logger#usage[relaton-logger] documentation.
99
+
100
+ == Development
101
+
102
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
103
+
104
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
105
+
106
+ == Contributing
107
+
108
+ Bug reports and pull requests are welcome on GitHub at https://github.com/relaton/relaton-bsi.
109
+
110
+ == License
111
+
112
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).