asciidoctor-bibliography 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +5 -0
- data/.gitignore +8 -2
- data/.hound.yml +3 -0
- data/.oss-guides.rubocop.yml +1076 -0
- data/.rubocop.yml +4 -10
- data/.travis.yml +2 -1
- data/Gemfile +1 -1
- data/README.adoc +224 -24
- data/Rakefile +2 -2
- data/asciidoctor-bibliography.gemspec +23 -23
- data/lib/asciidoctor-bibliography.rb +2 -2
- data/lib/asciidoctor-bibliography/asciidoctor.rb +4 -4
- data/lib/asciidoctor-bibliography/asciidoctor/bibliographer_preprocessor.rb +9 -56
- data/lib/asciidoctor-bibliography/bibliographer.rb +6 -7
- data/lib/asciidoctor-bibliography/citation.rb +56 -53
- data/lib/asciidoctor-bibliography/citation_item.rb +19 -10
- data/lib/asciidoctor-bibliography/database.rb +18 -6
- data/lib/asciidoctor-bibliography/databases/bibtex.rb +10 -10
- data/lib/asciidoctor-bibliography/errors.rb +16 -0
- data/lib/asciidoctor-bibliography/formatters/csl.rb +13 -2
- data/lib/asciidoctor-bibliography/formatters/tex.rb +42 -44
- data/lib/asciidoctor-bibliography/helpers.rb +9 -9
- data/lib/asciidoctor-bibliography/index.rb +17 -13
- data/lib/asciidoctor-bibliography/options.rb +97 -0
- data/lib/asciidoctor-bibliography/version.rb +1 -1
- data/samples/latex_macros_in_bibtex/sample.adoc +1 -1
- data/samples/standard/sample-default.adoc +3 -3
- data/samples/standard/sample-default.html +9 -8
- data/samples/standard/sample-din.adoc +1 -1
- data/samples/standard/sample-din.html +4 -3
- data/samples/standard/sample-ieee.adoc +1 -1
- data/samples/standard/sample-ieee.html +4 -3
- data/samples/tex/sample-authoryear.adoc +7 -17
- data/samples/tex/sample-authoryear.html +10 -32
- data/samples/tex/sample-numbers.adoc +7 -18
- data/samples/tex/sample-numbers.html +7 -29
- data/samples/tex/{sample-ordering.adoc → sample-sort.adoc} +6 -4
- data/spec/citation_item_spec.rb +67 -19
- data/spec/database_spec.rb +21 -16
- data/spec/helpers_spec.rb +46 -44
- data/spec/options_spec.rb +43 -0
- data/spec/spec_helper.rb +53 -55
- metadata +9 -7
- data/lib/asciidoctor-bibliography/exceptions.rb +0 -5
- data/samples/tex/sample-din.adoc +0 -74
- data/samples/tex/sample-din.html +0 -556
- data/samples/tex/sample-ordering.html +0 -467
data/.rubocop.yml
CHANGED
@@ -1,17 +1,11 @@
|
|
1
|
+
inherit_from: .oss-guides.rubocop.yml
|
2
|
+
|
1
3
|
AllCops:
|
2
4
|
TargetRubyVersion: 2.3
|
3
|
-
Excludes:
|
4
|
-
- deprecated/**/*.rb
|
5
|
-
- spec/**/*.rb
|
6
5
|
|
6
|
+
# TODO: shorten all lines to 80, as per oss-guides.
|
7
7
|
Metrics/LineLength:
|
8
8
|
Max: 120
|
9
9
|
|
10
|
-
|
11
|
-
Enabled: false
|
12
|
-
|
13
|
-
Style/FileName:
|
14
|
-
Enabled: false
|
15
|
-
|
16
|
-
Documentation:
|
10
|
+
Rails:
|
17
11
|
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.adoc
CHANGED
@@ -1,14 +1,35 @@
|
|
1
|
-
= Citations
|
1
|
+
= Citations and Bibliography the "asciidoctor-way"
|
2
|
+
|
3
|
+
asciidoctor-bibliography lets you handle citations and bibliography the
|
4
|
+
"http://asciidoctor.org/[asciidoctor]-way"!
|
2
5
|
|
3
6
|
image:https://img.shields.io/gem/v/asciidoctor-bibliography.svg["Gem Version", link="https://rubygems.org/gems/asciidoctor-bibliography"]
|
4
7
|
image:https://img.shields.io/travis/riboseinc/asciidoctor-bibliography/master.svg["Build Status", link="https://travis-ci.org/riboseinc/asciidoctor-bibliography"]
|
5
8
|
image:https://codeclimate.com/github/riboseinc/asciidoctor-bibliography/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/riboseinc/asciidoctor-bibliography"]
|
6
9
|
|
7
|
-
Citations in AsciiDoc using the fantastic http://asciidoctor.org/[asciidoctor].
|
8
10
|
|
9
11
|
== Introduction
|
10
12
|
|
11
|
-
This gem allows you to add
|
13
|
+
This gem allows you to add citations to AsciiDoc imported from BibTex files.
|
14
|
+
|
15
|
+
Citation styling leverages the popular http://citationstyles.org/[CSL] language
|
16
|
+
so you have direct access to thousands of crowdsourced styles including IEEE,
|
17
|
+
APA, Chicago, DIN and ISO 690.
|
18
|
+
|
19
|
+
The `bibliography:[]` command generates a full reference list that adheres to
|
20
|
+
your configured citation style.
|
21
|
+
|
22
|
+
On top of that you also have a formatter derived from the `Bib(La)TeX` world,
|
23
|
+
so all the macros you are familiar with are recognized.
|
24
|
+
|
25
|
+
Its syntax is designed to be "`native-asciidoctor`":
|
26
|
+
|
27
|
+
* single cite `cite:[key]`;
|
28
|
+
* contextual cite `cite[key, page=3]`;
|
29
|
+
* multiple cites `cite:[key1]+[key2]`;
|
30
|
+
* full cite `fullcite:[key]`; and
|
31
|
+
* TeX-compatible macros including `citep:[key]`, `citet:[]key` and friends.
|
32
|
+
|
12
33
|
|
13
34
|
== Installation
|
14
35
|
|
@@ -33,55 +54,234 @@ Or install it yourself as:
|
|
33
54
|
$ gem install asciidoctor-bibliography
|
34
55
|
----
|
35
56
|
|
36
|
-
== Configure
|
37
57
|
|
38
|
-
|
58
|
+
== Quick start
|
39
59
|
|
60
|
+
In your document header, choose the filename of a `BibTeX` database and a style (e.g. `apa`, `ieee`, `nature` and http://editor.citationstyles.org/searchByName/[others]).
|
61
|
+
|
62
|
+
[source,asciidoc]
|
40
63
|
----
|
41
|
-
=
|
42
|
-
:bibliography-database:
|
43
|
-
:bibliography-
|
44
|
-
:bibliography-reference-style: ieee
|
64
|
+
= My first document using asciidoctor-bibliography
|
65
|
+
:bibliography-database: my_database.bib
|
66
|
+
:bibliography-style: apa
|
45
67
|
----
|
46
68
|
|
47
|
-
|
69
|
+
In your document body, cite your resources using their keys:
|
48
70
|
|
49
|
-
|
71
|
+
[source,asciidoc]
|
72
|
+
----
|
73
|
+
This will end with a citation cite:[Aa2017].
|
74
|
+
----
|
75
|
+
|
76
|
+
Then list out the resources you cited:
|
77
|
+
|
78
|
+
[source,asciidoc]
|
79
|
+
----
|
80
|
+
bibliography::[]
|
81
|
+
----
|
82
|
+
|
83
|
+
When compiling, include `asciidoctor-bibliography` in your chain:
|
50
84
|
|
51
85
|
[source,console]
|
52
86
|
----
|
53
|
-
$ asciidoctor -r asciidoctor-bibliography
|
87
|
+
$ asciidoctor -r asciidoctor-bibliography my_first_document.adoc
|
54
88
|
----
|
55
89
|
|
56
|
-
|
90
|
+
That's it!
|
91
|
+
|
92
|
+
|
93
|
+
== Usage
|
94
|
+
|
95
|
+
`asciidoctor-bibliography` allows for more customizations and macros.
|
96
|
+
Let's examine all its features in full detail.
|
57
97
|
|
98
|
+
|
99
|
+
=== Citations
|
100
|
+
|
101
|
+
To cite a resource you provide its unique database key to an inline macro:
|
102
|
+
|
103
|
+
[source,asciidoc]
|
58
104
|
----
|
59
|
-
|
105
|
+
Here comes a citation cite:[Aa2017] and it's gone.
|
60
106
|
----
|
61
107
|
|
62
|
-
|
108
|
+
Referring to a specific location inside a resource can be done providing an extra named attribute:
|
63
109
|
|
110
|
+
[source,asciidoc]
|
64
111
|
----
|
65
|
-
|
112
|
+
cite:[Aa2017, page=42]
|
66
113
|
----
|
67
114
|
|
68
|
-
|
115
|
+
Allowed locators are `book`, `chapter`, `column`, `figure`, `folio`, `issue`, `line`, `note`, `opus`, `page`, `paragraph`, `part`, `section`, `sub-verbo`, `verse` and `volume`. Their support depends upon which ones your style implements.
|
116
|
+
|
117
|
+
An extra `locator` attribute with no custom rendering exists.
|
118
|
+
It appears where the ordinary locators would, but you can fully customize it:
|
69
119
|
|
120
|
+
[source,asciidoc]
|
121
|
+
----
|
122
|
+
cite:[Aa2017, locator=" halfway through"]
|
70
123
|
----
|
71
|
-
= Latex Macros In Bibtex Items
|
72
|
-
:bibliography-database: reference.bib
|
73
|
-
:bibliography-reference-style: ieee
|
74
124
|
|
75
|
-
|
125
|
+
Note that all locators except the first one will be ignored.
|
76
126
|
|
77
|
-
|
78
|
-
tools -- Searching Function" (see cite:guo2009[]).
|
127
|
+
To `prefix` and `suffix` citations with arbitrary strings you can use the relative attributes:
|
79
128
|
|
80
|
-
|
129
|
+
[source,asciidoc]
|
130
|
+
----
|
131
|
+
cite:[Aa2017, prefix="see ", suffix=" if you will"]
|
132
|
+
----
|
133
|
+
|
134
|
+
To cite multiple resources you concatenate them as follows:
|
135
|
+
|
136
|
+
[source,asciidoc]
|
137
|
+
----
|
138
|
+
cite:[Aa2017]+[Bb2017]+[Cc2017]
|
139
|
+
----
|
140
|
+
|
141
|
+
You can apply a different locator to each one.
|
81
142
|
|
143
|
+
|
144
|
+
=== Bibliographies
|
145
|
+
|
146
|
+
To render the bibliography you simply use the following block macro:
|
147
|
+
|
148
|
+
[source,asciidoc]
|
149
|
+
----
|
82
150
|
bibliography::[]
|
83
151
|
----
|
84
152
|
|
153
|
+
|
154
|
+
=== Databases
|
155
|
+
|
156
|
+
Specifying a database file is mandatory and it can be done in the header with its filename:
|
157
|
+
|
158
|
+
[source,asciidoc]
|
159
|
+
----
|
160
|
+
:bibliography-database: my_database.bib
|
161
|
+
----
|
162
|
+
|
163
|
+
Currently only the `BibTeX` format is supported; more will come soon.
|
164
|
+
|
165
|
+
|
166
|
+
=== Styling
|
167
|
+
|
168
|
+
The default style for citations and bibliographies is `apa`.
|
169
|
+
You can change that in the header:
|
170
|
+
|
171
|
+
[source,asciidoc]
|
172
|
+
----
|
173
|
+
:bibliography-style: apa
|
174
|
+
----
|
175
|
+
|
176
|
+
Valid style names can be found directly in the
|
177
|
+
https://github.com/citation-style-language/styles[official repository]
|
178
|
+
or searching through the friendly http://editor.citationstyles.org/[style editor].
|
179
|
+
|
180
|
+
You can also simply use the filename of a CSL file on your machine if you need more customization.
|
181
|
+
|
182
|
+
|
183
|
+
=== Hyperlinks
|
184
|
+
|
185
|
+
By default, citations include hyperlinks to their entry in the bibliography.
|
186
|
+
You can disable them in the header:
|
187
|
+
|
188
|
+
[source,asciidoc]
|
189
|
+
----
|
190
|
+
:bibliography-hyperlinks: false
|
191
|
+
----
|
192
|
+
|
193
|
+
|
194
|
+
=== Sorting
|
195
|
+
|
196
|
+
You can override the sorting specified by the CSL style you have chosen, if you desire to do so.
|
197
|
+
|
198
|
+
The relevant option is `bibliography-sort` and it accepts a YAML string specifying a list of keys to sort the entries with.
|
199
|
+
|
200
|
+
Let's explore some of the possibilities.
|
201
|
+
|
202
|
+
|
203
|
+
==== No Sort
|
204
|
+
|
205
|
+
The simplest option is *no sorting*; an empty list will cause the entries to be in appearance order.
|
206
|
+
|
207
|
+
[source,asciidoc]
|
208
|
+
----
|
209
|
+
:bibliography-sort: []
|
210
|
+
----
|
211
|
+
|
212
|
+
|
213
|
+
==== Sort By Single Key
|
214
|
+
|
215
|
+
To sort in a single key - say, the rendered author name - it's as simple as
|
216
|
+
|
217
|
+
[source,asciidoc]
|
218
|
+
----
|
219
|
+
:bibliography-sort: macro: author
|
220
|
+
----
|
221
|
+
|
222
|
+
|
223
|
+
==== Reverse Sort
|
224
|
+
|
225
|
+
However you might want to reverse the order:
|
226
|
+
|
227
|
+
[source,asciidoc]
|
228
|
+
----
|
229
|
+
:bibliography-sort: { macro: author, sort: descending }
|
230
|
+
----
|
231
|
+
|
232
|
+
|
233
|
+
==== Sort By Multiple Keys
|
234
|
+
|
235
|
+
It is possible to use any number of sorting keys putting them in an array.
|
236
|
+
E.g. to sort by issuing date:
|
237
|
+
|
238
|
+
[source,asciidoc]
|
239
|
+
----
|
240
|
+
:bibliography-sort: [{ macro: author, sort: descending }, { variable: issued }]
|
241
|
+
----
|
242
|
+
|
243
|
+
You might be asking: what is the difference between `variable` s and `macro` s?
|
244
|
+
|
245
|
+
The former are metadata fields fixed by the http://docs.citationstyles.org/en/stable/specification.html#appendix-iv-variables[CSL specification].
|
246
|
+
|
247
|
+
The latter are combinations of variables defined by your chosen style.
|
248
|
+
|
249
|
+
To use them effectively you'll need to know its implementation.
|
250
|
+
|
251
|
+
This task is not daunting at all, as the http://editor.citationstyles.org/[style editor] allows you to quickly list them and understand their role.
|
252
|
+
|
253
|
+
As for the `sort` option, the valid values are `ascending` (default) and `descending` as you'd exect.
|
254
|
+
|
255
|
+
|
256
|
+
=== TeX-mode
|
257
|
+
|
258
|
+
While the `cite` macro is reserved for CSL styling, all traditional Bib(La)TeX macros are accessible through the same syntax with their usual names:
|
259
|
+
|
260
|
+
* `citet`
|
261
|
+
* `citet*`
|
262
|
+
* `citealt`
|
263
|
+
* `citealt*`
|
264
|
+
* `citep`
|
265
|
+
* `citep*`
|
266
|
+
* `citealp`
|
267
|
+
* `citealp*`
|
268
|
+
* `citeauthor`
|
269
|
+
* `citeauthor*`
|
270
|
+
* `citeyear` and `citeyearpar`.
|
271
|
+
|
272
|
+
NOTE: no macros are missing since `\cite` is equivalent to `\citet`!
|
273
|
+
|
274
|
+
To cite multiple items you can concatenate them just like with `cite`.
|
275
|
+
|
276
|
+
You can set their style in the header:
|
277
|
+
|
278
|
+
[source,asciidoc]
|
279
|
+
----
|
280
|
+
:bibliography-tex-style: authoryear
|
281
|
+
----
|
282
|
+
|
283
|
+
Accepted values are `authoryear` (default) and `numeric`.
|
284
|
+
|
85
285
|
== Development
|
86
286
|
|
87
287
|
We follow Sandi Metz's Rules for this gem, you can read the
|
data/Rakefile
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require "asciidoctor-bibliography/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = "asciidoctor-bibliography"
|
9
9
|
spec.version = AsciidoctorBibliography::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
10
|
+
spec.authors = ["Ribose Inc."]
|
11
|
+
spec.email = ["open.source@ribose.com"]
|
12
12
|
|
13
13
|
spec.summary = 'Citations and bibliography the "asciidoctor-way"'
|
14
14
|
spec.description = <<~END
|
@@ -25,25 +25,25 @@ Gem::Specification.new do |spec|
|
|
25
25
|
|
26
26
|
The `bibliography:[]` command generates a full reference list that adheres to your configured citation style.
|
27
27
|
END
|
28
|
-
spec.homepage =
|
29
|
-
spec.license =
|
28
|
+
spec.homepage = "https://github.com/riboseinc/asciidoctor-bibliography"
|
29
|
+
spec.license = "MIT"
|
30
30
|
|
31
|
-
spec.require_paths = [
|
31
|
+
spec.require_paths = ["lib"]
|
32
32
|
spec.files = `git ls-files`.split("\n")
|
33
33
|
spec.test_files = `git ls-files -- {spec}/*`.split("\n")
|
34
|
-
spec.required_ruby_version = Gem::Requirement.new(
|
35
|
-
|
36
|
-
spec.add_dependency
|
37
|
-
spec.add_dependency
|
38
|
-
spec.add_dependency
|
39
|
-
spec.add_dependency
|
40
|
-
spec.add_dependency
|
41
|
-
|
42
|
-
spec.add_development_dependency
|
43
|
-
spec.add_development_dependency
|
44
|
-
spec.add_development_dependency
|
45
|
-
spec.add_development_dependency
|
46
|
-
spec.add_development_dependency
|
47
|
-
spec.add_development_dependency
|
48
|
-
spec.add_development_dependency
|
34
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
35
|
+
|
36
|
+
spec.add_dependency "asciidoctor"
|
37
|
+
spec.add_dependency "citeproc-ruby"
|
38
|
+
spec.add_dependency "csl-styles", "~> 1"
|
39
|
+
spec.add_dependency "latex-decode", "~> 0.2"
|
40
|
+
spec.add_dependency "bibtex-ruby"
|
41
|
+
|
42
|
+
spec.add_development_dependency "bundler"
|
43
|
+
spec.add_development_dependency "byebug"
|
44
|
+
spec.add_development_dependency "rspec"
|
45
|
+
spec.add_development_dependency "rake"
|
46
|
+
spec.add_development_dependency "simplecov"
|
47
|
+
spec.add_development_dependency "yard"
|
48
|
+
spec.add_development_dependency "rubocop"
|
49
49
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require "asciidoctor/extensions"
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative "asciidoctor/bibliographer_preprocessor"
|
4
|
+
require_relative "asciidoctor/document_ext"
|
5
|
+
require_relative "bibliographer"
|
6
6
|
|
7
7
|
Asciidoctor::Document.include AsciidoctorBibliography::Asciidoctor::DocumentExt
|
8
8
|
|
@@ -1,24 +1,20 @@
|
|
1
|
-
require
|
2
|
-
require 'pp'
|
1
|
+
require "asciidoctor"
|
3
2
|
|
4
|
-
require_relative
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
3
|
+
require_relative "../helpers"
|
4
|
+
require_relative "../database"
|
5
|
+
require_relative "../citation"
|
6
|
+
require_relative "../index"
|
7
|
+
require_relative "../options"
|
8
8
|
|
9
9
|
module AsciidoctorBibliography
|
10
10
|
module Asciidoctor
|
11
11
|
class BibliographerPreprocessor < ::Asciidoctor::Extensions::Preprocessor
|
12
12
|
def process(document, reader)
|
13
|
-
|
14
|
-
|
15
|
-
if document.bibliographer.options['database'].nil?
|
16
|
-
warn "No bibliographic database was provided: all bibliographic macros will be ignored. You can set it using the 'bibliography-database' option in the document's preamble."
|
17
|
-
return reader
|
18
|
-
end
|
13
|
+
document.bibliographer.options =
|
14
|
+
::AsciidoctorBibliography::Options.new_from_reader reader
|
19
15
|
|
20
16
|
# Load database(s).
|
21
|
-
document.bibliographer.database = Database.new(document.bibliographer.options
|
17
|
+
document.bibliographer.database = Database.new(document.bibliographer.options.database)
|
22
18
|
|
23
19
|
# Find, store and replace citations with uuids.
|
24
20
|
processed_lines = reader.read_lines.map do |line|
|
@@ -30,9 +26,6 @@ module AsciidoctorBibliography
|
|
30
26
|
end
|
31
27
|
reader = ::Asciidoctor::Reader.new processed_lines
|
32
28
|
|
33
|
-
# NOTE: retrieval and formatting are separated to allow sorting and numeric styles.
|
34
|
-
# document.bibliographer.sort
|
35
|
-
|
36
29
|
# Find and replace uuids with formatted citations.
|
37
30
|
processed_lines = reader.lines.join("\n") # for quicker matching
|
38
31
|
document.bibliographer.citations.each do |citation|
|
@@ -55,46 +48,6 @@ module AsciidoctorBibliography
|
|
55
48
|
processed_lines.flatten!
|
56
49
|
::Asciidoctor::Reader.new processed_lines
|
57
50
|
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
OPTIONS_PREFIX = 'bibliography-'.freeze
|
62
|
-
|
63
|
-
OPTIONS_DEFAULTS = {
|
64
|
-
'order' => 'alphabetical',
|
65
|
-
'reference-style' => 'apa',
|
66
|
-
'citation-style' => 'authoryear',
|
67
|
-
'hyperlinks' => 'true',
|
68
|
-
'database' => nil
|
69
|
-
}.freeze
|
70
|
-
|
71
|
-
def set_bibliographer_options(document, reader)
|
72
|
-
# We peek at the document attributes we need, without perturbing the parsing flow.
|
73
|
-
# NOTE: we're in a preprocessor and they haven't been parsed yet; doing it manually.
|
74
|
-
# pp reader
|
75
|
-
header_attributes = extract_header_attributes reader
|
76
|
-
user_options = filter_bibliography_attributes header_attributes
|
77
|
-
document.bibliographer.options = OPTIONS_DEFAULTS.merge user_options
|
78
|
-
end
|
79
|
-
|
80
|
-
def extract_header_attributes(reader)
|
81
|
-
tdoc = ::Asciidoctor::Document.new
|
82
|
-
treader = ::Asciidoctor::PreprocessorReader.new(
|
83
|
-
tdoc,
|
84
|
-
reader.source_lines
|
85
|
-
)
|
86
|
-
|
87
|
-
::Asciidoctor::Parser
|
88
|
-
.parse(treader, tdoc, header_only: true)
|
89
|
-
.attributes
|
90
|
-
end
|
91
|
-
|
92
|
-
def filter_bibliography_attributes(hash)
|
93
|
-
Helpers
|
94
|
-
.slice(hash, *OPTIONS_DEFAULTS.keys.map { |k| "#{OPTIONS_PREFIX}#{k}" })
|
95
|
-
.map { |k, v| [k[OPTIONS_PREFIX.length..-1], v] }.to_h
|
96
|
-
.reject { |_, value| value.nil? || value.empty? }.to_h
|
97
|
-
end
|
98
51
|
end
|
99
52
|
end
|
100
53
|
end
|