csl 1.0.0.pre3 → 1.0.0.pre4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,91 +1,147 @@
1
1
  module CSL
2
-
2
+
3
3
  class Style < Node
4
4
  types << CSL::Info << CSL::Locale
5
-
5
+
6
6
  @default = :apa
7
7
 
8
8
  @root = File.expand_path('../../../vendor/styles', __FILE__).freeze
9
-
9
+
10
10
  @extension = '.csl'.freeze
11
11
  @prefix = ''
12
-
12
+
13
13
  class << self
14
14
  include Loader
15
-
15
+
16
16
  attr_accessor :default
17
17
 
18
18
  def parse(data)
19
19
  node = CSL.parse!(data, self)
20
-
20
+
21
21
  raise ParseError, "root node is not a style: #{node.inspect}" unless
22
22
  node.is_a?(self)
23
-
23
+
24
24
  node
25
- end
25
+ end
26
26
  end
27
-
27
+
28
28
  attr_defaults :version => Schema.version, :xmlns => Schema.namespace
29
-
29
+
30
30
  attr_struct :xmlns, :version, :class, :'default-locale',
31
31
  :'initialize-with-hyphen', :'page-range-format',
32
32
  :'demote-non-dropping-particle', *Schema.attr(:name, :names)
33
-
33
+
34
34
  attr_children :'style-options', :info, :locale, :macro,
35
35
  :citation, :bibliography
36
-
36
+
37
+ attr_reader :macros, :errors
38
+
37
39
  alias options style_options
38
40
  alias locales locale
39
-
41
+
42
+ alias has_macros? has_macro?
43
+
40
44
  def_delegators :info, :self_link, :self_link=, :has_self_link?,
41
45
  :template_link, :template_link=, :has_template_link?,
42
46
  :documentation_link, :documentation_link=, :has_documentation_link?,
43
- :title=, :id=
44
-
47
+ :independent_parent_link, :independent_parent_link=,
48
+ :has_independent_parent_link?, :title=, :id=, :has_title?, :has_id?,
49
+ :published_at, :updated_at
50
+
45
51
  def initialize(attributes = {})
46
- super(attributes, &nil)
47
- children[:locale], children[:macro] = [], []
48
-
52
+ super(attributes, &nil)
53
+ children[:locale], children[:macro], @macros, @errors = [], [], {}, []
54
+
49
55
  yield self if block_given?
50
56
  end
51
57
 
58
+ # @override
59
+ def added_child(node)
60
+ delegate = :"added_#{node.nodename}"
61
+ send delegate, node if respond_to?(delegate, true)
62
+ node
63
+ end
64
+
65
+ # @override
66
+ def deleted_child(node)
67
+ delegate = :"deleted_#{node.nodename}"
68
+ send delegate, node if respond_to?(delegate, true)
69
+ node
70
+ end
71
+
52
72
  def validate
53
- Schema.validate self
73
+ @errors = Schema.validate self
54
74
  end
55
-
75
+
56
76
  def valid?
57
77
  validate.empty?
58
78
  end
59
-
79
+
60
80
  def info
61
81
  children[:info] ||= Info.new
62
82
  end
63
-
83
+
64
84
  alias_child :metadata, :info
65
-
85
+
66
86
  # @return [String] the style's id
67
87
  def id
68
- return nil unless info.has_id?
88
+ return unless info.has_id?
69
89
  info.id.to_s
70
90
  end
71
-
91
+
72
92
  # @return [String] the style's title
73
93
  def title
74
- return nil unless info.has_title?
94
+ return unless info.has_title?
75
95
  info.title.to_s
76
96
  end
77
-
78
- # @return [Time] timestamp for the time set in info.updated
79
- def updated_at
80
- return nil unless info.has_updated?
81
- Time.parse(info.updated)
82
- end
97
+
98
+ alias has_template? has_template_link?
99
+
100
+ # @return [Style] the style's template
101
+ def template
102
+ return unless has_template?
103
+ load_related_style_from template_link
104
+ end
105
+
106
+ alias dependent? has_independent_parent_link?
107
+
108
+ def independent?
109
+ !dependent?
110
+ end
111
+
112
+ def independent_parent
113
+ return unless dependent?
114
+ load_related_style_from independent_parent_link
115
+ end
83
116
 
84
117
  private
85
-
118
+
86
119
  def preamble
87
120
  Schema.preamble.dup
