citeproc 1.1.0 → 1.3.0
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/README.md +67 -66
- data/lib/citeproc/attributes.rb +2 -2
- data/lib/citeproc/bibliography.rb +1 -1
- data/lib/citeproc/citation_data.rb +89 -5
- data/lib/citeproc/compatibility.rb +5 -34
- data/lib/citeproc/date.rb +89 -49
- data/lib/citeproc/names.rb +42 -46
- data/lib/citeproc/number.rb +14 -9
- data/lib/citeproc/selector.rb +5 -4
- data/lib/citeproc/utilities.rb +11 -0
- data/lib/citeproc/variable.rb +24 -7
- data/lib/citeproc/version.rb +1 -1
- metadata +4 -13
- data/.document +0 -5
- data/.github/workflows/ci.yml +0 -33
- data/.yardopts +0 -2
- data/AGPL +0 -662
- data/Gemfile +0 -34
- data/Rakefile +0 -64
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8708658d44ed66deb17744c846697187edbcd1f6dc308c4bf3bc69933ede3e7e
|
|
4
|
+
data.tar.gz: 1d1af4037b6dae14f20adffdbb7e51b35ecd02728586f95932348416788347c1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4dc2d276583d4071cf17459265a3c706f8eb4091c59527a80506241e8f5187de4eba9f6cb140e560327fde38f8e8225348818dfeda0e1b2b98ef53acb67c5064
|
|
7
|
+
data.tar.gz: 33de631e29bd0e3484a0509e4f61bfb4e2b59fe87aeb8e7cbd25c1d9065ce20588637725f00d9f88ab2e19bcee765d3a19bc71d25adced9135d6a74627018279
|
data/README.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
CiteProc
|
|
2
2
|
========
|
|
3
|
-
CiteProc is a cite processor interface and citation data API
|
|
4
|
-
Citation Style Language (CSL) specifications.
|
|
5
|
-
a dedicated processor engine is required;
|
|
6
|
-
in the
|
|
3
|
+
CiteProc is a cite processor interface and citation data API
|
|
4
|
+
based on the Citation Style Language (CSL) specifications.
|
|
5
|
+
To actually process citations a dedicated processor engine is required;
|
|
6
|
+
a pure Ruby engine is available in the
|
|
7
|
+
[citeproc-ruby](https://rubygems.org/gems/citeproc-ruby) gem.
|
|
7
8
|
|
|
8
9
|
Quickstart
|
|
9
10
|
----------
|
|
@@ -12,117 +13,117 @@ Install CiteProc-Ruby and all official CSL styles (optional).
|
|
|
12
13
|
$ [sudo] gem install citeproc-ruby
|
|
13
14
|
$ [sudo] gem install csl-styles
|
|
14
15
|
|
|
15
|
-
Start rendering
|
|
16
|
+
Start rendering your references with any CSL style!
|
|
16
17
|
|
|
17
18
|
require 'citeproc'
|
|
18
19
|
require 'csl/styles'
|
|
20
|
+
require 'bibtex'
|
|
19
21
|
|
|
20
|
-
# Create a new processor
|
|
21
|
-
# format, and locale.
|
|
22
|
+
# Create a new processor
|
|
23
|
+
# with the desired style, format, and locale.
|
|
22
24
|
cp = CiteProc::Processor.new style: 'apa', format: 'text'
|
|
23
25
|
|
|
24
|
-
# To see what styles are available in your current
|
|
25
|
-
#
|
|
26
|
-
# locales as `CSL::Locale.ls'.
|
|
26
|
+
# To see what styles are available in your current environment,
|
|
27
|
+
# run `CSL::Style.ls';
|
|
28
|
+
# this also works for locales as `CSL::Locale.ls'.
|
|
27
29
|
|
|
28
|
-
# Tell the processor where to find your references.
|
|
29
|
-
# example we load them from a BibTeX bibliography
|
|
30
|
-
# bibtex-ruby gem.
|
|
30
|
+
# Tell the processor where to find your references.
|
|
31
|
+
# In this example we load them from a BibTeX bibliography
|
|
32
|
+
# using the bibtex-ruby gem (`gem install bibtex-ruby').
|
|
31
33
|
cp.import BibTeX.open('./references.bib').to_citeproc
|
|
32
34
|
|
|
33
|
-
# Now you are ready for rendering;
|
|
34
|
-
# provides
|
|
35
|
-
# `
|
|
35
|
+
# Now you are ready for rendering;
|
|
36
|
+
# the processor API provides two main rendering methods:
|
|
37
|
+
# `process' and `bibliography'.
|
|
36
38
|
|
|
37
|
-
# For simple one-off renditions,
|
|
38
|
-
# `render' in bibliography or citation mode:
|
|
39
|
+
# For simple one-off renditions,
|
|
40
|
+
# you can also call `render' in bibliography or citation mode:
|
|
39
41
|
cp.render :bibliography, id: 'knuth'
|
|
40
42
|
|
|
41
43
|
# This will return a rendered reference, like:
|
|
42
|
-
#-> Knuth, D. (1968). The art of computer programming.
|
|
43
|
-
|
|
44
|
-
# CiteProc-Ruby exposes a full CSL API to you;
|
|
45
|
-
# makes it possible to just alter CSL styles on the
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
# we can also make a quick adjustment at runtime:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
|
|
44
|
+
#-> Knuth, D. (1968). The art of computer programming (Vol. 1). Addison-Wesley.
|
|
45
|
+
|
|
46
|
+
# CiteProc-Ruby exposes a full CSL API to you;
|
|
47
|
+
# this makes it possible to just alter CSL styles on the fly.
|
|
48
|
+
# For example, what if we want names not to be initialized
|
|
49
|
+
# even though APA style is configured to do so?
|
|
50
|
+
# We could change the CSL style itself,
|
|
51
|
+
# but we can also make a quick adjustment at runtime:
|
|
52
|
+
cp.engine.style.macros['author-bib'].each_descendant do |node|
|
|
53
|
+
node[:initialize] = 'false' if node.nodename == 'name'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# What just happened?
|
|
57
|
+
# We selected the current style's 'author-bib' macro
|
|
58
|
+
# and changed all of its CSL name nodes;
|
|
59
|
+
# the cite processor output will pick-up the changes right away:
|
|
58
60
|
|
|
59
61
|
cp.render :bibliography, id: 'knuth'
|
|
60
|
-
#-> Knuth, Donald. (1968). The art of computer programming (Vol. 1).
|
|
62
|
+
#-> Knuth, Donald. (1968). The art of computer programming (Vol. 1). Addison-Wesley.
|
|
61
63
|
|
|
62
64
|
# Note that we have picked 'text' as the output format;
|
|
63
|
-
# if we want to make
|
|
64
|
-
# can switch to HTML instead:
|
|
65
|
+
# if we want to make use of richer output formats
|
|
66
|
+
# we can switch to HTML instead:
|
|
65
67
|
cp.engine.format = 'html'
|
|
66
68
|
|
|
67
69
|
cp.render :bibliography, id: 'knuth'
|
|
68
|
-
#-> Knuth, Donald. (1968). <i>The art of computer programming</i> (Vol. 1).
|
|
70
|
+
#-> Knuth, Donald. (1968). <i>The art of computer programming</i> (Vol. 1). Addison-Wesley.
|
|
69
71
|
|
|
70
72
|
# You can also render citations on the fly.
|
|
71
|
-
cp.render :citation, id: 'knuth', locator: '23'
|
|
73
|
+
cp.render :citation, id: 'knuth', locator: '23', label: 'page'
|
|
72
74
|
#-> (Knuth, 1968, p. 23)
|
|
73
75
|
|
|
74
76
|
Documentation
|
|
75
77
|
-------------
|
|
76
|
-
* [CiteProc Documentation](
|
|
77
|
-
* [CiteProc-Ruby API Documentation](
|
|
78
|
-
* [CSL-Ruby API Documentation](
|
|
78
|
+
* [CiteProc Documentation](https://rubydoc.info/gems/citeproc/)
|
|
79
|
+
* [CiteProc-Ruby API Documentation](https://rubydoc.info/gems/citeproc-ruby/)
|
|
80
|
+
* [CSL-Ruby API Documentation](https://rubydoc.info/gems/csl/)
|
|
79
81
|
|
|
80
82
|
Optional Dependencies
|
|
81
83
|
---------------------
|
|
82
84
|
CiteProc-Ruby tries to minimize hard dependencies for increased compatibility.
|
|
83
85
|
You can speed up the XML parsing by installing
|
|
84
|
-
[Nokogiri](https://rubygems.org/gems/nokogiri);
|
|
85
|
-
Ruby standard library will be used.
|
|
86
|
+
[Nokogiri](https://rubygems.org/gems/nokogiri);
|
|
87
|
+
otherwise the REXML from the Ruby standard library will be used.
|
|
86
88
|
|
|
87
|
-
Similarly, you can install
|
|
88
|
-
[EDTF](https://rubygems.org/gems/edtf)
|
|
89
|
-
|
|
90
|
-
additional inputs for date variables.
|
|
89
|
+
Similarly, you can install the
|
|
90
|
+
[EDTF](https://rubygems.org/gems/edtf)
|
|
91
|
+
gem to support a wide range of additional inputs for date variables.
|
|
91
92
|
|
|
92
93
|
CSL Styles and Locales
|
|
93
94
|
----------------------
|
|
94
|
-
You can load CSL styles and locales
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
You can load CSL styles and locales
|
|
96
|
+
by passing a respective XML string, file name, or URL.
|
|
97
|
+
You can also load styles and locales by name
|
|
98
|
+
if the corresponding files are installed
|
|
99
|
+
in your local styles and locale directories.
|
|
97
100
|
By default, CSL-Ruby looks for CSL styles and locale files in
|
|
98
101
|
|
|
99
102
|
/usr/local/share/csl/styles
|
|
100
103
|
/usr/local/share/csl/locales
|
|
101
104
|
|
|
102
|
-
You can change these locations
|
|
103
|
-
`CSL::Locale.root` respectively.
|
|
105
|
+
You can change these locations
|
|
106
|
+
by changing the value of `CSL::Style.root` and `CSL::Locale.root` respectively.
|
|
104
107
|
|
|
105
|
-
Alternatively, you can `gem install csl-styles`
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Compatibility
|
|
110
|
-
-------------
|
|
111
|
-
The cite processor and the CSL API libraries have been developed for MRI,
|
|
112
|
-
Rubinius, and JRuby. Please note that we try to support only Ruby versions
|
|
113
|
-
1.9.3 and upwards.
|
|
108
|
+
Alternatively, you can `gem install csl-styles`
|
|
109
|
+
to install all official CSL styles and locales.
|
|
110
|
+
To make the styles and locales available,
|
|
111
|
+
simply `require 'csl/styles'`.
|
|
114
112
|
|
|
115
113
|
Credits
|
|
116
114
|
-------
|
|
117
115
|
Thanks to Rintze M. Zelle, Sebastian Karcher, Frank G. Bennett, Jr.,
|
|
118
|
-
and Bruce D'Arcus of CSL and citeproc-js fame
|
|
116
|
+
and Bruce D'Arcus of CSL and citeproc-js fame
|
|
117
|
+
for their support!
|
|
119
118
|
|
|
120
|
-
Thanks to Google and the Berkman Center at Harvard University
|
|
121
|
-
this project as part of
|
|
119
|
+
Thanks to Google and the Berkman Center at Harvard University
|
|
120
|
+
for supporting this project as part of
|
|
121
|
+
[Google Summer of Code](https://developers.google.com/open-source/soc/).
|
|
122
122
|
|
|
123
123
|
Copyright
|
|
124
124
|
---------
|
|
125
|
-
Copyright 2009-
|
|
125
|
+
Copyright 2009-2026 Sylvester Keil.
|
|
126
|
+
All rights reserved.
|
|
126
127
|
|
|
127
128
|
Copyright 2012 President and Fellows of Harvard College.
|
|
128
129
|
|
data/lib/citeproc/attributes.rb
CHANGED
|
@@ -37,7 +37,7 @@ module CiteProc
|
|
|
37
37
|
return false if value.nil?
|
|
38
38
|
return false if value.respond_to?(:empty?) && value.empty?
|
|
39
39
|
|
|
40
|
-
value.to_s !~ /^(false|no|never)$/i
|
|
40
|
+
value.to_s !~ /^(false|no|never|0)$/i
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def filter_key(key)
|
|
@@ -108,7 +108,7 @@ module CiteProc
|
|
|
108
108
|
case
|
|
109
109
|
when equal?(other)
|
|
110
110
|
true
|
|
111
|
-
when self.class != other.class, length != other.length
|
|
111
|
+
when self.class != other.class, attributes.length != other.attributes.length
|
|
112
112
|
false
|
|
113
113
|
else
|
|
114
114
|
other.attributes.each_pair do |key, value|
|
|
@@ -11,12 +11,72 @@ module CiteProc
|
|
|
11
11
|
include Comparable
|
|
12
12
|
|
|
13
13
|
@labels = [
|
|
14
|
-
:
|
|
15
|
-
:
|
|
14
|
+
:act,
|
|
15
|
+
:appendix,
|
|
16
|
+
:'article-locator',
|
|
17
|
+
:book,
|
|
18
|
+
:canon,
|
|
19
|
+
:chapter,
|
|
20
|
+
:column,
|
|
21
|
+
:elocation,
|
|
22
|
+
:equation,
|
|
23
|
+
:figure,
|
|
24
|
+
:folio,
|
|
25
|
+
:issue,
|
|
26
|
+
:line,
|
|
27
|
+
:note,
|
|
28
|
+
:opus,
|
|
29
|
+
:page,
|
|
30
|
+
:paragraph,
|
|
31
|
+
:part,
|
|
32
|
+
:rule,
|
|
33
|
+
:scene,
|
|
34
|
+
:section,
|
|
35
|
+
:'sub-verbo',
|
|
36
|
+
:supplement,
|
|
37
|
+
:table,
|
|
38
|
+
:timestamp,
|
|
39
|
+
:'title-locator',
|
|
40
|
+
:verse,
|
|
41
|
+
:version,
|
|
42
|
+
:volume
|
|
16
43
|
].freeze
|
|
17
44
|
|
|
45
|
+
# Abbreviations of locator labels (for extraction)
|
|
46
|
+
@locator_abbreviations = {
|
|
47
|
+
'app.' => 'appendix',
|
|
48
|
+
'art.' => 'article-locator',
|
|
49
|
+
'bk.' => 'book',
|
|
50
|
+
'ch.' => 'chapter',
|
|
51
|
+
'col.' => 'column',
|
|
52
|
+
'fig.' => 'figure',
|
|
53
|
+
'fol.' => 'folio',
|
|
54
|
+
'l.' => 'line',
|
|
55
|
+
'n.' => 'note',
|
|
56
|
+
'no.' => 'issue',
|
|
57
|
+
'op.' => 'opus',
|
|
58
|
+
'p.' => 'page',
|
|
59
|
+
'pp.' => 'page',
|
|
60
|
+
'para.' => 'paragraph',
|
|
61
|
+
'pt.' => 'part',
|
|
62
|
+
'r.' => 'rule',
|
|
63
|
+
'sec.' => 'section',
|
|
64
|
+
'supp.' => 'supplement',
|
|
65
|
+
'sv.' => 'sub-verbo',
|
|
66
|
+
'tbl.' => 'table',
|
|
67
|
+
'tit.' => 'title-locator',
|
|
68
|
+
'vol.' => 'volume',
|
|
69
|
+
'vrs.' => 'verse'
|
|
70
|
+
}.freeze
|
|
71
|
+
|
|
18
72
|
class << self
|
|
19
|
-
attr_reader :labels
|
|
73
|
+
attr_reader :labels, :locator_abbreviations
|
|
74
|
+
|
|
75
|
+
# @param abbreviations [Hash<String,String>] label abbreviations
|
|
76
|
+
# @return [Regexp] a pattern matching any of the abbreviations
|
|
77
|
+
def locator_label_pattern(abbreviations = locator_abbreviations)
|
|
78
|
+
Regexp.union(abbreviations.keys.sort_by { |abbr| -abbr.length })
|
|
79
|
+
end
|
|
20
80
|
end
|
|
21
81
|
|
|
22
82
|
# @!attribute id
|
|
@@ -66,6 +126,32 @@ module CiteProc
|
|
|
66
126
|
yield self if block_given?
|
|
67
127
|
end
|
|
68
128
|
|
|
129
|
+
# @return [String, nil] the locator label;
|
|
130
|
+
# defaults to "page" if there is a locator
|
|
131
|
+
def label
|
|
132
|
+
read_attribute(:label) || ('page' if locator?)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Moves a label at the start of the locator into the label
|
|
136
|
+
# (e.g., "vol. 1" becomes "1" with the label "volume") unless
|
|
137
|
+
# the item has a label other than "page".
|
|
138
|
+
#
|
|
139
|
+
# @param abbreviations [Hash<String,String>] label abbreviations
|
|
140
|
+
# @return [self]
|
|
141
|
+
def parse_locator!(abbreviations = CitationItem.locator_abbreviations)
|
|
142
|
+
return self unless locator? && label.to_s == 'page'
|
|
143
|
+
|
|
144
|
+
pattern = CitationItem.locator_label_pattern(abbreviations)
|
|
145
|
+
match = /\A(#{pattern})\s+(.+)\z/m.match(locator.to_s)
|
|
146
|
+
|
|
147
|
+
unless match.nil?
|
|
148
|
+
self.label = abbreviations[match[1]]
|
|
149
|
+
self.locator = match[2]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
self
|
|
153
|
+
end
|
|
154
|
+
|
|
69
155
|
def initialize_copy(other)
|
|
70
156
|
@attributes = other.attributes.deep_copy
|
|
71
157
|
end
|
|
@@ -83,8 +169,6 @@ module CiteProc
|
|
|
83
169
|
end
|
|
84
170
|
|
|
85
171
|
|
|
86
|
-
|
|
87
|
-
|
|
88
172
|
class CitationData
|
|
89
173
|
|
|
90
174
|
extend Forwardable
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
if RUBY_PLATFORM =~ /java/i
|
|
8
8
|
require 'java'
|
|
9
9
|
|
|
10
|
-
puts java.lang.System.getProperty('file.encoding')
|
|
11
|
-
|
|
12
10
|
module CiteProc
|
|
13
11
|
def upcase(string)
|
|
14
12
|
java.lang.String.new(string).to_upper_case(java.util.Locale::ENGLISH).to_s
|
|
@@ -22,39 +20,12 @@ if RUBY_PLATFORM =~ /java/i
|
|
|
22
20
|
else
|
|
23
21
|
|
|
24
22
|
module CiteProc
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def downcase(string)
|
|
31
|
-
string.downcase
|
|
32
|
-
end
|
|
33
|
-
else
|
|
34
|
-
# Ruby 2.3 and older require extra Gems
|
|
35
|
-
begin
|
|
36
|
-
require 'unicode_utils'
|
|
37
|
-
def upcase(string)
|
|
38
|
-
UnicodeUtils.upcase(string)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def downcase(string)
|
|
42
|
-
UnicodeUtils.downcase(string)
|
|
43
|
-
end
|
|
44
|
-
rescue LoadError
|
|
45
|
-
begin
|
|
46
|
-
require 'unicode'
|
|
47
|
-
def upcase(string)
|
|
48
|
-
Unicode.upcase(string)
|
|
49
|
-
end
|
|
23
|
+
def upcase(string)
|
|
24
|
+
string.upcase
|
|
25
|
+
end
|
|
50
26
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
end
|
|
54
|
-
rescue LoadError
|
|
55
|
-
warn "CiteProc requires the `unicode_utils` or `unicode` Gem on Ruby 2.3"
|
|
56
|
-
end
|
|
57
|
-
end
|
|
27
|
+
def downcase(string)
|
|
28
|
+
string.downcase
|
|
58
29
|
end
|
|
59
30
|
end
|
|
60
31
|
end
|
data/lib/citeproc/date.rb
CHANGED
|
@@ -7,8 +7,8 @@ module CiteProc
|
|
|
7
7
|
#
|
|
8
8
|
# {Date Dates} can be constructed from a wide range of input values,
|
|
9
9
|
# including Ruby date objects, integers, date ranges, ISO 8601 and
|
|
10
|
-
# CiteProc JSON strings or hashes, and - provided you have the
|
|
11
|
-
#
|
|
10
|
+
# CiteProc JSON strings or hashes, and - provided you have the EDTF gem
|
|
11
|
+
# installed - EDTF strings.
|
|
12
12
|
#
|
|
13
13
|
# @example Initialization
|
|
14
14
|
# CiteProc::Date.new
|
|
@@ -17,9 +17,6 @@ module CiteProc
|
|
|
17
17
|
# CiteProc::Date.today
|
|
18
18
|
# #-> #<CiteProc::Date "[2012, 6, 10]">
|
|
19
19
|
#
|
|
20
|
-
# CiteProc::Date.new('Yesterday')
|
|
21
|
-
# #-> #<CiteProc::Date "[[2012, 6, 9]]">
|
|
22
|
-
#
|
|
23
20
|
# CiteProc::Date.new(1966)
|
|
24
21
|
# #-> #<CiteProc::Date "[1966]">
|
|
25
22
|
#
|
|
@@ -129,6 +126,18 @@ module CiteProc
|
|
|
129
126
|
!bc? && year < 1000
|
|
130
127
|
end
|
|
131
128
|
|
|
129
|
+
# Seasons may be encoded as months 21 to 24 (Spring to Winter).
|
|
130
|
+
# @return [Integer, nil] the season (1 to 4) or nil if the
|
|
131
|
+
# month does not encode a season
|
|
132
|
+
def season
|
|
133
|
+
month - 20 if month && month.between?(21, 24)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# @return [Boolean] whether or not the month encodes a season
|
|
137
|
+
def season?
|
|
138
|
+
!season.nil?
|
|
139
|
+
end
|
|
140
|
+
|
|
132
141
|
# Formats the date parts according to the passed-in format string.
|
|
133
142
|
# @param format [String] a format string
|
|
134
143
|
# @return [String,nil] the formatted date string; nil if the date
|
|
@@ -148,8 +157,10 @@ module CiteProc
|
|
|
148
157
|
# @return [Fixnum,nil] the result of the comparison (-1, 0, 1 or nil)
|
|
149
158
|
def <=>(other)
|
|
150
159
|
case
|
|
160
|
+
when other.is_a?(DateParts) && season? && other.season?
|
|
161
|
+
[year, season] <=> [other.year, other.season]
|
|
151
162
|
when other.is_a?(DateParts)
|
|
152
|
-
|
|
163
|
+
comparable <=> other.comparable
|
|
153
164
|
when other.respond_to?(:to_date)
|
|
154
165
|
to_date <=> other.to_date
|
|
155
166
|
else
|
|
@@ -192,6 +203,14 @@ module CiteProc
|
|
|
192
203
|
def inspect
|
|
193
204
|
"#<DateParts #{to_s}>"
|
|
194
205
|
end
|
|
206
|
+
|
|
207
|
+
protected
|
|
208
|
+
|
|
209
|
+
# Seasons are compared like dates without month.
|
|
210
|
+
# @return [Array<Fixnum>] the date parts used for comparison
|
|
211
|
+
def comparable
|
|
212
|
+
season? ? to_citeproc.take(1) : to_citeproc
|
|
213
|
+
end
|
|
195
214
|
end
|
|
196
215
|
|
|
197
216
|
#
|
|
@@ -210,13 +229,11 @@ module CiteProc
|
|
|
210
229
|
# List of date parsers (must respond to #parse)
|
|
211
230
|
@parsers = []
|
|
212
231
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
# warn "failed to load `#{date_parser}' gem"
|
|
219
|
-
end
|
|
232
|
+
begin
|
|
233
|
+
require 'edtf'
|
|
234
|
+
@parsers << ::EDTF
|
|
235
|
+
rescue LoadError
|
|
236
|
+
# warn "failed to load `edtf' gem"
|
|
220
237
|
end
|
|
221
238
|
|
|
222
239
|
@parsers << ::Date
|
|
@@ -229,9 +246,8 @@ module CiteProc
|
|
|
229
246
|
# A list of available date parsers. Each parser must respond to a
|
|
230
247
|
# #parse method that converts a date string into a Ruby date object.
|
|
231
248
|
# By default, the list will include Ruby's date parser from the
|
|
232
|
-
# standard library, as well as the
|
|
233
|
-
#
|
|
234
|
-
# make sure to `gem install chronic edtf`.
|
|
249
|
+
# standard library, as well as the parser of the EDTF gem if it is
|
|
250
|
+
# available; to install it on your system run `gem install edtf`.
|
|
235
251
|
#
|
|
236
252
|
# @return [Array] the available date parsers
|
|
237
253
|
attr_reader :parsers
|
|
@@ -276,12 +292,44 @@ module CiteProc
|
|
|
276
292
|
end
|
|
277
293
|
|
|
278
294
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
295
|
+
def_delegators :to_ruby, :strftime
|
|
296
|
+
|
|
297
|
+
attr_predicates :circa, :literal, :'date-parts'
|
|
298
|
+
|
|
299
|
+
# @return [Boolean] whether or not the date has a season field
|
|
300
|
+
def has_season?
|
|
301
|
+
attribute?(:season)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def season=(season)
|
|
305
|
+
write_attribute :season, season
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
# Season names recognized in the season field
|
|
309
|
+
SEASONS = {
|
|
310
|
+
'spring' => 1, 'summer' => 2, 'autumn' => 3, 'fall' => 3, 'winter' => 4
|
|
311
|
+
}.freeze
|
|
312
|
+
|
|
313
|
+
# A season takes the place of the month. If the (start) date has a
|
|
314
|
+
# month, the season is encoded by the month (21 to 24); otherwise
|
|
315
|
+
# the season field is used. Season numbers (1 to 4) and names in
|
|
316
|
+
# the season field are converted to integers.
|
|
317
|
+
#
|
|
318
|
+
# @return [Integer, String, nil] the season (1 to 4), the season
|
|
319
|
+
# field as a string if it is not a season number or name, or nil
|
|
320
|
+
def season
|
|
321
|
+
return parts[0].season if month
|
|
283
322
|
|
|
284
|
-
|
|
323
|
+
value = read_attribute(:season) or return
|
|
324
|
+
name = value.to_s.strip.downcase
|
|
325
|
+
|
|
326
|
+
SEASONS[name] || (name.match?(/\A[1-4]\z/) ? name.to_i : value.to_s)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# @return [Boolean] whether or not the date has a season (see #season)
|
|
330
|
+
def season?
|
|
331
|
+
!season.nil?
|
|
332
|
+
end
|
|
285
333
|
|
|
286
334
|
def initialize(value = {})
|
|
287
335
|
super
|
|
@@ -321,11 +369,15 @@ module CiteProc
|
|
|
321
369
|
when value.is_a?(Hash)
|
|
322
370
|
attributes = value.symbolize_keys
|
|
323
371
|
|
|
324
|
-
if attributes.has_key?(:raw)
|
|
325
|
-
|
|
372
|
+
if attributes.has_key?(:raw) && Array(attributes[:'date-parts']).empty?
|
|
373
|
+
raw = attributes.delete(:raw)
|
|
374
|
+
attributes.delete(:'date-parts')
|
|
375
|
+
date = Date.parse(raw)
|
|
376
|
+
|
|
377
|
+
@value = date.nil? ? { :literal => raw } : date.value
|
|
326
378
|
@value.merge!(attributes)
|
|
327
379
|
else
|
|
328
|
-
@value = attributes.deep_copy
|
|
380
|
+
@value = attributes.except(:raw).deep_copy
|
|
329
381
|
end
|
|
330
382
|
convert_parts!
|
|
331
383
|
|
|
@@ -397,34 +449,16 @@ module CiteProc
|
|
|
397
449
|
d
|
|
398
450
|
end
|
|
399
451
|
|
|
400
|
-
# @return [::Date,nil] the date
|
|
401
|
-
|
|
402
|
-
d = parts[0] and d.to_date
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
def start_date=(date)
|
|
406
|
-
parts[0] = DateParts.new(date.strftime('%Y-%m-%d').split(/-/))
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
def end_date=(date)
|
|
410
|
-
parts[1] = DateParts.new(date.nil? ? 0 : date.strftime('%Y-%m-%d').split(/-/))
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
# @return [Date,Range] the date as a Ruby date object or as a Range if
|
|
414
|
-
# this instance is closed range
|
|
452
|
+
# @return [::Date, Range, nil] the date as a Ruby date object or as
|
|
453
|
+
# a Range if this instance is closed range
|
|
415
454
|
def to_ruby
|
|
416
455
|
if closed_range?
|
|
417
|
-
|
|
456
|
+
parts[0].to_date..parts[1].to_date
|
|
418
457
|
else
|
|
419
|
-
|
|
458
|
+
d = parts[0] and d.to_date
|
|
420
459
|
end
|
|
421
460
|
end
|
|
422
461
|
|
|
423
|
-
# @return [::Date,nil] the range's end date; or nil
|
|
424
|
-
def end_date
|
|
425
|
-
d = parts[1] and d.to_date
|
|
426
|
-
end
|
|
427
|
-
|
|
428
462
|
# @return [Boolean] whether or not the date-parts contain an end date
|
|
429
463
|
def has_end_date?
|
|
430
464
|
parts[1] && !parts[1].empty?
|
|
@@ -506,7 +540,7 @@ module CiteProc
|
|
|
506
540
|
case
|
|
507
541
|
when literal?
|
|
508
542
|
literal
|
|
509
|
-
when
|
|
543
|
+
when has_season?
|
|
510
544
|
season
|
|
511
545
|
else
|
|
512
546
|
parts.map(&:to_citeproc).inspect
|
|
@@ -516,8 +550,14 @@ module CiteProc
|
|
|
516
550
|
def <=>(other)
|
|
517
551
|
case other
|
|
518
552
|
when CiteProc::Date
|
|
519
|
-
|
|
520
|
-
|
|
553
|
+
result = parts <=> other.parts
|
|
554
|
+
|
|
555
|
+
# Seasons are ordered among themselves only
|
|
556
|
+
if result == 0 && season? && other.season?
|
|
557
|
+
result = season.to_i <=> other.season.to_i
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
result
|
|
521
561
|
when ::Date
|
|
522
562
|
parts <=> [other]
|
|
523
563
|
else
|