lib/csl/style/names.rb in csl-1.0.2 vs lib/csl/style/names.rb in csl-1.1.0
- old
+ new
@@ -1,25 +1,32 @@
+# encoding: utf-8
+
module CSL
class Style
class Names < Node
+ extend InheritsNameOptions
- attr_struct :variable, *Schema.attr(:names, :delimiter, :affixes, :font)
+ attr_struct :variable, *Schema.attr(:delimiter, :affixes, :font)
attr_children :name, :'et-al', :label, :substitute
+ inherits :names_options
+
alias labels label
def initialize(attributes = {})
super(attributes)
children[:label] = []
yield self if block_given?
end
- def delimiter
- attributes.fetch(:delimiter, '')
+ def delimiter(node = nil, style = nil)
+ attributes.fetch(:delimiter) do
+ inherited_names_options(node, style)[:delimiter] || ''
+ end
end
def has_variable?
attribute?(:variable)
end
@@ -30,39 +37,56 @@
end
class Name < Node
+ extend InheritsNameOptions
attr_struct :form, *Schema.attr(:name, :affixes, :font, :delimiter)
- attr_defaults :form => 'long', :delimiter => ', ',
- :'delimiter-precedes-last' => 'contextual', :initialize => true,
- :'sort-separator' => ', '
+ # Having default attributes makes inheritance really difficult.
+ #
+ # attr_defaults :form => 'long', :delimiter => ', ',
+ # :'delimiter-precedes-last' => 'contextual', :initialize => true,
+ # :'sort-separator' => ', '
attr_children :'name-part'
+ inherits :name_options
+
alias parts name_part
def initialize(attributes = {})
super(attributes)
children[:'name-part'] = []
yield self if block_given?
end
+ def count?
+ attribute?(:form) && attributes[:form] == 'count'
+ end
- def initialize?
- attributes[:initialize].to_s !~ /^false$/i
+ def name_options
+ attributes_for :form, :initialize, :'initialize-with', :'sort-separator'
end
+ def initialize_without_hyphen?
+ !root? && root.respond_to?(:initialize_without_hyphen?) &&
+ root.initialize_without_hyphen?
+ end
+
def et_al
- parent && parent.et_al
+ @et_al || parent && parent.et_al
end
+ def et_al=(et_al)
+ @et_al = et_al
+ end
+
# @param names [#to_i, Enumerable] the list of names (or its length)
- # @return [Boolean] whether or not the should be truncate
+ # @return [Boolean] whether or not the list should be truncated
def truncate?(names, subsequent = false)
names = names.length if names.respond_to?(:length)
limit = truncate_when(subsequent)
!limit.zero? && names.to_i >= limit
@@ -77,54 +101,156 @@
names.take limit
end
def truncate_when(subsequent = false)
if subsequent && attribute?(:'et-al-subsequent-min')
- attribute[:'et-al-subsequent-min'].to_i
+ attributes[:'et-al-subsequent-min'].to_i
else
- attribute[:'et-al-min'].to_i
+ attributes[:'et-al-min'].to_i
end
end
def truncate_at(subsequent = false)
if subsequent && attribute?(:'et-al-subsequent-use-first')
- attribute[:'et-al-subsequent-use-first'].to_i
+ attributes.fetch(:'et-al-subsequent-use-first', 1).to_i
else
- attribute[:'et-al-use-first'].to_i
+ attributes.fetch(:'et-al-use-first', 1).to_i
end
end
+ def truncate_at!(at)
+ attributes[:'et-al-use-first'] = at.to_i
+ self
+ end
+
+ def truncate_when!(pos)
+ attributes[:'et-al-min'] = pos.to_i
+ self
+ end
+
+ def truncate_subsequent_at!(at)
+ attributes[:'et-al-subsequent-use-first'] = at.to_i
+ self
+ end
+
+ def truncate_subsequent_when!(pos)
+ attributes[:'et-al-subsequent-min'] = pos.to_i
+ self
+ end
+
# @return [String] the delimiter between family and given names
# in sort order
def sort_separator
- attributes[:'sort-separator'].to_s
+ attributes[:'sort-separator'] || ', '
end
# @return [String] the delimiter between names
def delimiter
- attributes[:delimiter].to_s
+ attributes[:delimiter] || ', '
end
def name_as_sort_order?
attribute?(:'name-as-sort-order')
end
+ def name_as_sort_order_at?(position)
+ return false unless name_as_sort_order?
+ all_names_as_sort_order? || position == 1 && first_name_as_sort_order?
+ end
+
def name_as_sort_order
attributes[:'name-as-sort-order'].to_s
end
alias sort_order name_as_sort_order
def first_name_as_sort_order?
- attributes[:'name-as-sort-order'].to_s =~ /^first$/i
+ !!(attributes[:'name-as-sort-order'].to_s =~ /^first$/i)
end
def all_names_as_sort_order?
- attributes[:'name-as-sort-order'].to_s =~ /^all$/i
+ !!(attributes[:'name-as-sort-order'].to_s =~ /^all$/i)
end
-
+ def first_name_as_sort_order!
+ attributes[:'name-as-sort-order'] = 'first'
+ self
+ end
+
+ def all_names_as_sort_order!
+ attributes[:'name-as-sort-order'] = 'all'
+ self
+ end
+
+ def delimiter_precedes_et_al?(names)
+ names = names.length if names.respond_to?(:length)
+
+ case
+ when delimiter_never_precedes_et_al?
+ false
+ when delimiter_always_precedes_et_al?
+ true
+ when delimiter_precedes_et_al_after_inverted_name?
+ name_as_sort_order_at?(names.to_i)
+ else
+ names.to_i > 1
+ end
+ end
+
+ # @return [Boolean] whether or not the delimmiter should
+ # always be inserted before et-al
+ def delimiter_always_precedes_et_al?
+ !!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^always$/i)
+ end
+
+ # Set the :'delimiter-precedes-et-al' attribute to 'always'.
+ # @return [self] self
+ def delimiter_always_precedes_et_al!
+ attributes[:'delimiter-precedes-et-al'] = 'always'
+ self
+ end
+
+ alias delimiter_precedes_et_al! delimiter_always_precedes_et_al!
+
+
+ # @return [Boolean] whether or not the delimiter should
+ # never be inserted before et-al
+ def delimiter_never_precedes_et_al?
+ !!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^never$/i)
+ end
+
+ # Set the :'delimiter-precedes-et-al' attribute to 'never'
+ # @return [self] self
+ def delimiter_never_precedes_et_al!
+ attributes[:'delimiter-precedes-et-al'] = 'never'
+ self
+ end
+
+ # @return [Boolean] whether or not the delimtier should
+ # be inserted between before et-al depending on the
+ # number of names rendered
+ def delimiter_contextually_precedes_et_al?
+ return true unless attribute?[:'delimiter-precedes-et-al']
+ !!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^contextual/i)
+ end
+
+ # Set the :'delimiter-precedes-et-al' attribute to 'contextual'
+ # @return [self] self
+ def delimiter_contextually_precedes_et_al!
+ attributes[:'delimiter-precedes-et-al'] = 'contextual'
+ self
+ end
+
+ def delimiter_precedes_et_al_after_inverted_name?
+ !!(attributes[:'delimiter-precedes-et-al'].to_s =~ /^after-inverted-name/i)
+ end
+
+ def delimiter_precedes_et_al_after_inverted_name!
+ attributes[:'delimiter-precedes-et-al'] = 'after-inverted-name'
+ self
+ end
+
# @param names [#to_i, Enumerable] the list of names (or its length)
# @return [Boolean] whether or not the delimiter will be inserted between
# the penultimate and the last name
def delimiter_precedes_last?(names)
names = names.length if names.respond_to?(:length)
@@ -134,11 +260,11 @@
true
when delimiter_never_precedes_last?
false
when delimiter_always_precedes_last?
true
- when delimiter_precedeces_last_after_inverted_name?
+ when delimiter_precedes_last_after_inverted_name?
if name_as_sort_order?
all_names_as_sort_order? || names.to_i == 2
else
false
end
@@ -178,10 +304,11 @@
end
# @return [Boolean] whether or not the should be inserted between the
# penultimate and the last name depending on the number of names
def delimiter_contextually_precedes_last?
+ return true unless attribute?(:'delimiter-precedes-last')
!!(attributes[:'delimiter-precedes-last'].to_s =~ /^contextual/i)
end
# Set the :'delimiter-precedes-last' attribute to 'contextual'
# @return [self] self
@@ -201,29 +328,41 @@
def ellipsis?
attributes[:'et-al-use-last'].to_s =~ /^true$/
end
+ def ellipsis
+ "#{delimiter}… "
+ end
+
def connector
c = attributes[:and]
c == 'symbol' ? '&' : c
end
+
+ def connector=(c)
+ attributes[:and] = c
+ end
end
class NamePart < Node
has_no_children
attr_struct :name, :'text-case', *Schema.attr(:affixes, :font)
+
+ def name
+ attributes[:name]
+ end
end
class EtAl < Node
has_no_children
- attr_struct :term, *Schema.attr(:affixes, :font)
+ attr_struct :term, :'text-case', *Schema.attr(:affixes, :font)
attr_defaults :term => 'et-al'
end
class Substitute < Node
end
end
-end
\ No newline at end of file
+end