citeproc 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,22 @@
1
1
  require 'forwardable'
2
2
 
3
3
  module CiteProc
4
-
4
+
5
5
  class Engine
6
-
7
6
  extend Forwardable
8
- include Abbreviate
9
-
7
+
8
+ include Converters
9
+
10
10
  @subclasses ||= []
11
11
 
12
12
  class << self
13
-
13
+
14
14
  attr_reader :subclasses, :type, :version
15
-
15
+
16
16
  attr_writer :default
17
-
17
+
18
18
  private :new
19
-
19
+
20
20
  def inherited(subclass)
21
21
  subclass.public_class_method :new
22
22
  @subclasses << subclass
@@ -34,33 +34,33 @@ module CiteProc
34
34
  subclasses.detect { |e| e.name == name } ||
35
35
  block_given? ? yield(subclasses) : nil
36
36
  end
37
-
37
+
38
38
  # Loads the engine with the given name and returns the engine class.
39
39
  def detect!(name)
40
40
  load(name)
41
41
  block_given? ? detect(name, &Proc.new) : detect(name)
42
42
  end
43
-
43
+
44
44
  # Returns the best available engine class or nil.
45
45
  def autodetect(options = {})
46
46
  subclasses.detect { |e|
47
47
  !options.has_key?(:engine) || e.name == options[:engine] and
48
48
  !options.has_key?(:name) || e.name == options[:name]
49
- } || subclasses.first
49
+ } || subclasses.first
50
50
  end
51
-
51
+
52
52
  # Loads the engine by requiring the engine name.
53
53
  def load(name)
54
54
  require name.gsub(/-/,'/')
55
55
  rescue LoadError
56
56
  warn "failed to load #{name} engine: try to gem install #{name}"
57
57
  end
58
-
58
+
59
59
  # Returns a list of all available engine names.
60
60
  def available
61
61
  subclasses.map(&:engine_name)
62
62
  end
63
-
63
+
64
64
  def engine_name
65
65
  @name ||= name.gsub(/::/, '-').downcase # returns class name as fallback
66
66
  end
@@ -70,64 +70,45 @@ module CiteProc
70
70
  end
71
71
  end
72
72
 
73
- attr_accessor :processor, :locales, :style, :items
74
-
75
- def initialize(attributes = {})
76
- @processor = attributes[:processor]
77
-
78
- @items = attributes[:items] || {}
79
- @abbreviations = attributes[:abbreviations] || { :default => {} }
80
-
73
+ attr_accessor :processor
74
+
75
+ def_delegators :@processor, :options, :abbreviations, :style, :locale,
76
+ :items, :language, :region, :abbreviate
77
+
78
+ def initialize(processor = nil)
79
+ @processor = processor
81
80
  yield self if block_given?
82
81
  end
83
82
 
84
- def start
85
- @started = true
86
- self
87
- end
88
-
89
- def stop
90
- @started = false
91
- self
92
- end
93
-
94
- def started?; !!@started; end
95
-
96
- alias running? started?
97
-
98
83
  [[:name, :engine_name], :type, :version].each do |method_id, target|
99
84
  define_method(method_id) do
100
85
  self.class.send(target || method_id)
101
86
  end
102
87
  end
103
-
88
+
104
89
  def process
105
90
  raise NotImplementedByEngine
106
91
  end
107
-
108
- alias process_citation_cluster process
109
92
 
110
93
  def append
111
94
  raise NotImplementedByEngine
112
95
  end
113
-
114
- alias append_citation_cluster append
115
96
 
116
-
117
97
  def bibliography
118
98
  raise NotImplementedByEngine
119
99
  end
120
-
121
- alias make_bibliography bibliography
122
-
100
+
123
101
  def update_items
124
102
  raise NotImplementedByEngine
125
103
  end
126
-
104
+
127
105
  def update_uncited_items
128
106
  raise NotImplementedByEngine
129
107
  end
130
-
108
+
109
+ def inspect
110
+ "#<CiteProc::Engine #{name}-#{type}-#{version}>"
111
+ end
131
112
  end
132
113
 
133
114
  end
data/lib/citeproc/item.rb CHANGED
@@ -1,113 +1,122 @@
1
1
  module CiteProc