88
- end
121
+ end
122
+
123
+ def load_related_style_from(uri)
124
+ # TODO try local first
125
+ Style.load(uri)
126
+ end
127
+
128
+ def added_macro(node)
129
+ unless node.attribute?(:name)
130
+ raise ValidationError,
131
+ "failed to register macro #{node.inspect}: name attribute missing"
132
+ end
133
+
134
+ if macros.key?(node[:name])
135
+ raise ValidationError,
136
+ "failed to register macro #{node.inspect}: duplicate name"
137
+ end
138
+
139
+ macros[node[:name]] = node
140
+ end
141
+
142
+ def deleted_macro(node)
143
+ macros.delete node[:name]
144
+ end
89
145
  end
90
-
146
+
91
147
  end
@@ -1,17 +1,17 @@
1
1
  module CSL
2
-
2
+
3
3
  module Treelike
4
-
4
+
5
5
  attr_accessor :parent
6
6
  attr_reader :children
7
7
  attr_writer :nodename
8
-
8
+
9
9
  protected :parent=
10
-
10
+
11
11
  def self.included(base)
12
12
  base.extend(ClassMethods)
13
13
  end
14
-
14
+
15
15
  # @return [String] the node's name.
16
16
  def nodename
17
17
  @nodename ||= self.class.name.split(/::/)[-1].gsub(/([[:lower:]])([[:upper:]])/, '\1-\2').downcase
@@ -25,12 +25,13 @@ module CSL
25
25
  enum_for :each_child
26
26
  end
27
27
  end
28
-
28
+
29
29
  def delete_children(*nodes)
30
30
  nodes.each do |node|
31
31
  delete_child node
32
32
  end
33
33
  end
34
+ alias delete delete_children
34
35
 
35
36
  # Deletes child nodes that are equal to the passed-in node. Returns all
36
37
  # deleted children. If no children were deleted, returns nil. If the
@@ -38,54 +39,52 @@ module CSL
38
39
  # deleted.
39
40
  def delete_child(child)
40
41
  deleted = children.delete child
41
-
42
+
42
43
  case
43
44
  when deleted.nil? && block_given?
44
45
  yield
45
46
  when deleted.nil?
46
47
  nil
47
48
  else
48
- [*deleted].each do |node|
49
- node.parent = nil
50
-
51
- deleted_child node
52
- node.deleted_from self
53
- end
54
-
49
+ deleted.parent = nil
50
+
51
+ deleted_child deleted
52
+ deleted.deleted_from self
53
+
55
54
  deleted
56
55
  end
57
56
  rescue => e
58
57
  # TODO rollback
59
58
  raise e
60
59
  end
61
-
60
+
62
61
  def add_children(*nodes)
63
62
  nodes.each do |node|
64
63
  add_child node
65
64
  end
66
65
  self
67
66
  end
68
-
67
+
69
68
  def add_child(node)
70
69
  node.unlink
71
-
70
+
72
71
  node.parent = self
73
72
  children << node
74
-
73
+
75
74
  added_child node
76
75
  node.added_to self
77
-
76
+
78
77
  node
79
78
  rescue => e
80
79
  # TODO rollback
81
80
  raise e
82
81
  end
83
-
82
+
84
83
  def <<(node)
85
84
  add_child node
86
85
  self
87
86
  end
88
-
87
+
89
88
  # Returns the first immediate child node whose nodename matches the
90
89
  # passed-in name/pattern and attribute conditions.
91
90
  #
@@ -99,7 +98,7 @@ module CSL
99
98
  end
100
99
  end
101
100
  alias > find_child
102
-
101
+
103
102
  # Returns all immediate child nodes whose nodename matches the passed-in
104
103
  # name/pattern and attribute conditions; returns an empty array if there
105
104
  # is no match.
@@ -124,20 +123,20 @@ module CSL
124
123
  def empty?
125
124
  children.empty?
126
125
  end
127
-
126
+
128
127
  # Unlinks the node and all its children from its parent node. Returns
129
128
  # the old parent node or nil.
130
129
  def unlink
131
130
  return nil if root?
132
-
131
+
133
132
  other = parent
134
133
  other.delete_child self
135
-
134
+
136
135
  self.parent = nil
137
136
 
138
137
  other
139
138
  end
140
-
139
+
141
140
  def each_sibling
142
141
  if block_given?
143
142
  unless root?
@@ -145,73 +144,73 @@ module CSL
145
144
  yield node unless node.equal?(self)
146
145
  end
147
146
  end
148
-
147
+
149
148
  self
150
149
  else
151
150
  enum_for :each_sibling
152
151
  end
153
152
  end
154
-
153
+
155
154
  def siblings
156
155
  @siblings = each_sibling.to_a
157
156
  end
158
-
157
+
159
158
  # Traverses the node's sub-tree in depth-first order.
160
159
  def each_descendant
