csl 1.0.0.pre1 → 1.0.0.pre2
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.
- data/.gitignore +1 -0
- data/.travis.yml +10 -1
- data/Rakefile +1 -1
- data/features/locales/ordinalize.feature +109 -0
- data/features/style/loading.feature +27 -27
- data/lib/csl.rb +9 -1
- data/lib/csl/compatibility.rb +4 -0
- data/lib/csl/errors.rb +5 -2
- data/lib/csl/info.rb +32 -5
- data/lib/csl/loader.rb +3 -3
- data/lib/csl/locale.rb +19 -2
- data/lib/csl/locale/date.rb +3 -3
- data/lib/csl/locale/term.rb +14 -4
- data/lib/csl/node.rb +41 -23
- data/lib/csl/parser.rb +15 -2
- data/lib/csl/pretty_printer.rb +11 -9
- data/lib/csl/schema.rb +95 -8
- data/lib/csl/style.rb +16 -5
- data/lib/csl/style/choose.rb +16 -0
- data/lib/csl/style/date.rb +4 -4
- data/lib/csl/style/label.rb +2 -2
- data/lib/csl/style/names.rb +3 -3
- data/lib/csl/style/number.rb +2 -1
- data/lib/csl/style/text.rb +2 -2
- data/lib/csl/version.rb +1 -1
- data/spec/csl/info_spec.rb +20 -1
- data/spec/csl/locale/term_spec.rb +45 -0
- data/spec/csl/node_spec.rb +3 -1
- data/spec/csl/schema_spec.rb +37 -4
- data/spec/csl/style/{conditional_spec.rb → choose_spec.rb} +1 -1
- data/spec/csl/style_spec.rb +4 -2
- data/spec/spec_helper.rb +2 -2
- data/vendor/schema/csl-categories.rng +47 -0
- data/vendor/schema/csl-terms.rng +144 -0
- data/vendor/schema/csl-types.rng +45 -0
- data/vendor/schema/csl-variables.rng +114 -0
- data/vendor/schema/csl.rng +1750 -0
- metadata +16 -14
- data/lib/csl/style/conditional.rb +0 -11
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
@@ -854,6 +854,115 @@ Feature: Converting numbers to ordinals using CSL locales
|
|
854
854
|
| 21:e |
|
855
855
|
# | 101:e |
|
856
856
|
# | 1001:e |
|
857
|
+
# | 301:e |
|
858
|
+
| 21:e |
|
859
|
+
| 21:e |
|
860
|
+
# | 1001:e |
|
861
|
+
|
862
|
+
@v1.0.1 @locale @ordinals @i18n @gender @lang:pl
|
863
|
+
Scenario: Gendered Swedish CSL 1.0.1 locales
|
864
|
+
Given the locale:
|
865
|
+
"""
|
866
|
+
<?xml version="1.0" encoding="utf-8"?>
|
867
|
+
<locale xmlns="http://purl.org/net/xbiblio/csl" version="1.0.1" xml:lang="sv">
|
868
|
+
<terms>
|
869
|
+
<term name="ordinal-00">:e</term>
|
870
|
+
|
871
|
+
<term name="ordinal-01">:a</term>
|
872
|
+
<term name="ordinal-01" gender-form="masculine">:e</term>
|
873
|
+
<term name="ordinal-01" gender-form="feminine">:a</term>
|
874
|
+
|
875
|
+
<term name="ordinal-02">:a</term>
|
876
|
+
<term name="ordinal-02" gender-form="masculine">:e</term>
|
877
|
+
<term name="ordinal-02" gender-form="feminine">:a</term>
|
878
|
+
|
879
|
+
<term name="ordinal-11">:e</term>
|
880
|
+
<term name="ordinal-11" gender-form="feminine">:e</term>
|
881
|
+
<term name="ordinal-12">:e</term>
|
882
|
+
<term name="ordinal-12" gender-form="feminine">:e</term>
|
883
|
+
|
884
|
+
<term name="ordinal-21">:e</term>
|
885
|
+
<term name="ordinal-21" gender-form="feminine">:e</term>
|
886
|
+
<term name="ordinal-22">:e</term>
|
887
|
+
<term name="ordinal-22" gender-form="feminine">:e</term>
|
888
|
+
|
889
|
+
<term name="ordinal-31">:e</term>
|
890
|
+
<term name="ordinal-32">:e</term>
|
891
|
+
|
892
|
+
<term name="ordinal-41">:e</term>
|
893
|
+
<term name="ordinal-42">:e</term>
|
894
|
+
|
895
|
+
<term name="ordinal-51">:e</term>
|
896
|
+
<term name="ordinal-52">:e</term>
|
897
|
+
|
898
|
+
<term name="ordinal-61">:e</term>
|
899
|
+
<term name="ordinal-62">:e</term>
|
900
|
+
|
901
|
+
<term name="ordinal-71">:e</term>
|
902
|
+
<term name="ordinal-72">:e</term>
|
903
|
+
|
904
|
+
<term name="ordinal-81">:e</term>
|
905
|
+
<term name="ordinal-82">:e</term>
|
906
|
+
|
907
|
+
<term name="ordinal-91">:e</term>
|
908
|
+
<term name="ordinal-92">:e</term>
|
909
|
+
</terms>
|
910
|
+
</locale>
|
911
|
+
"""
|
912
|
+
When I ordinalize these numbers:
|
913
|
+
| num | form | gender | number |
|
914
|
+
| 0 | | | |
|
915
|
+
| 1 | | | |
|
916
|
+
| 2 | | | |
|
917
|
+
| 3 | | | |
|
918
|
+
| 4 | | | |
|
919
|
+
| 5 | | | |
|
920
|
+
| 6 | | | |
|
921
|
+
| 7 | | | |
|
922
|
+
| 8 | | | |
|
923
|
+
| 9 | | | |
|
924
|
+
| 10 | | | |
|
925
|
+
| 1 | | feminine | |
|
926
|
+
| 1 | | masculine | |
|
927
|
+
| 2 | | feminine | |
|
928
|
+
| 2 | | masculine | |
|
929
|
+
| 23 | | | |
|
930
|
+
| 999 | | | |
|
931
|
+
| 11 | | | |
|
932
|
+
| 11 | | feminine | |
|
933
|
+
| 11 | | masculine | |
|
934
|
+
| 21 | | | |
|
935
|
+
# | 101 | | | |
|
936
|
+
# | 1001 | | feminine | |
|
937
|
+
# | 301 | | | |
|
938
|
+
| 21 | | masculine | singular |
|
939
|
+
| 21 | | masculine | plural |
|
940
|
+
# | 1001 | | masculine | |
|
941
|
+
Then the ordinals should be:
|
942
|
+
| ordinal |
|
943
|
+
| 0:e |
|
944
|
+
| 1:a |
|
945
|
+
| 2:a |
|
946
|
+
| 3:e |
|
947
|
+
| 4:e |
|
948
|
+
| 5:e |
|
949
|
+
| 6:e |
|
950
|
+
| 7:e |
|
951
|
+
| 8:e |
|
952
|
+
| 9:e |
|
953
|
+
| 10:e |
|
954
|
+
| 1:a |
|
955
|
+
| 1:e |
|
956
|
+
| 2:a |
|
957
|
+
| 2:e |
|
958
|
+
| 23:e |
|
959
|
+
| 999:e |
|
960
|
+
| 11:e |
|
961
|
+
| 11:e |
|
962
|
+
| 11:e |
|
963
|
+
| 21:e |
|
964
|
+
# | 101:e |
|
965
|
+
# | 1001:e |
|
857
966
|
# | 301:e |
|
858
967
|
| 21:e |
|
859
968
|
| 21:e |
|
@@ -8,33 +8,33 @@ Feature: Loading CSL Style
|
|
8
8
|
<?xml version="1.0" encoding="utf-8"?>
|
9
9
|
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never">
|
10
10
|
<info>
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
11
|
+
<title>American Psychological Association 6th Edition</title>
|
12
|
+
<id>http://www.zotero.org/styles/apa</id>
|
13
|
+
<link href="http://www.zotero.org/styles/apa" rel="self"/>
|
14
|
+
<link href="http://owl.english.purdue.edu/owl/resource/560/01/" rel="documentation"/>
|
15
|
+
<author>
|
16
|
+
<name>Simon Kornblith</name>
|
17
|
+
<email>simon@simonster.com</email>
|
18
|
+
</author>
|
19
|
+
<contributor>
|
20
|
+
<name>Bruce D'Arcus</name>
|
21
|
+
</contributor>
|
22
|
+
<contributor>
|
23
|
+
<name>Curtis M. Humphrey</name>
|
24
|
+
</contributor>
|
25
|
+
<contributor>
|
26
|
+
<name>Richard Karnesky</name>
|
27
|
+
<email>karnesky+zotero@gmail.com</email>
|
28
|
+
<uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
|
29
|
+
</contributor>
|
30
|
+
<contributor>
|
31
|
+
<name>Sebastian Karcher</name>
|
32
|
+
</contributor>
|
33
|
+
<category field="psychology"/>
|
34
|
+
<category field="generic-base"/>
|
35
|
+
<category citation-format="author-date"/>
|
36
|
+
<updated>2010-01-27T20:08:03+00:00</updated>
|
37
|
+
<rights>This work is licensed under a Creative Commons Attribution-Share Alike 3.0 License: http://creativecommons.org/licenses/by-sa/3.0/</rights>
|
38
38
|
</info>
|
39
39
|
<locale xml:lang="en">
|
40
40
|
<terms>
|
data/lib/csl.rb
CHANGED
@@ -29,7 +29,7 @@ require 'csl/locale/style_options'
|
|
29
29
|
require 'csl/style'
|
30
30
|
require 'csl/style/bibliography'
|
31
31
|
require 'csl/style/citation'
|
32
|
-
require 'csl/style/
|
32
|
+
require 'csl/style/choose'
|
33
33
|
require 'csl/style/date'
|
34
34
|
require 'csl/style/group'
|
35
35
|
require 'csl/style/label'
|
@@ -51,4 +51,12 @@ module CSL
|
|
51
51
|
Parser.instance.parse!(*arguments)
|
52
52
|
end
|
53
53
|
|
54
|
+
def validate(node)
|
55
|
+
Schema.validate(node)
|
56
|
+
end
|
57
|
+
|
58
|
+
def valid?(node)
|
59
|
+
Schema.valid?(node)
|
60
|
+
end
|
61
|
+
|
54
62
|
end
|
data/lib/csl/compatibility.rb
CHANGED
data/lib/csl/errors.rb
CHANGED
data/lib/csl/info.rb
CHANGED
@@ -2,9 +2,9 @@ module CSL
|
|
2
2
|
|
3
3
|
class Info < Node
|
4
4
|
|
5
|
-
attr_children :
|
6
|
-
:
|
7
|
-
:updated, :'link-dependent-style'
|
5
|
+
attr_children :title, :'title-short', :id, :issn, :eissn, :issnl,
|
6
|
+
:link, :author, :contributor, :category, :published, :summary,
|
7
|
+
:updated, :rights, :'link-dependent-style'
|
8
8
|
|
9
9
|
alias contributors contributor
|
10
10
|
|
@@ -21,7 +21,7 @@ module CSL
|
|
21
21
|
attr_children :name, :email, :uri
|
22
22
|
end
|
23
23
|
|
24
|
-
class Link <
|
24
|
+
class Link < Node
|
25
25
|
attr_struct :href, :rel
|
26
26
|
end
|
27
27
|
|
@@ -30,10 +30,37 @@ module CSL
|
|
30
30
|
end
|
31
31
|
|
32
32
|
|
33
|
-
class Category <
|
33
|
+
class Category < Node
|
34
34
|
attr_struct :field, :'citation-format'
|
35
35
|
end
|
36
|
+
|
37
|
+
class Id < TextNode
|
38
|
+
end
|
39
|
+
|
40
|
+
class Name < TextNode
|
41
|
+
end
|
42
|
+
|
43
|
+
class Email < TextNode
|
44
|
+
end
|
45
|
+
|
46
|
+
class Title < TextNode
|
47
|
+
end
|
48
|
+
|
49
|
+
class ShortTitle < TextNode
|
50
|
+
end
|
51
|
+
|
52
|
+
class Summary < TextNode
|
53
|
+
end
|
36
54
|
|
55
|
+
class Rights < TextNode
|
56
|
+
end
|
57
|
+
|
58
|
+
class Uri < TextNode
|
59
|
+
end
|
60
|
+
|
61
|
+
class Updated < TextNode
|
62
|
+
end
|
63
|
+
|
37
64
|
end
|
38
65
|
|
39
66
|
|
data/lib/csl/loader.rb
CHANGED
@@ -25,9 +25,9 @@ module CSL
|
|
25
25
|
when input.to_s =~ /^\s*</
|
26
26
|
data = input
|
27
27
|
else
|
28
|
-
|
28
|
+
|
29
29
|
case
|
30
|
-
when File.exists?(input)
|
30
|
+
when File.exists?(input.to_s)
|
31
31
|
location = input
|
32
32
|
when File.exists?(extend_name(input))
|
33
33
|
location = extend_name(input)
|
@@ -56,7 +56,7 @@ module CSL
|
|
56
56
|
# Extends the passed-in string to a style/locale name, by prefixing and
|
57
57
|
# appending the default name prefix and extension.
|
58
58
|
def extend_name(string)
|
59
|
-
if File.extname(string).empty?
|
59
|
+
if File.extname(string.to_s).empty?
|
60
60
|
name = [string, extension].compact.join
|
61
61
|
else
|
62
62
|
name = string.to_s.dup
|
data/lib/csl/locale.rb
CHANGED
@@ -37,7 +37,7 @@ module CSL
|
|
37
37
|
attr_reader :languages, :regions
|
38
38
|
|
39
39
|
def parse(data)
|
40
|
-
node = CSL.parse!(data)
|
40
|
+
node = CSL.parse!(data, self)
|
41
41
|
|
42
42
|
raise ParseError, "root node is not a locale: #{node.inspect}" unless
|
43
43
|
node.is_a?(self)
|
@@ -48,6 +48,7 @@ module CSL
|
|
48
48
|
end
|
49
49
|
|
50
50
|
attr_defaults :version => Schema.version, :xmlns => Schema.namespace
|
51
|
+
attr_struct :xmlns, :version
|
51
52
|
|
52
53
|
attr_children :'style-options', :info, :date, :terms
|
53
54
|
|
@@ -312,6 +313,14 @@ module CSL
|
|
312
313
|
[number, ordinal.to_s(options)].join
|
313
314
|
end
|
314
315
|
|
316
|
+
def validate
|
317
|
+
Schema.validate self
|
318
|
+
end
|
319
|
+
|
320
|
+
def valid?
|
321
|
+
validate.empty?
|
322
|
+
end
|
323
|
+
|
315
324
|
# Locales are sorted first by language, then by region; sort order is
|
316
325
|
# alphabetical with the following exceptions: the default locale is
|
317
326
|
# prioritised; in case of a language match the default region of that
|
@@ -357,9 +366,17 @@ module CSL
|
|
357
366
|
private
|
358
367
|
|
359
368
|
def attribute_assignments
|
360
|
-
|
369
|
+
if root?
|
370
|
+
super.push('xml:lang="%s"' % to_s)
|
371
|
+
else
|
372
|
+
'xml:lang="%s"' % to_s
|
373
|
+
end
|
361
374
|
end
|
362
375
|
|
376
|
+
def preamble
|
377
|
+
Schema.preamble.dup
|
378
|
+
end
|
379
|
+
|
363
380
|
# @return [Hash] a valid ordinalize query; the name attribute is a format string
|
364
381
|
def ordinalize_query_for(options)
|
365
382
|
q = { :name => 'ordinal-%02d' }
|
data/lib/csl/locale/date.rb
CHANGED
@@ -4,7 +4,7 @@ module CSL
|
|
4
4
|
# A localized Date comprises a set of formatting rules for dates.
|
5
5
|
class Date < Node
|
6
6
|
|
7
|
-
attr_struct :form, *Schema.attr(:font, :delimiter
|
7
|
+
attr_struct :form, :'text-case', *Schema.attr(:font, :delimiter)
|
8
8
|
attr_children :'date-part'
|
9
9
|
|
10
10
|
alias parts date_part
|
@@ -32,8 +32,8 @@ module CSL
|
|
32
32
|
class DatePart < Node
|
33
33
|
has_no_children
|
34
34
|
|
35
|
-
attr_struct :name, :form, :'range-delimiter',
|
36
|
-
*Schema.attr(:affixes, :
|
35
|
+
attr_struct :name, :form, :'range-delimiter', :'text-case',
|
36
|
+
*Schema.attr(:affixes, :font, :periods)
|
37
37
|
|
38
38
|
%w{ day month year }.each do |part|
|
39
39
|
define_method("#{part}?") do
|
data/lib/csl/locale/term.rb
CHANGED
@@ -147,6 +147,9 @@ module CSL
|
|
147
147
|
#
|
148
148
|
# @option options [:singular,:plural] :number (:singular) whether to
|
149
149
|
# return the term's singular or plural variant.
|
150
|
+
# @option options [Boolean] :plural (false) whether or not to return
|
151
|
+
# the term's plural variant (this option, if set, takes precedence
|
152
|
+
# over :number).
|
150
153
|
#
|
151
154
|
# @return [String] the term as a string
|
152
155
|
def to_s(options = nil)
|
@@ -169,12 +172,19 @@ module CSL
|
|
169
172
|
def pluralize?(options)
|
170
173
|
return false if options.nil?
|
171
174
|
|
172
|
-
|
175
|
+
case
|
176
|
+
when options.key?(:plural) || options.key?('plural')
|
177
|
+
options[:plural] || options['plural']
|
178
|
+
when options.key?(:number) || options.key?('number')
|
179
|
+
key = options[:number] || options['number']
|
173
180
|
|
174
|
-
|
175
|
-
|
181
|
+
if key.is_a?(Fixnum) || key.to_s =~ /^[+-]?\d+$/
|
182
|
+
key.to_i > 1
|
183
|
+
else
|
184
|
+
!key.blank? && key.to_s =~ /^plural/i
|
185
|
+
end
|
176
186
|
else
|
177
|
-
|
187
|
+
false
|
178
188
|
end
|
179
189
|
end
|
180
190
|
|
data/lib/csl/node.rb
CHANGED
@@ -29,22 +29,27 @@ module CSL
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def constantize(name)
|
32
|
-
types.detect
|
33
|
-
|
32
|
+
klass = types.detect { |t| t.matches?(name) }
|
33
|
+
|
34
|
+
if klass || !superclass.respond_to?(:constantize)
|
35
|
+
klass
|
36
|
+
else
|
37
|
+
superclass.constantize(name)
|
34
38
|
end
|
35
39
|
end
|
40
|
+
|
41
|
+
# @return [Boolean] whether or not the node's name matches the passed-in name
|
42
|
+
def matches?(nodename)
|
43
|
+
name.split(/::/)[-1].gsub(/([[:lower:]])([[:upper:]])/, '\1-\2').downcase == nodename
|
44
|
+
end
|
36
45
|
|
37
46
|
# Returns a new node with the passed in name and attributes.
|
38
47
|
def create(name, attributes = {}, &block)
|
39
48
|
klass = constantize(name)
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
node = new(attributes, &block)
|
45
|
-
node.nodename = name
|
46
|
-
node
|
47
|
-
end
|
50
|
+
node = (klass || Node).new(attributes, &block)
|
51
|
+
node.nodename = name
|
52
|
+
node
|
48
53
|
end
|
49
54
|
|
50
55
|
def create_attributes(attributes)
|
@@ -72,11 +77,11 @@ module CSL
|
|
72
77
|
|
73
78
|
# 1.8 Compatibility
|
74
79
|
@keys = attributes.map(&:to_sym).freeze
|
75
|
-
|
80
|
+
|
76
81
|
class << self
|
77
82
|
attr_reader :keys
|
78
83
|
end
|
79
|
-
|
84
|
+
|
80
85
|
def initialize(attrs = {})
|
81
86
|
super(*attrs.symbolize_keys.values_at(*keys))
|
82
87
|
end
|
@@ -84,7 +89,7 @@ module CSL
|
|
84
89
|
# @return [<Symbol>] a list of symbols representing the names/keys
|
85
90
|
# of the attribute variables.
|
86
91
|
def keys
|
87
|
-
|
92
|
+
__class__.keys
|
88
93
|
end
|
89
94
|
|
90
95
|
def values
|
@@ -102,7 +107,7 @@ module CSL
|
|
102
107
|
end
|
103
108
|
|
104
109
|
def fetch(key, default = nil)
|
105
|
-
value = keys.include?(key.to_sym) && send(key)
|
110
|
+
value = keys.include?(key.to_sym) && send(:'[]', key)
|
106
111
|
|
107
112
|
if block_given?
|
108
113
|
value || yield(key)
|
@@ -120,8 +125,8 @@ module CSL
|
|
120
125
|
other.respond_to?(:each_pair)
|
121
126
|
|
122
127
|
other.each_pair do |part, value|
|
123
|
-
|
124
|
-
send(
|
128
|
+
part = part.to_sym
|
129
|
+
send(:'[]=', part, value) if !value.nil? && keys.include?(part)
|
125
130
|
end
|
126
131
|
|
127
132
|
self
|
@@ -187,6 +192,14 @@ module CSL
|
|
187
192
|
end
|
188
193
|
alias has_text? textnode?
|
189
194
|
|
195
|
+
def save_to(path, options = {})
|
196
|
+
File.open(path, 'w:UTF-8') do |f|
|
197
|
+
f << (options[:compact] ? to_xml : pretty_print)
|
198
|
+
end
|
199
|
+
|
200
|
+
self
|
201
|
+
end
|
202
|
+
|
190
203
|
def <=>(other)
|
191
204
|
[nodename, attributes, children] <=> [other.nodename, other.attributes, other.children]
|
192
205
|
rescue
|
@@ -200,9 +213,9 @@ module CSL
|
|
200
213
|
tags = []
|
201
214
|
tags << "<#{[nodename, *attribute_assignments].join(' ')}>"
|
202
215
|
|
203
|
-
tags << children.map
|
216
|
+
tags << children.map { |node|
|
204
217
|
node.respond_to?(:tags) ? node.tags : [node.to_s]
|
205
|
-
|
218
|
+
}.flatten(1)
|
206
219
|
|
207
220
|
tags << "</#{nodename}>"
|
208
221
|
tags
|
@@ -235,8 +248,17 @@ module CSL
|
|
235
248
|
|
236
249
|
class << self
|
237
250
|
undef_method :attr_children
|
251
|
+
|
252
|
+
# @override
|
253
|
+
def create(name, attributes = {}, &block)
|
254
|
+
klass = constantize(name)
|
255
|
+
|
256
|
+
node = (klass || TextNode).new(attributes, &block)
|
257
|
+
node.nodename = name
|
258
|
+
node
|
259
|
+
end
|
238
260
|
end
|
239
|
-
|
261
|
+
|
240
262
|
attr_accessor :text
|
241
263
|
alias to_s text
|
242
264
|
|
@@ -269,11 +291,7 @@ module CSL
|
|
269
291
|
end
|
270
292
|
|
271
293
|
def tags
|
272
|
-
|
273
|
-
tags << "<#{attribute_assignments.unshift(nodename).join(' ')}>"
|
274
|
-
tags << text
|
275
|
-
tags << "</#{nodename}>"
|
276
|
-
tags
|
294
|
+
["<#{attribute_assignments.unshift(nodename).join(' ')}>#{text}</#{nodename}>"]
|
277
295
|
end
|
278
296
|
|
279
297
|
def inspect
|