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,189 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What is relaton-xsf?
6
+
7
+ A Ruby gem for bibliographic retrieval of XMPP XEP (XMPP Extension Protocol) specifications. Part of the Relaton family of gems. Fetches data from https://xmpp.org/extensions/refs/ and the relaton-data-xsf GitHub repository.
8
+
9
+ ## Commands
10
+
11
+ - `bundle exec rake spec:xsf` — run this flavor's suite (from the repo root)
12
+ - `bundle exec rake spec:update_index_xsf` — refresh
13
+ `spec/xsf/fixtures/index-v2.zip` from the published index
14
+ - `bundle exec rubocop` — lint
15
+ - `bundle exec rubocop -a` — lint with auto-fix
16
+ - `bin/console` — interactive console with gem loaded
17
+
18
+ ## Architecture
19
+
20
+ Namespace: `Relaton::Xsf` (under `lib/relaton/xsf/`). Branch `lutaml-integration` uses the new nested namespace (not the old `RelatonXsf`).
21
+
22
+ Key classes and their base classes from relaton-core:
23
+
24
+ | Class | Base | Role |
25
+ |---|---|---|
26
+ | `Processor` | `Relaton::Core::Processor` | Plugin entry point for relaton registry |
27
+ | `Bibliography` | Module (extends self) | Search & get interface; **parses the reference into a pubid** (`parse_ref`) |
28
+ | `HitCollection` | `Relaton::Core::HitCollection` | Collection of search results |
29
+ | `Hit` | `Relaton::Core::Hit` | Single result; lazy-loads YAML from GitHub |
30
+ | `DataFetcher` | `Relaton::Core::DataFetcher` | Crawls xmpp.org, parses BibXML, saves docs |
31
+ | `Docidentifier` | `Relaton::Bib::Docidentifier` | Exposes the id as a `Pubid::Xsf::Identifier` via `#pubid` |
32
+ | `Item` / `Bibitem` / `Bibdata` | `Relaton::Bib::Item` | Bibliographic item models (lutaml-model based) |
33
+
34
+ ## Index (`index-v2`, pubid-keyed)
35
+
36
+ `INDEXFILE` is the pubid-backed `index-v2`: rows are `Pubid::Xsf::Identifier`
37
+ hashes (`_type: pubid:xsf:xep` with `number`). The consumer
38
+ (`HitCollection#index`) and the producer (`DataFetcher#index`) pass
39
+ `pubid_class: ::Pubid::Xsf::Identifier`. Omitting it on the **producer**
40
+ writes v1-shaped rows under a v2 name, silently (`FileIO#save` calls `to_hash`
41
+ only for instances of `pubid_class`); omitting it on the **consumer** leaves
42
+ the rows raw hashes with `FileIO#sorted` false, so every lookup scans all 520.
43
+ `Processor#remove_index_file` passes `url: true` and `file:` only: the delete
44
+ never reads the index (see `lib/relaton/index/CLAUDE.md`).
45
+
46
+ An XEP identifier is a publisher and a number, nothing else — no edition, no
47
+ date, no part, and one row per XEP (520 rows, ids unique). That makes this the
48
+ simplest flavor in the sweep: there is no selection order to preserve, and the
49
+ reference states every component it has, so pubid's asymmetric subset match
50
+ (`ref === row[:id]`, `Pubid::SubsetMatch`) is exact equality after narrowing.
51
+
52
+ ### The index guard, and the two rows that are pages rather than XEPs
53
+
54
+ `DataFetcher#add_to_index` parses the docid and, on failure, records
55
+ `@errors[docid]` — which `report_errors` turns into a GitHub issue at the end of
56
+ the crawl (the 3GPP/ECMA precedent) — and skips the row. The data file is still
57
+ written, so a document that cannot be indexed is unindexed, never lost.
58
+
59
+ The guard is not decoration. One unparseable row does not fail that row:
60
+ `Relaton::Index` declares the **whole file** corrupt, deletes it, and hands back
61
+ an **empty** index — measured, 519 good rows plus one unparseable id loads as
62
+ **0 rows**, and the only trace is two INFO lines (`Wrong structure of file …`,
63
+ `Considering … corrupt, removing it`). Every XSF lookup then fails silently.
64
+
65
+ Two published rows are pages rather than XEPs — the XMPP repository's `README`
66
+ and its `xep-xxxx` template, which the crawl mints records for because they sit
67
+ in the same listing. pubid accepts them as the literal numbers `README` and
68
+ `xxxx`, so they carry into `index-v2` like any other row and resolve normally.
69
+ It stayed strict about everything else: `XEP banana` and a typo such as
70
+ `XEP 00O1` are still rejected, which is what keeps an unparseable reference a
71
+ warning rather than a silent miss.
72
+
73
+ Nothing in the published corpus trips the guard today, so a recorded error means
74
+ upstream grew a shape pubid does not know — exactly when an issue is worth
75
+ filing.
76
+
77
+ ### Where the reference becomes an identifier
78
+
79
+ `Bibliography.parse_ref` does it, not `HitCollection`. That split is not
80
+ cosmetic: `Type#search_candidates` narrows only when its search argument is
81
+ **not** a `String`, so the string has to become an identifier at the entry
82
+ point. `HitCollection` therefore receives a `Pubid::Xsf::Identifier` (or nil,
83
+ when the reference could not be parsed) and does nothing but the index lookup.
84
+ `Core::HitCollection` documents `ref` as `[String, Pubid]`, so this is the
85
+ interface working as intended.
86
+
87
+ ### Pubid-backed docidentifier
88
+
89
+ `Relaton::Xsf::Docidentifier` parses its `content` into a
90
+ `Pubid::Xsf::Identifier` kept in `@pubid`, while the lutaml `content` attribute
91
+ stays a plain string. Parsing is soft — a missing gem or non-XSF content leaves
92
+ `@pubid` nil rather than raising during deserialization. `Item` narrows the
93
+ inherited `docidentifier` attribute to it.
94
+
95
+ It is **purely additive**: `to_yaml` and `to_xml` are byte-identical before and
96
+ after, so no published document or index needs regenerating.
97
+
98
+ **It deliberately implements none of `remove_part!` / `remove_date!` /
99
+ `to_all_parts!`.** An XEP identifier is a publisher and a number and nothing
100
+ else, so there is genuinely nothing for any of them to strip, and
101
+ `Bib::Docidentifier` defaults all three to no-ops for exactly that case. Empty
102
+ overrides would assert a flavor rule that does not exist. Compare
103
+ `Relaton::Ogc::Docidentifier`, which overrides `remove_date!` because OGC really
104
+ does carry a revision.
105
+
106
+ ### Lookup
107
+
108
+ `HitCollection#search` follows the ETSI/W3C/OGC idiom:
109
+
110
+ - **Pass the pubid, not the string.** `Type#search_candidates` narrows only
111
+ when the argument is not a `String`, so the plain reference this flavor used
112
+ to pass disabled the binary search however the index was built.
113
+ `pubid_class:` alone fixes nothing; both had to change together.
114
+ - **Matching is exact.** The old `index.search(ref)` compared a **substring**
115
+ of the rendered id, so a bare `001` answered with **11** documents
116
+ (`XEP 0001` and every `XEP 001x`) and `Bibliography#get` took `.first` —
117
+ a truncated reference silently resolved to whichever sorted first. It now
118
+ returns nothing.
119
+ - **An unrecognized reference raises.** Like ISO, ETSI and 3GPP, the parse
120
+ error propagates: relaton-cli rescues `Pubid::Errors::Error` and renders
121
+ `"..." is not a recognized standards identifier`
122
+ (`gems/relaton-cli/lib/relaton/cli/command.rb:324`,
123
+ `subcommand_collection.rb:134`), and `Db#fetch` logs it through the
124
+ `StandardError` arm at `lib/relaton/db.rb:122`. `Pubid::Errors::ParseError`
125
+ includes the marker module `Pubid::Errors::Error`, which is what makes the
126
+ CLI's rescue work for every flavor.
127
+
128
+ Rescuing into a warning and an empty result — which several flavors still do
129
+ — collapses "this identifier is malformed" into "no such document", and a
130
+ caller cannot tell them apart. The parse also happens **before**
131
+ `HitCollection` is constructed, so it is never relabelled as the
132
+ `Relaton::RequestError` that collection's own rescue raises.
133
+ - **Three reference forms are normalized** in `Bibliography#normalize_ref`, because
134
+ `Pubid::Xsf` accepts only the canonical `XEP 0001`:
135
+
136
+ | form | before | after |
137
+ |---|---|---|
138
+ | `XEP 0001` | resolves | resolves |
139
+ | `0001` (bare) | resolves (substring) | resolves — the token is added |
140
+ | `XEP-0001` | **no match** | resolves — the spelling xmpp.org itself uses |
141
+ | `xep 0001` | no match | resolves — the token match is case-insensitive |
142
+
143
+ The hyphen and case forms are new support, not preserved behaviour: the
144
+ substring match compared against `XEP 0001`, which has a space.
145
+
146
+ ### Both indexes, one crawl
147
+
148
+ `relaton-data-xsf` publishes **both** from a single crawl: the `index-v2` this
149
+ fetcher writes, and its own `index-v1` built by `build_index_v1.rb` for released
150
+ relaton v2 consumers. Both carry the same 520 rows — building v1 from `data/`
151
+ was originally what kept `XEP README` and `XEP xxxx` available there while they
152
+ were unindexable in v2, and pubid accepting them has since removed that
153
+ asymmetry.
154
+
155
+ Verified against the published `index-v2`: 520 rows, all deserialize, sorted,
156
+ **0** keying on `""`, `XEP 0001` narrows to 1 of 520, and every accepted
157
+ spelling resolves to a file that returns HTTP 200.
158
+
159
+ Data flow: `Processor#get` → `Bibliography.get` → `HitCollection.search` → `Hit#item` → fetches YAML → `Relaton::Bib::Item.from_yaml`
160
+
161
+ DataFetcher flow: Crawls `https://xmpp.org/extensions/refs/`, parses each XML ref via `Relaton::Bib::Converter::BibXml.to_item`, sets `ext.flavor = "xsf"`, saves to disk.
162
+
163
+ Constants: `INDEXFILE = "index-v2"`, `GHDATA_URL` points to relaton-data-xsf `v2` branch.
164
+
165
+ ## Testing
166
+
167
+ - **Index fixture:** `spec/xsf/fixtures/index-v2.zip` is seeded into the
168
+ `Relaton::Index` pool by `spec/xsf/support/webmock.rb` — see **Index
169
+ (`index-v2`, pubid-keyed)** above for why it is re-seeded per example and
170
+ built with `pubid_class:`. Refresh it with `rake spec:update_index_xsf`.
171
+ - RSpec with VCR cassettes (`spec/vcr_cassettes/`) for HTTP interactions
172
+ - WebMock disables all external network connections
173
+ - Fixtures in `spec/fixtures/` (item.yaml, bibdata.xml, bibitem.xml)
174
+ - Round-trip tests verify YAML→Item→YAML and XML→Item→XML fidelity
175
+ - `DataFetcher` is lazily required — specs that test it must `require "relaton/xsf/data_fetcher"` explicitly
176
+ - Same for `Processor` — `require "relaton/xsf/processor"`
177
+
178
+ ## Key dependencies
179
+
180
+ - `relaton-core` — abstract base classes (Processor, HitCollection, Hit, DataFetcher)
181
+ - `relaton-bib` — bibliographic models, XML/YAML serialization (lutaml-model based)
182
+ - `relaton-index` — index management for quick document lookups
183
+ - `mechanize` — HTTP fetching and HTML parsing
184
+
185
+ ## Style
186
+
187
+ - RuboCop with relaton shared config (inherits from riboseinc/oss-guides)
188
+ - Target Ruby version: 3.1
189
+ - Logging via `Relaton::Xsf::Util` (extends `Relaton::Bib::Util`, PROGNAME = "relaton-xsf")
@@ -0,0 +1,127 @@
1
+ = Relaton::XSF: bibliographic retrieval of XMPP XEP specifications
2
+
3
+ == Purpose
4
+
5
+ `relaton-xsf` provides bibliographic information of XMPP XEP specifications using the
6
+ https://github.com/relaton/relaton-models#the-relaton-bibliographic-models[BibliographicItem model].
7
+
8
+ == Data sources
9
+
10
+ Relaton-XSF retrieves bibliographic information from https://xmpp.org/extensions/refs/[XMPP dataset].
11
+
12
+ The XSF Library dataset provides documents listed in the https://github.com/relaton/relaton-data-xsf/blob/v2/index-v2.yaml[index].
13
+
14
+ == Usage
15
+
16
+ === Search for a standard using keywords
17
+
18
+ [source,ruby]
19
+ ----
20
+ require 'relaton/xsf'
21
+ => true
22
+
23
+ hit_collection = Relaton::Xsf::Bibliography.search("XEP 0001")
24
+ => <Relaton::Xsf::HitCollection:0x000000000013c0 @ref=XEP 0001 @fetched=false>
25
+
26
+ item = hit_collection[0].item
27
+ => #<Relaton::Bib::ItemData:0x0000000124d510b8
28
+ ...
29
+ ----
30
+
31
+ === XML serialization
32
+ [source,ruby]
33
+ ----
34
+ item.to_xml
35
+ => "<bibitem id="XEP0001" type="standard" schema-version="v1.4.1">
36
+ <fetched>2026-03-04</fetched>
37
+ <title language="en" script="Latn">XMPP Extension Protocols</title>
38
+ <uri type="src">http://xmpp.org/extensions/xep-0001.html</uri>
39
+ <uri type="HTML">http://xmpp.org/extensions/xep-0001.html</uri>
40
+ <docidentifier type="XEP" primary="true">XEP 0001</docidentifier>
41
+ ...
42
+ <bibitem>"
43
+ ----
44
+ With argument `bibdata: true` it outputs XML wrapped by `bibdata` element and adds flavor `ext` element.
45
+ [source,ruby]
46
+ ----
47
+ item.to_xml bibdata: true
48
+ => "<bibdata type="standard" schema-version="v1.4.1">
49
+ <fetched>2026-03-04</fetched>
50
+ <title language="en" script="Latn">XMPP Extension Protocols</title>
51
+ <uri type="src">http://xmpp.org/extensions/xep-0001.html</uri>
52
+ <uri type="HTML">http://xmpp.org/extensions/xep-0001.html</uri>
53
+ <docidentifier type="XEP" primary="true">XEP 0001</docidentifier>
54
+ ...
55
+ <ext>
56
+ <doctype>rfc</doctype>
57
+ <flavor>xsf</flavor>
58
+ </ext>
59
+ </bibdata>"
60
+ ----
61
+
62
+ === Get document by reference
63
+ [source,ruby]
64
+ ----
65
+ item = Relaton::Xsf::Bibliography.get "XEP 0001"
66
+ [relaton-xsf] INFO: (XEP 0001) Fetching from Relaton repository ...
67
+ [relaton-xsf] INFO: (XEP 0001) Found: `XEP 0001`
68
+ => #<Relaton::Bib::ItemData:0x0000000125036f58
69
+ ...
70
+
71
+ item.docidentifier.first.content
72
+ => "XEP 0001"
73
+ ----
74
+
75
+ === Typed source links
76
+
77
+ XSF publications have `src` type source link.
78
+
79
+ [source,ruby]
80
+ ----
81
+ item.source[0].type
82
+ => "src"
83
+
84
+ item.source[0].content
85
+ => "http://xmpp.org/extensions/xep-0001.html"
86
+ ----
87
+
88
+ === Fetch data
89
+
90
+ This gem uses the https://xmpp.org/extensions/refs/ dataset as a data source.
91
+
92
+ The method `Relaton::Xsf::DataFetcher.fetch(output: "data", format: "yaml")` fetches all the documents from the dataset and saves them to the `./data` folder in YAML format.
93
+ Arguments:
94
+
95
+ - `output` - folder to save documents (default './data').
96
+ - `format` - the format in which the documents are saved. Possible formats are: `yaml`, `xml`, `bibxxml` (default `yaml`).
97
+
98
+ [source,ruby]
99
+ ----
100
+ require 'relaton/xsf/data_fetcher'
101
+
102
+ Relaton::Xsf::DataFetcher.fetch
103
+ Started at: 2021-09-01 18:01:01 +0200
104
+ Stopped at: 2021-09-01 18:01:43 +0200
105
+ Done in: 42 sec.
106
+ => nil
107
+ ----
108
+
109
+ === Logging
110
+
111
+ Relaton::Xsf 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.
112
+
113
+ == Development
114
+
115
+ 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.
116
+
117
+ To update the index test fixture (used by tests), run `rake spec:update_index_xsf`. This downloads the latest published index from the https://github.com/relaton/relaton-data-xsf[relaton-data-xsf] repository.
118
+
119
+ 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 https://rubygems.org[rubygems.org].
120
+
121
+ == Contributing
122
+
123
+ Bug reports and pull requests are welcome on GitHub at https://github.com/metanorma/relaton-xsf.
124
+
125
+ == License
126
+
127
+ The gem is available as open source under the terms of the https://opensource.org/license/bsd-2-clause/[2-Clause BSD License].
data/lib/relaton.rb CHANGED
@@ -20,6 +20,7 @@ require "yaml"
20
20
 
21
21
  module Relaton
22
22
  autoload :Logger, "relaton/logger"
23
+ autoload :Equivalence, "relaton/equivalence"
23
24
  autoload :Core, "relaton/core"
24
25
  autoload :Index, "relaton/index"
25
26
  autoload :Bib, "relaton/bib"