161
160
  if block_given?
162
161
  each_child do |child|
163
- yield child
162
+ yield child
164
163
  child.each_descendant(&Proc.new)
165
164
  end
166
-
165
+
167
166
  self
168
167
  else
169
168
  enum_for :each_descendant
170
169
  end
171
170
  end
172
-
171
+
173
172
  # Returns all descendants of the node. See {#descendants!}
174
173
  # for a memoized version.
175
174
  def descendants
176
175
  @descendants = each_descendant.to_a
177
176
  end
178
-
177
+
179
178
  def each_ancestor
180
179
  if block_given?
181
180
  p = parent
182
-
181
+
183
182
  until p.nil?
184
183
  yield p
185
184
  p = p.parent
186
185
  end
187
-
186
+
188
187
  self
189
188
  else
190
189
  enum_for :each_ancestor
191
190
  end
192
191
  end
193
-
192
+
194
193
  # @returns this node's ancestors as an array
195
194
  def ancestors
196
195
  @ancestors = each_ancestor.to_a
197
196
  end
198
-
197
+
199
198
  # @return [Fixnum] the node's current depth in the tree
200
199
  def depth
201
200
  @depth = ancestors.length
202
201
  end
203
-
202
+
204
203
  # @return [Node] the root node
205
204
  def root
206
205
  @root = root? ? self : parent.root!
207
206
  end
208
-
207
+
209
208
  # @returns [Boolean] whether or not the node is the tree's root node
210
209
  def root?
211
210
  parent.nil?
212
211
  end
213
212
 
214
-
213
+
215
214
  # Add memoized methods. When processing citations, styles will
216
215
  # typically remain stable; therefore cite processors may opt
217
216
  # to use memoized versions of the following methods. These
@@ -223,34 +222,34 @@ module CSL
223
222
  instance_variable_get(ivar) || send(name)
224
223
  end
225
224
  end
226
-
225
+
227
226
  protected
228
-
227
+
229
228
  # @abstract
230
229
  # Called after the node was added to another node.
231
230
  def added_to(node)
232
231
  end
233
-
232
+
234
233
  # @abstract
235
234
  # Called when the node was deleted from an other node.
236
235
  def deleted_from(node)
237
236
  end
238
-
237
+
239
238
  private
240
-
239
+
241
240
  # @abstract
242
241
  # Called when the passed-in node was added to this node as a child.
243
242
  def added_child(node)
244
243
  end
245
-
244
+
246
245
  # @abstract
247
246
  # Called when the passed-in node was deleted from this node's child nodes.
248
247
  def deleted_child(node)
249
248
  end
250
-
249
+
251
250
 
252
251
  module ClassMethods
253
-
252
+
254
253
  # Returns a new instance of an Array or Struct to manage the Node's
255
254
  # children. This method is called automatically by the Node's
256
255
  # constructor.
@@ -261,27 +260,27 @@ module CSL
261
260
  []
262
261
  end
263
262
  end
264
-
263
+
265
264
  def constantize_nodename(name)
266
265
  return constantize(name) if respond_to?(:constantize)
267
-
266
+
268
267
  klass = name.to_s.capitalize.gsub(/(\w)-(\w)/) { [$1, $2.upcase].join }
269
-
268
+
270
269
  if const_defined?(klass)
271
- const_get(klass)
270
+ const_get(klass)
272
271
  else
273
272
  nil
274
273
  end
275
274
  end
276
-
277
-
275
+
276
+
278
277
  private
279
-
278
+
280
279
  def attr_child_names_for(name)
281
280
  reader = name.to_s.downcase.tr('-', '_')
282
281
  [name.to_sym, reader, "set_child_#{reader}", "has_#{reader}?"]
283
282
  end
284
-
283
+
285
284
  # Creates a Struct for the passed-in child node names that will be
286
285
  # used internally by the Node to manage its children. The Struct
287
286
  # will be automatically initialized and is used similarly to the
@@ -295,7 +294,7 @@ module CSL
295
294
  # method will try to coerce the passed-in value into the correct
296
295
  # node type automatically.
297
296
  def attr_children(*names)
298
-
297
+
299
298
  names.each do |name|
300
299
  name, reader, writer, predicate = attr_child_names_for(name)
301
300
 
@@ -312,7 +311,7 @@ module CSL
312
311
  define_method(writer) do |value|
313
312
  begin
314
313
  klass = self.class.constantize_nodename(name)
315
-
314
+
316
315
  if klass
317
316
  value = klass.new(value)
318
317
  else
@@ -320,7 +319,7 @@ module CSL
320
319
  value = (value.is_a?(String) ? TextNode : Node).new(value)
