csl 1.0.0.pre1 → 1.0.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|