2
-
3
- # Items are similar to a Ruby Hash but pose a number of constraints on their
4
- # contents: keys are always (implicitly converted to) symbols and values
5
- # are strictly instances of CiteProc::Variable. When Items are constructed
6
- # from (or merged with) JSON objects or Hashes Variable instances are
7
- # automatically created using by passing the variables key as type to
8
- # Variable.create this will create the expected Variable type for all
9
- # fields defined in CSL (for example, the `issued' field will become a
10
- # CiteProc::Date object); unknown types will be converted to simple
11
- # CiteProc::Variable instances, which should be fine for numeric or string
12
- # values but may cause problems for more complex types.
13
- #
14
- # Every Item provides accessor methods for all known field names; unknown
15
- # fields can still be accessed using array accessor syntax.
16
- #
17
- # i = Item.new(:edition => 3, :unknown_field => 42)
18
- # i.edition -> #<CiteProc::Number "3">
19
- # i[:edition] -> #<CiteProc::Number "3">
20
- # i[:unknown_field] -> #<CiteProc::Variable "42">
21
- #
22
- # Items can be converted to the CiteProc JSON format via #to_citeproc (or
23
- # #to_json to get a JSON string).
24
- class Item
25
-
26
- @types = [
27
- :article, :'article-journal', :'article-magazine', :'article-newspaper',
28
- :bill, :book, :broadcast, :chapter, :entry, :'entry-dictionary',
29
- :'entry-encyclopedia', :figure, :graphic, :interview, :legal_case,
30
- :legislation, :manuscript, :map, :motion_picture, :musical_score,
31
- :pamphlet, :'paper-conference', :patent, :personal_communication, :post,
32
- :'post-weblog', :report, :review, :'review-book', :song, :speech,
33
- :thesis, :treaty, :webpage].freeze
34
-
35
- @bibtex_types = Hash.new { |h,k| :misc }.merge(Hash[*%w{
36
- pamphlet booklet
37
- paper-conference conference
38
- chapter inbook
39
- chapter incollection
40
- paper-conference inproceedings
41
- book manual
42
- thesis phdthesis
43
- paper-conference proceedings
44
- report techreport
45
- manuscript unpublished
46
- article article
47
- article-journal article
48
- article-magazine article
49
- }.map(&:intern)]).freeze
50
-
51
- class << self
52
- attr_reader :types, :bibtex_types
53
- end
54
-
55
- include Attributes
56
- include Enumerable
57
-
58
- attr_predicates :id, :'short-title', :'journal-abbreviation',
59
- *Variable.fields[:all]
60
-
61
- def initialize(attributes = nil)
62
- merge(attributes)
63
- end
64
-
65
- def initialize_copy(other)
66
- @attributes = other.attributes.deep_copy
67
- end
2
+
3
+
4
+ # Items are similar to a Ruby Hash but pose a number of constraints on their
5
+ # contents: keys are always (implicitly converted to) symbols and values
6
+ # are strictly instances of CiteProc::Variable. When Items are constructed
7
+ # from (or merged with) JSON objects or Hashes Variable instances are
8
+ # automatically created using by passing the variables key as type to
9
+ # Variable.create this will create the expected Variable type for all
10
+ # fields defined in CSL (for example, the `issued' field will become a
11
+ # CiteProc::Date object); unknown types will be converted to simple
12
+ # CiteProc::Variable instances, which should be fine for numeric or string
13
+ # values but may cause problems for more complex types.
14
+ #
15
+ # Every Item provides accessor methods for all known field names; unknown
16
+ # fields can still be accessed using array accessor syntax.
17
+ #
18
+ # i = Item.new(:edition => 3, :unknown_field => 42)
19
+ # i.edition -> #<CiteProc::Number "3">
20
+ # i[:edition] -> #<CiteProc::Number "3">
21
+ # i[:unknown_field] -> #<CiteProc::Variable "42">
22
+ #
23
+ # Items can be converted to the CiteProc JSON format via #to_citeproc (or
24
+ # #to_json to get a JSON string).
25
+ class Item
68
26
 
