lib/citeproc/js/engine.rb in citeproc-js-0.0.2 vs lib/citeproc/js/engine.rb in citeproc-js-0.0.6

- old
+ new

@@ -1,153 +1,151 @@ module CiteProc module JS - + class Engine < CiteProc::Engine @name = 'citeproc-js'.freeze @type = 'CSL'.freeze @version = '1.0' @priority = 0 - + @path = File.expand_path('../support', __FILE__) class << self - + attr_reader :path - + def parser ExecJS.runtime.name =~ /rhino|spidermonkey/i ? 'xmle4x.js' : 'xmldom.js' end - + # Returns the citeproc-js JavaScript code. def source @source || reload end - + # Forces a reload citeproc-js JavaScript code. Returns the source # code. def reload @source = [ parser, 'citeproc.js', 'system.js' ].map { |s| File.open(File.join(path,s), 'r:UTF-8').read }.join.freeze end private - + def attr_context(*arguments) arguments.flatten.each do |m| define_method(underscore(m)) do delegate "citeproc.#{m}" end end end - + def delegate_context(*arguments) arguments.flatten.each do |m| define_method(underscore(m)) do |*args| delegate "citeproc.#{m}(#{args.map { |a| MultiJson.encode(a) }.join(',')})" end end end - + def underscore(javascript_method) word = javascript_method.to_s.split(/\./)[-1] word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2') word.gsub!(/([a-z\d])([A-Z])/, '\1_\2') word.downcase! word end end - - # - # instance methods - # - def style=(style) - @style = Style.load(style.to_s) - end - - def locales=(locale) - @locales = { locale.to_sym => Locale.load(locale.to_s) } - end - + attr_context :processor_version, :csl_version, :opt alias flags opt delegate_context %w{ setOutputFormat updateItems updateUncitedItems makeBibliography appendCitationCluster processCitationCluster previewCitationCluster registry.getSortedRegistryItems } - + alias format= set_output_format - alias bibliography make_bibliography alias sorted_registry_items get_sorted_registry_items %w{ append process preview }.each do |m| alias_method m, "#{m}_citation_cluster" end - + + # Don't expose all delegates to public interface + private :opt, :append_citation_cluster, :process_citation_cluster, + :set_output_format, :make_bibliography, :preview_citation_cluster, + :get_sorted_registry_items + def registry @registry ||= Hash.new { |h,k| delegate "citeproc.registry.#{k}" } end - + def citation_registry @citation_registry ||= Hash.new { |h,k| registry["citationreg.#{k}"] } end - - def language; options[:locale]; end - - def start - return if started? - super - self.style = processor.options[:style] if @style.nil? - self.locales = processor.options[:locale] if @locales.nil? - - @context = ExecJS.compile(Engine.source) - update_system - - delegate "citeproc = new CSL.Engine(system, #{style.inspect}, #{language.inspect})", :exec - set_output_format(options[:format]) - - self - rescue => e - stop - raise EngineError.new('failed to start engine', e) + # The processor's items converted to citeproc-js format + def items + Hash[*processor.items.map { |id, item| + [id.to_s, item.respond_to?(:to_citeproc) ? item.to_citeproc : item.to_s] + }.flatten] end - def stop - @context = nil - super + # The locale put into a hash to make citeproc-js happy + def locales + { locale.name => locale.to_s } end - def set_abbreviations(namespace) + # Sets the abbreviation's namespace, both in Ruby and JS land + def namespace=(namespace) delegate "citeproc.setAbbreviations(#{ namespace.to_s.inspect })" - @default_namespace = namespace.to_sym + @namespace = namespace.to_sym end - alias default_namespace= set_abbreviations + def bibliography(selector = Selector.new) + Bibliography(make_bibliography(selector.to_citeproc)) + end + + def append(citation) + append_citation_cluster(citation.to_citeproc, false) + end private + def context + @context || compile_context + end + + def compile_context + @context = ExecJS.compile(Engine.source) + update_system(:abbreviations, :items, :locales) + + delegate "citeproc = new CSL.Engine(system, #{style.to_s.inspect}, #{locale.name.inspect})", :exec + set_output_format(options[:format]) + + @context + rescue => e + raise EngineError, "failed to compile engine context: #{e.message}" + end + def update_system(*arguments) - arguments = [:abbreviations, :items, :locales] if arguments.empty? - delegate "system.update(#{ MultiJson.encode(Hash[*arguments.flatten.map { |a| [a, send(a)] }.flatten]) })" + arguments = arguments.flatten.map { |a| [a, send(a)] } + delegate "system.update(#{ MultiJson.encode(Hash[*arguments.flatten]) })" end - + def delegate(script, method = :eval) - if running? - @context.send(method, script) - else - warn "not executing script: engine has not been started" - end + context.send(method, script) rescue => e - raise EngineError.new('failed to execute javascript:', e) + raise EngineError, "failed to execute javascript: #{e.message}" end - + end - + end end