321
320
  value.nodename = name.to_s
322
321
  end
323
-
322
+
324
323
  rescue => e
325
324
  raise ArgumentError, "failed to convert #{value.inspect} to node: #{e.message}"
326
325
  end unless value.respond_to?(:nodename)
@@ -328,20 +327,20 @@ module CSL
328
327
  children << value
329
328
  value
330
329
  end
331
-
330
+
332
331
  alias_method :"#{reader}=", writer unless method_defined?(:"#{reader}=")
333
332
  end
334
333
  end
335
-
334
+
336
335
  const_set(:Children, Struct.new(*names) {
337
-
336
+
338
337
  # 1.8 Compatibility
339
338
  @keys = members.map(&:to_sym).freeze
340
-
339
+
341
340
  class << self
342
341
  attr_reader :keys
343
342
  end
344
-
343
+
345
344
  def initialize(attrs = {})
346
345
  super(*attrs.symbolize_keys.values_at(*keys))
347
346
  end
@@ -351,9 +350,9 @@ module CSL
351
350
  def keys
352
351
  __class__.keys
353
352
  end
354
-
353
+
355
354
  alias original_each each
356
-
355
+
357
356
  def count
358
357
  values.reject { |c| c.nil? || c.empty? }.length
359
358
  end
@@ -373,11 +372,11 @@ module CSL
373
372
  to_enum
374
373
  end
375
374
  end
376
-
375
+
377
376
  def empty?
378
377
  all?(&:nil?)
379
378
  end
380
-
379
+
381
380
  # Adds the node as a child node. Raises ValidationError if none
382
381
  # of the Struct members matches the node's name. If there is
383
382
  # already a node set with this node name, the node will be pushed
@@ -386,7 +385,7 @@ module CSL
386
385
  unless node.respond_to?(:nodename) && keys.include?(node.nodename.to_sym)
387
386
  raise ValidationError, "not allowed to add #{node.inspect} to #{inspect}"
388
387
  end
389
-
388
+
390
389
  current = self[node.nodename]
391
390
  case current
392
391
  when Array
@@ -396,19 +395,19 @@ module CSL
396
395
  else
397
396
  self[node.nodename] = [current, node]
398
397
  end
399
-
398
+
400
399
  self
401
400
  end
402
-
401
+
403
402
  alias << push
404
-
403
+
405
404
  # Delete items from self that are equal to node. If any items are
406
405
  # found, returns the deleted items. If the items is not found,
407
406
  # returns nil. If the optional code block is given, returns the
408
407
  # result og block if the item is not found.
409
408
  def delete(node)
410
409
  return nil unless node.respond_to?(:nodename)
411
-
410
+
412
411
  deleted = resolve(node.nodename)
413
412
  if deleted.kind_of?(Array)
414
413
  deleted = deleted.delete(node)
@@ -419,30 +418,30 @@ module CSL
419
418
  deleted = nil
420
419
  end
421
420
  end
422
-
421
+
423
422
  if deleted.nil? && block_given?
424
423
  yield
425
424
  else
426
425
  deleted
427
426
  end
428
427
  end
429
-
428
+
430
429
  def fetch(name, default = nil)
431
- if block_given?
430
+ if block_given?
432
431
  resolve(name) || yield(key)
433
432
  else
434
433
  resolve(name) || default
435
434
  end
436
435
  end
437
-
436
+
438
437
  private
439
-
438
+
440
439
  def resolve(nodename)
441
440
  keys.include?(nodename.to_sym) && send(nodename)
442
441
  end
443
442
  })
444
443
  end
445
-
444
+
446
445
  def alias_child(new_name, old_name)
447
446
  attr_child_names_for(new_name).zip(attr_child_names_for(old_name)).each do |nn, on|
448
447
  alias_method nn, on if method_defined?(on)
@@ -450,7 +449,7 @@ module CSL
450
449
  end
451
450
 
452
451
  # Turns the node into a leaf-node.
453
- def has_no_children
452
+ def has_no_children
454
453
  undef_method :add_child
455
454
  undef_method :added_child
456
455
  undef_method :add_children
@@ -459,9 +458,9 @@ module CSL
459
458
  undef_method :delete_child
460
459
  undef_method :deleted_child
461
460
  undef_method :delete_children
462
-
461
+
463
462
  private :children
464
-
463
+
465
464
  define_method(:has_children?) do
466
465
  false
467
466
  end
@@ -471,8 +470,8 @@ module CSL
471
470
  end
472
471
 
473
472
  end
474
-
473
+
475
474
  end
476
-
475
+
477
476
  end
478
477
  end