relaton 3.0.3 → 3.0.5
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 +4 -4
- data/lib/relaton/3gpp/data_fetcher.rb +3 -2
- data/lib/relaton/bib/CLAUDE.md +24 -4
- data/lib/relaton/bib/README.adoc +64 -0
- data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +12 -1
- data/lib/relaton/bib/converter/bibxml/to_rfcxml.rb +32 -8
- data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +10 -3
- data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup_v3.rb +43 -0
- data/lib/relaton/bib/converter/bibxml/to_rfcxml_v3.rb +416 -0
- data/lib/relaton/bib/converter/bibxml.rb +21 -9
- data/lib/relaton/bib/item_data.rb +19 -7
- data/lib/relaton/bib/model/abstract.rb +5 -0
- data/lib/relaton/bib/model/localized_string.rb +6 -1
- data/lib/relaton/bib/sanitizer.rb +20 -5
- data/lib/relaton/bipm/data_outcomes_parser.rb +2 -1
- data/lib/relaton/bipm/si_brochure_parser.rb +3 -2
- data/lib/relaton/core/data_fetcher.rb +3 -2
- data/lib/relaton/core/processor.rb +29 -0
- data/lib/relaton/db/CLAUDE.md +14 -2
- data/lib/relaton/db/cache.rb +5 -2
- data/lib/relaton/db.rb +7 -3
- data/lib/relaton/ecma/processor.rb +8 -0
- data/lib/relaton/equivalence.rb +2 -2
- data/lib/relaton/gb/scraper.rb +2 -2
- data/lib/relaton/ieee/data_fetcher.rb +2 -1
- data/lib/relaton/ietf/bibxml_parser.rb +6 -0
- data/lib/relaton/iho/CLAUDE.md +4 -2
- data/lib/relaton/iho/bibliography.rb +44 -13
- data/lib/relaton/iho/processor.rb +6 -0
- data/lib/relaton/index/file_io.rb +9 -8
- data/lib/relaton/index/shard_source.rb +3 -2
- data/lib/relaton/iso/hit_collection.rb +20 -3
- data/lib/relaton/jcgm/meetings_parser.rb +2 -2
- data/lib/relaton/nist/cswp.rb +2 -2
- data/lib/relaton/nist/data_fetcher.rb +3 -2
- data/lib/relaton/sdo/store.rb +3 -1
- data/lib/relaton/version.rb +1 -1
- data/lib/relaton/xsf/hit.rb +2 -1
- metadata +10 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e8ce7b77ba7b71f2bc7232319b926e70116ca3cdadf53395ef39e1dc4437a64
|
|
4
|
+
data.tar.gz: d0f29e54fa2129e444819703dfbd9b20ced132b34613053b6944b560370f9447
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 158c8d47b5a66ddd647f568aa35327ec4f1ee51e5d4ece559c77a610d3ac9474bcd90aa9bcedd544dd0cdaacf7dcac74f72560f810e014c2caa86477d7e33954
|
|
7
|
+
data.tar.gz: bf49242892015cae4f95d8b63120aa494bb936db2dd98eac34ac8f90ca1f94b889f7d99fd79cc933777f5a04796cb48dc3b933a110f79e29ce6d1f283bb5b744
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require "yeptris/psych"
|
|
1
2
|
require "fileutils"
|
|
2
3
|
require "net/http"
|
|
3
4
|
require "uri"
|
|
@@ -64,7 +65,7 @@ module Relaton
|
|
|
64
65
|
# @return [String, nil] file name
|
|
65
66
|
#
|
|
66
67
|
def get_file(renewal) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
67
|
-
@current =
|
|
68
|
+
@current = Yeptris::Psych.load_file CURRENT if File.exist? CURRENT
|
|
68
69
|
@current ||= {}
|
|
69
70
|
uri = URI(CSV_URL)
|
|
70
71
|
n = 0
|
|
@@ -183,7 +184,7 @@ module Relaton
|
|
|
183
184
|
# @return [Relaton3gpp::BibliographicItem, nil] merged bibliographic item or nil if no merge has been done
|
|
184
185
|
#
|
|
185
186
|
def merge_duplication(bib, file)
|
|
186
|
-
hash =
|
|
187
|
+
hash = Yeptris::Psych.load_file file
|
|
187
188
|
existed = Item.from_hash hash
|
|
188
189
|
changed = update_source? bib, existed
|
|
189
190
|
bib1, bib2, chng = transposed_relation bib, existed
|
data/lib/relaton/bib/CLAUDE.md
CHANGED
|
@@ -61,7 +61,15 @@ Each bibliographic attribute has its own class in `lib/relaton/bib/model/`:
|
|
|
61
61
|
**`Relaton::Bib::Sanitizer`** ([lib/relaton/bib/sanitizer.rb](lib/relaton/bib/sanitizer.rb))
|
|
62
62
|
strips markup outside the basicdoc set. `LocalizedMarkedUpString#content=` calls it on
|
|
63
63
|
assignment, so every `Title`, `Abstract`, `Note`, `Formattedref` and `Docidentifier` in
|
|
64
|
-
every flavor passes through it.
|
|
64
|
+
every flavor passes through it. The set it keeps depends on the field, through
|
|
65
|
+
`#sanitizer_allowed`: every field keeps `ALLOWED` (basicdoc inline markup), and `Abstract`
|
|
66
|
+
keeps `ALLOWED_WITH_BLOCKS`, which adds `BLOCK` — the basicdoc lists, notes, tables, figures
|
|
67
|
+
and admonitions, with the children their grammar requires (`name`, `thead`/`tbody`/`tfoot`,
|
|
68
|
+
`image`). That split follows `biblio.rng`: `<abstract>` takes `BasicBlockNoId`, and a title,
|
|
69
|
+
note, docidentifier or formattedref takes only `PureTextElement`, so do not widen the
|
|
70
|
+
default. Before relaton#421 an abstract's list or note unwrapped to bare `<p>`s with no
|
|
71
|
+
error. A consumer must therefore not assume that an abstract holds only `<p>` and inline
|
|
72
|
+
markup. Two properties are load-bearing:
|
|
65
73
|
|
|
66
74
|
- **It does not give up on an undeclared namespace prefix.** Third-party markup prefixes
|
|
67
75
|
its elements — Crossref returns JATS as `<jats:p><jats:italic>x</jats:italic></jats:p>`,
|
|
@@ -99,7 +107,17 @@ every flavor passes through it. Two properties are load-bearing:
|
|
|
99
107
|
### Rendering
|
|
100
108
|
|
|
101
109
|
- **`Renderer::BibtexBuilder`** - Converts `ItemData` to BibTeX format
|
|
102
|
-
- **`Converter::BibXml`** - Converts `ItemData` to
|
|
110
|
+
- **`Converter::BibXml`** - Converts `ItemData` to an `Rfcxml::V3` model object via
|
|
111
|
+
`Relaton::Bib::Converter::BibXml.from_item`; call `to_xml` on the result (this is what
|
|
112
|
+
`ItemData#to_rfcxml` does). Two output shapes share one class hierarchy:
|
|
113
|
+
- `ToRfcxml` / `ToRfcxmlReferencegroup` (default) emit **BibXML**, the shape the Relaton
|
|
114
|
+
data repositories publish. It keeps the RFC 7991-deprecated `<format>` element, so it
|
|
115
|
+
must stay byte-compatible — every relaton data fetcher's `"bibxml"` format is
|
|
116
|
+
`entry.to_rfcxml`. Do not change its output.
|
|
117
|
+
- `ToRfcxmlV3` / `ToRfcxmlReferencegroupV3` (`v3: true`) subclass those and emit strict
|
|
118
|
+
**RFC 7991**: no `<format>`, plus `<stream>`, `ascii*` attributes and `<refcontent>`.
|
|
119
|
+
New v3-only behaviour belongs in the subclass, so the default path stays untouched by
|
|
120
|
+
construction and `spec/bib/relaton/bib/converter/bibxml_spec.rb` keeps passing unedited.
|
|
103
121
|
- **lutaml-model native** - `to_xml`, `to_yaml`, `to_json` via the serialization classes
|
|
104
122
|
|
|
105
123
|
### Usage Pattern
|
|
@@ -120,11 +138,13 @@ item.to_xml # as <bibitem>
|
|
|
120
138
|
item.to_xml(bibdata: true) # as <bibdata>
|
|
121
139
|
item.to_yaml
|
|
122
140
|
item.to_bibtex
|
|
123
|
-
item.to_rfcxml
|
|
141
|
+
item.to_rfcxml # BibXML (what the data repos publish)
|
|
142
|
+
item.to_rfcxml(v3: true) # strict RFC 7991 / xml2rfc v3
|
|
143
|
+
item.to_rfcxml(anchor: "ISO712", include_keywords: false)
|
|
124
144
|
```
|
|
125
145
|
|
|
126
146
|
## Code Style
|
|
127
147
|
|
|
128
148
|
- Follows Ribose OSS Ruby style guide (inherited via `.rubocop.yml`)
|
|
129
|
-
- Target Ruby version: 3.
|
|
149
|
+
- Target Ruby version: 3.3+ (`required_ruby_version` in the gemspec, `TargetRubyVersion` in `.rubocop.yml`)
|
|
130
150
|
- Uses YARD documentation comments
|
data/lib/relaton/bib/README.adoc
CHANGED
|
@@ -311,6 +311,70 @@ item.to_rfcxml
|
|
|
311
311
|
</reference>
|
|
312
312
|
----
|
|
313
313
|
|
|
314
|
+
=== Export bibliographic item to strict RFC XML v3
|
|
315
|
+
|
|
316
|
+
`to_rfcxml` emits the BibXML shape published by the Relaton data repositories,
|
|
317
|
+
which still carries the `<format>` element that RFC 7991 deprecates. Pass
|
|
318
|
+
`v3: true` for output that follows the RFC 7991 (xml2rfc v3) vocabulary
|
|
319
|
+
instead: no `<format>`, a `<stream>` element, `ascii*` attributes, and
|
|
320
|
+
`<refcontent>` for identifiers that cannot be expressed as `<seriesInfo>`.
|
|
321
|
+
|
|
322
|
+
[source,ruby]
|
|
323
|
+
----
|
|
324
|
+
item.to_rfcxml v3: true
|
|
325
|
+
<reference anchor="ISO20483">
|
|
326
|
+
<front>
|
|
327
|
+
<title>Cereals and pulses</title>
|
|
328
|
+
<author initials="Ö." asciiInitials="O." surname="Nürk" asciiSurname="Nurk"/>
|
|
329
|
+
<author>
|
|
330
|
+
<organization abbrev="ISO" ascii="International Organization for Standardization">International Organization for Standardization</organization>
|
|
331
|
+
</author>
|
|
332
|
+
<date year="2013"/>
|
|
333
|
+
</front>
|
|
334
|
+
<refcontent>ISO 20483:2013-2014</refcontent>
|
|
335
|
+
</reference>
|
|
336
|
+
----
|
|
337
|
+
|
|
338
|
+
Documents published by the IETF (identified by a contributing organization
|
|
339
|
+
named `IETF`, `Internet Engineering Task Force` or `RFC Publisher`) express
|
|
340
|
+
their identifiers as `<seriesInfo>` rather than `<refcontent>`:
|
|
341
|
+
|
|
342
|
+
[source,ruby]
|
|
343
|
+
----
|
|
344
|
+
<reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
|
|
345
|
+
<stream>IETF</stream>
|
|
346
|
+
<front>
|
|
347
|
+
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
|
|
348
|
+
<seriesInfo name="BCP" value="14"/>
|
|
349
|
+
<seriesInfo name="RFC" value="2119"/>
|
|
350
|
+
...
|
|
351
|
+
</front>
|
|
352
|
+
</reference>
|
|
353
|
+
----
|
|
354
|
+
|
|
355
|
+
The v3 mode also applies the citation rules the IETF toolchain expects, which
|
|
356
|
+
the BibXML mode leaves alone:
|
|
357
|
+
|
|
358
|
+
* Contributors with role `author` or `editor` become `<author>`; the wider set
|
|
359
|
+
(`publisher`, `authorizer`, `translator`, …) is used only when the item names
|
|
360
|
+
no author or editor, so an RFC's publisher is not listed as its author.
|
|
361
|
+
* `<title>` takes the composite `title[@type="main"]`, else joins
|
|
362
|
+
title-intro / title-main / title-part, so multipart standards keep their full
|
|
363
|
+
title. Inline markup is flattened, since v3 `<title>` is text-only.
|
|
364
|
+
* Identifiers that restate the reference label, `URN` identifiers and the
|
|
365
|
+
`I-D.` anchor form are left out of `<refcontent>`; Internet-Draft
|
|
366
|
+
`<seriesInfo>` carries the full `draft-…` name, which is what xml2rfc
|
|
367
|
+
resolves against.
|
|
368
|
+
* Where folding a name leaves no letters (a non-Latin script), the `ascii*`
|
|
369
|
+
attribute is omitted rather than emitted blank.
|
|
370
|
+
|
|
371
|
+
Two further options are accepted by both modes:
|
|
372
|
+
|
|
373
|
+
`anchor:`:: overrides the anchor otherwise derived from `docnumber`, for
|
|
374
|
+
callers that carry their own identifier (for example a Metanorma Semantic XML
|
|
375
|
+
`bibitem/@id`).
|
|
376
|
+
`include_keywords:`:: set to `false` to suppress `<keyword>` elements.
|
|
377
|
+
|
|
314
378
|
=== Logging
|
|
315
379
|
|
|
316
380
|
RelatonBib 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.
|
|
@@ -326,7 +326,18 @@ module Relaton
|
|
|
326
326
|
|
|
327
327
|
t = Title.new(content: si.name, language: "en", script: "Latn")
|
|
328
328
|
Series.new(title: [t], number: si.value, type: "main")
|
|
329
|
-
end.compact
|
|
329
|
+
end.compact + stream_series
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
# RFC XML v3 carries the publication stream in a <stream> element.
|
|
333
|
+
# ItemData has no dedicated slot for it, so it is kept the way
|
|
334
|
+
# relaton-ietf does: as a series marked `type="stream"`.
|
|
335
|
+
def stream_series
|
|
336
|
+
return [] unless @reference.stream
|
|
337
|
+
|
|
338
|
+
t = Title.new(content: @reference.stream, language: "en",
|
|
339
|
+
script: "Latn")
|
|
340
|
+
[Series.new(title: [t], type: "stream")]
|
|
330
341
|
end
|
|
331
342
|
|
|
332
343
|
# --- Keyword ---
|
|
@@ -5,14 +5,15 @@ module Relaton
|
|
|
5
5
|
module Converter
|
|
6
6
|
module BibXml
|
|
7
7
|
class ToRfcxml
|
|
8
|
-
def initialize(item, include_keywords: true)
|
|
8
|
+
def initialize(item, include_keywords: true, anchor: nil)
|
|
9
9
|
@item = item
|
|
10
10
|
@include_keywords = include_keywords
|
|
11
|
+
@anchor = anchor
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
def transform
|
|
14
15
|
model = ::Rfcxml::V3::Reference.new
|
|
15
|
-
model.anchor = @item.docnumber || derive_anchor
|
|
16
|
+
model.anchor = @anchor || @item.docnumber || derive_anchor
|
|
16
17
|
model.target = create_target
|
|
17
18
|
model.front = create_front
|
|
18
19
|
model.format = create_format
|
|
@@ -26,14 +27,22 @@ module Relaton
|
|
|
26
27
|
di&.content&.to_s&.gsub(" ", ".")
|
|
27
28
|
end
|
|
28
29
|
|
|
30
|
+
# A <uri> may legitimately carry no type -- biblio.rng makes it
|
|
31
|
+
# optional, and hand-authored bibitems often omit it -- so never call
|
|
32
|
+
# String methods on it unguarded.
|
|
33
|
+
def target_types = %w[src doi]
|
|
34
|
+
|
|
29
35
|
def create_target
|
|
30
|
-
target =
|
|
31
|
-
@item.source.detect { |l| l.type.casecmp("doi").zero? }
|
|
36
|
+
target = target_types.filter_map { |t| source_of_type(t) }.first
|
|
32
37
|
return unless target
|
|
33
38
|
|
|
34
39
|
target.content.to_s
|
|
35
40
|
end
|
|
36
41
|
|
|
42
|
+
def source_of_type(type)
|
|
43
|
+
@item.source.detect { |l| l.type&.casecmp(type)&.zero? }
|
|
44
|
+
end
|
|
45
|
+
|
|
37
46
|
def create_front # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
38
47
|
front = ::Rfcxml::V3::Front.new
|
|
39
48
|
front.title = Rfcxml::V3::Title.new(content: @item.title[0].content) if @item.title.any?
|
|
@@ -59,9 +68,16 @@ module Relaton
|
|
|
59
68
|
end
|
|
60
69
|
end
|
|
61
70
|
|
|
71
|
+
# A `type="stream"` series is the publication stream, not a series:
|
|
72
|
+
# it has no number, so it would yield a valueless <seriesInfo>.
|
|
73
|
+
def seriesinfo_series?(ser)
|
|
74
|
+
ser.type != "stream" &&
|
|
75
|
+
ser.title.reject { |t| t.content == "DOI" }.any?
|
|
76
|
+
end
|
|
77
|
+
|
|
62
78
|
def series_to_seriesinfo # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
|
|
63
79
|
@item.series.select do |s|
|
|
64
|
-
s
|
|
80
|
+
seriesinfo_series?(s)
|
|
65
81
|
end.uniq do |s|
|
|
66
82
|
s.title.find { |t| t.content != "DOI" }.content
|
|
67
83
|
end.each_with_object([]) do |s, si|
|
|
@@ -71,8 +87,13 @@ module Relaton
|
|
|
71
87
|
end
|
|
72
88
|
end
|
|
73
89
|
|
|
90
|
+
# Which contributors become <author>; overridden by the v3 emitter.
|
|
91
|
+
def contributors_for_authors
|
|
92
|
+
@item.contributor.reject { |c| committee_contributor?(c) }
|
|
93
|
+
end
|
|
94
|
+
|
|
74
95
|
def create_authors # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
75
|
-
|
|
96
|
+
contributors_for_authors.map do |contrib|
|
|
76
97
|
role = "editor" if contrib.role.detect { |r| r.type == "editor" }
|
|
77
98
|
Rfcxml::V3::Author.new(
|
|
78
99
|
role: role,
|
|
@@ -284,7 +305,10 @@ module Relaton
|
|
|
284
305
|
return unless @item.abstract.any?
|
|
285
306
|
|
|
286
307
|
content = @item.abstract[0].content
|
|
287
|
-
paragraphs
|
|
308
|
+
# Semantic XML paragraphs carry attributes (`<p id="_349ea…">`);
|
|
309
|
+
# match those too, or the whole abstract falls through to the
|
|
310
|
+
# fallback below and the markup is escaped into the <t>.
|
|
311
|
+
paragraphs = content.scan(%r{<p\b[^>]*>(.*?)</p>}m).flatten
|
|
288
312
|
paragraphs = [content] if paragraphs.empty?
|
|
289
313
|
ts = paragraphs.map { |p| Rfcxml::V3::Text.new(content: CGI.unescapeHTML(p)) }
|
|
290
314
|
Rfcxml::V3::Abstract.new(t: ts)
|
|
@@ -294,7 +318,7 @@ module Relaton
|
|
|
294
318
|
|
|
295
319
|
def create_format # rubocop:disable Metrics/AbcSize
|
|
296
320
|
@item.source.each_with_object([]) do |l, a|
|
|
297
|
-
next unless FORMAT_TYPES.any? { |ft| l.type
|
|
321
|
+
next unless FORMAT_TYPES.any? { |ft| l.type&.casecmp(ft)&.zero? }
|
|
298
322
|
|
|
299
323
|
a << Rfcxml::V3::Format.new(
|
|
300
324
|
type: l.type, target: l.content,
|
|
@@ -3,9 +3,10 @@ module Relaton
|
|
|
3
3
|
module Converter
|
|
4
4
|
module BibXml
|
|
5
5
|
class ToRfcxmlReferencegroup
|
|
6
|
-
def initialize(item, include_keywords: true)
|
|
6
|
+
def initialize(item, include_keywords: true, anchor: nil)
|
|
7
7
|
@item = item
|
|
8
8
|
@include_keywords = include_keywords
|
|
9
|
+
@anchor = anchor
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def transform
|
|
@@ -30,6 +31,8 @@ module Relaton
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
def create_anchor
|
|
34
|
+
return @anchor if @anchor
|
|
35
|
+
|
|
33
36
|
docid = @item.docidentifier.detect(&:primary) ||
|
|
34
37
|
@item.docidentifier[0]
|
|
35
38
|
return unless docid
|
|
@@ -38,9 +41,13 @@ module Relaton
|
|
|
38
41
|
id.sub(/^(RFC|BCP|FYI|STD) /, '\1').sub(/^\w+\./, "")
|
|
39
42
|
end
|
|
40
43
|
|
|
44
|
+
# An untyped <uri> is legal, so guard before comparing.
|
|
45
|
+
def target_types = %w[src doi]
|
|
46
|
+
|
|
41
47
|
def create_target
|
|
42
|
-
target =
|
|
43
|
-
@item.source.detect { |l| l.type
|
|
48
|
+
target = target_types.filter_map do |type|
|
|
49
|
+
@item.source.detect { |l| l.type&.casecmp(type)&.zero? }
|
|
50
|
+
end.first
|
|
44
51
|
return unless target
|
|
45
52
|
|
|
46
53
|
target.content.to_s
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Bib
|
|
3
|
+
module Converter
|
|
4
|
+
module BibXml
|
|
5
|
+
#
|
|
6
|
+
# Strict RFC 7991 flavour of {ToRfcxmlReferencegroup}: members are
|
|
7
|
+
# rendered by {ToRfcxmlV3}, and every one of them gets an anchor,
|
|
8
|
+
# which the v3 grammar makes mandatory on `<reference>`.
|
|
9
|
+
#
|
|
10
|
+
class ToRfcxmlReferencegroupV3 < ToRfcxmlReferencegroup
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def target_types = %w[src HTML doi]
|
|
14
|
+
|
|
15
|
+
# <referencegroup> needs an anchor just as much as its members do,
|
|
16
|
+
# so fall back past the docidentifier the parent relies on.
|
|
17
|
+
def create_anchor
|
|
18
|
+
anchor = super || @item.docnumber || @item.id
|
|
19
|
+
anchor && anchor.to_s.strip.gsub(/\s+/, ".")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def build_references
|
|
23
|
+
included_items.each_with_index.map do |item, idx|
|
|
24
|
+
ref = ToRfcxmlV3.new(item, include_keywords: @include_keywords)
|
|
25
|
+
.transform
|
|
26
|
+
ref.anchor = member_anchor(idx) if ref.anchor.to_s.empty?
|
|
27
|
+
ref
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def included_items
|
|
32
|
+
@item.relation.select { |rel| rel.type == "includes" }
|
|
33
|
+
.map(&:bibitem)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def member_anchor(idx)
|
|
37
|
+
"#{create_anchor || 'reference'}_#{idx + 1}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|