69
- # Don't expose attributes. Items need to mimic Hash functionality in a controlled way.
70
- private :attributes
71
-
72
- def each
73
- if block_given?
74
- attributes.each(&Proc.new)
75
- self
76
- else
77
- to_enum
78
- end
79
- end
80
-
81
- # Returns a corresponding BibTeX::Entry if the bibtex-ruby gem is installed;
82
- # otherwise returns a BibTeX string.
83
- def to_bibtex
84
- # hash = to_hash
85
- #
86
- # hash[:type] = Item.bibtex_types[hash[:type]]
87
- #
88
- # if hash.has_key?(:issued)
89
- # date = hash.delete(:issued)
90
- # hash[:year] = date.year
91
- # hash[:month] = date.month
92
- # end
93
- #
94
- # Variable.fields[:date].each do |field|
95
- # hash[field] = hash[field].to_s if hash.has_key?(field)
96
- # end
97
- #
98
- # Variable.fields[:names].each do |field|
99
- # hash[field] = hash[field].map(&:sort_order!).join(' and ')
100
- # end
101
-
102
- raise 'not implemented yet'
103
- end
104
-
105
- private
106
-
107
- def filter_value(value, key)
108
- Variable.create!(value, key)
109
- end
27
+ @types = [
28
+ :article, :'article-journal', :'article-magazine', :'article-newspaper',
29
+ :bill, :book, :broadcast, :chapter, :entry, :'entry-dictionary',
30
+ :'entry-encyclopedia', :figure, :graphic, :interview, :legal_case,
31
+ :legislation, :manuscript, :map, :motion_picture, :musical_score,
32
+ :pamphlet, :'paper-conference', :patent, :personal_communication, :post,
33
+ :'post-weblog', :report, :review, :'review-book', :song, :speech,
34
+ :thesis, :treaty, :webpage].freeze
35
+
36
+ @bibtex_types = Hash.new { |h,k| :misc }.merge(Hash[*%w{
37
+ pamphlet booklet
38
+ paper-conference conference
39
+ chapter inbook
40
+ chapter incollection
41
+ paper-conference inproceedings
42
+ book manual
43
+ thesis phdthesis
44
+ paper-conference proceedings
45
+ report techreport
46
+ manuscript unpublished
47
+ article article
48
+ article-journal article
49
+ article-magazine article
50
+ }.map(&:intern)]).freeze
51
+
52
+ class << self
53
+ attr_reader :types, :bibtex_types
54
+ end
55
+
56
+ include Attributes
57
+ include Enumerable
58
+
59
+ attr_predicates :id, :'short-title', :'journal-abbreviation',
60
+ *Variable.fields[:all]
61
+
62
+ def initialize(attributes = nil)
63
+ merge(attributes)
64
+ end
65
+
66
+ def initialize_copy(other)
67
+ @attributes = other.attributes.deep_copy
68
+ end
69
+
70
+ # Don't expose attributes. Items need to mimic Hash functionality in a controlled way.
71
+ private :attributes
72
+
73
+ def each
74
+ if block_given?
75
+ attributes.each(&Proc.new)
76
+ self
77
+ else
78
+ to_enum
79
+ end
80
+ end
81
+
82
+ # Returns a corresponding BibTeX::Entry if the bibtex-ruby gem is installed;
83
+ # otherwise returns a BibTeX string.
84
+ def to_bibtex
85
+ # hash = to_hash
86
+ #
87
+ # hash[:type] = Item.bibtex_types[hash[:type]]
88
+ #
89
+ # if hash.has_key?(:issued)
90
+ # date = hash.delete(:issued)
91
+ # hash[:year] = date.year
92
+ # hash[:month] = date.month
93
+ # end
94
+ #
95
+ # Variable.fields[:date].each do |field|
96
+ # hash[field] = hash[field].to_s if hash.has_key?(field)
97
+ # end
98
+ #
99
+ # Variable.fields[:names].each do |field|
100
+ # hash[field] = hash[field].to_bibtex
101
+ # end
102
+
103
+ raise 'not implemented yet'
104
+ end
105
+
106
+ def to_sym
107
+ id.to_s.to_sym
108
+ end
109
+
110
+ def inspect
111
+ "#<CiteProc::Item id=#{id.inspect} attributes={#{attributes.length}}>"
112
+ end
113
+
114
+ private
110
115
 
111
- end
116
+ def filter_value(value, key)
117
+ Variable.create!(value, key)
118
+ end
112
119
 
120
+ end
121
+
113
122
  end
@@ -1,8 +1,11 @@
1
1
 
2
2
  module CiteProc
3
+
3
4
  class Processor
4
-
5
5
  extend Forwardable
6
+
7
+ include Abbreviate
8
+ include Converters
6
9
 
7
10
  @defaults = {
8
11
  :locale => 'en-US',
@@ -15,41 +18,105 @@ module CiteProc
15
18
  attr_reader :defaults
16
19
  end
17
20
 
18
- attr_reader :options, :engine, :items, :style
21
+ attr_reader :options, :items
22
+ attr_writer :engine
23
+
24
+ def_delegators :@locale, :language, :region
25
+
26
+ def_delegators :@items, :key?, :value?, :has_key?, :has_value?,
27
+ :include?, :member?, :length, :empty?
19
28
 
20
- def_delegators :@engine, :abbreviate, :abbreviations, :abbreviations=
21
-
22
29
  def initialize(options = {})
23
- @options = Processor.defaults.merge(options)
24
- @engine = Engine.autodetect(@options).new(:processor => self)
25
- @style = Style.load(@options[:style])
26
- @locales = @options[:locale]
27
- @items = {}
28
- end
29
-
30
- def style=(style)
31
- @style = Style.load(style.to_s)
32
- @engine.style = @style
33
- @style
34
- end
35
-
36
- def locales=(locale)
37
- @locales = { locale.to_sym => Locale.load(locale.to_s) }
38
- @engine.locales = @locales
39
- @locales
40
- end
41
-
42
- def process(*arguments)
43
- @engine.process(CitationData(arguments.flatten(1)))
44
- end
45
-
46
- def append(*arguments)
47
- @engine.append(CitationData(arguments.flatten(1)))
48
- end
49
-
50
- def bibliography(*arguments, &block)
51
- @engine.bibliography(Selector.new(*arguments, &block))
52
- end
53
-
30
+ @options, @items = Processor.defaults.merge(options), {}
31
+ yield self if block_given?
32
+ end
33
+
34
+ def engine
35
+ @engine ||= Engine.autodetect(options).new(self)
36
+ end
37
+
38
+ def style
39
+ @style || load_style
40
+ end
41
+
42
+ def locale
43
+ @locale || load_locale
44
+ end
45
+
46
+ def load_style(new_style = nil)
47
+ options[:style] = new_style unless new_style.nil?
48
+ @style = Style.open(options[:style])
49
+ end
50
+
51
+ def load_locale(new_locale = nil)
52
+ options[:locale] = new_locale unless new_locale.nil?
53
+ @locale = Locale.open(options[:locale])
54
+ end
55
+
56
+ def [](id)
57
+ items[id.to_sym]
58
+ end
59
+
60
+ def []=(id, item)
61
+ items[id.to_sym] = Item(item)
62
+ end
63
+
64
+ def register(item)
65
+ item = Item(item)
66
+ items[item.to_sym] = item
67
+ rescue => e
68
+ raise "failed to register item #{item.inspect}: #{e.message}"
69
+ end
70
+
71
+ def <<(item)
72
+ register(item)
73
+ self
74
+ end
75
+
76
+ def update(*arguments)
77
+ arguments.flatten(1).each do |argument|
78
+ case argument
79
+ when Item
80
+ register(argument)
81
+ when Array
82
+ argument.each { |item| register(item) }
83
+ when Hash
84
+ argument.each do |id, item|
85
+ id, item = id.to_sym, Item(item)
86
+
87
+ if items.key?(id) && block_given?
88
+ items[id] = yield items[id], item
89
+ else
90
+ items[id] = item
91
+ end
92
+ end
93
+ else
94
+ raise "failed to register items #{argument.inspect}"
95
+ end
96
+ end
97
+
98
+ self
99
+ ensure
100
+ # notify engine
101
+ end
102
+
103
+
104
+
105
+ def process(*arguments)
106
+ engine.process(CitationData(arguments.flatten(1)))
107
+ end
108
+
109
+ def append(*arguments)
110
+ engine.append(CitationData(arguments.flatten(1)))
111
+ end
112
+
113
+ def bibliography(*arguments, &block)
114
+ engine.bibliography(Selector.new(*arguments, &block))
115
+ end
116
+
117
+ def inspect
118
+ "#<CiteProc::Processor style=#{style.name.inspect} locale=#{locale.name.inspect} items=[#{items.length}]>"
119
+ end
120
+
54
121
  end
55
122
  end