utilities.rb 4.92 KB
Newer Older
Sylvester Keil's avatar
Sylvester Keil committed
1
module Jekyll
2
  class Scholar
3

4 5 6 7
    # Utility methods used by several Scholar plugins. The methods in this
    # module may depend on the presence of #config, #bibtex_file, and
    # #site readers
    module Utilities
8

9 10 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 38 39 40
      attr_reader :bibtex_file, :config, :site, :query,
        :context, :prefix, :key, :text

      def optparse(arguments)
        return if arguments.nil? || arguments.empty?

        parser = OptionParser.new do |opts|
          opts.on('-c', '--cited') do |cited|
            @cited = true
          end

          opts.on('-f', '--file FILE') do |file|
            @bibtex_file = file
          end

          opts.on('-q', '--query QUERY') do |query|
            @query = query
          end

          opts.on('-p', '--prefix PREFIX') do |prefix|
            @prefix = prefix
          end

          opts.on('-t', '--text TEXT') do |text|
            @text = text
          end
        end

        argv = arguments.split(/(\B-[cfqpt]|\B--(?:cited|file|query|prefix|text))/)

        parser.parse argv.map(&:strip).reject(&:empty?)
      end
41

42
      def bibtex_options
Artem Shinkarov's avatar
Artem Shinkarov committed
43
        @bibtex_options ||= { :strip => false }
44
      end
45

46 47 48
      def bibtex_path
        @bibtex_path ||= extend_path(bibtex_file)
      end
49

50 51
      def bibliography
        @bibliography ||= BibTeX.open(bibtex_path, bibtex_options)
52 53
      end

54
      def entries
55
        b = bibliography[query || config['query']]
56 57

        unless config['sort_by'] == 'none'
58
          b = b.sort_by { |e| e[config['sort_by']].to_s }
59 60
          b.reverse! if config['order'] =~ /^(desc|reverse)/i
        end
61

62 63
        b
      end
64

65 66 67 68
      def cited_only?
        !!@cited
      end

69 70 71 72
      def extend_path(name)
        if name.nil? || name.empty?
          name = config['bibliography']
        end
73

74 75
        # return as is if it is an absolute path
        return name if name.start_with?('/') && File.exists?(name)
76

77 78 79 80
        p = File.join(config['source'], name)
        p << '.bib' unless File.exists?(p)
        p
      end
81

82
      def reference_tag(entry)
Sylvester Keil's avatar
Sylvester Keil committed
83
        return missing_reference unless entry
84

Artem Shinkarov's avatar
Artem Shinkarov committed
85
        entry = entry.convert(:latex)
86 87 88
        reference = CiteProc.process entry.to_citeproc,
          :style => config['style'], :locale => config['locale'], :format => 'html'

Sylvester Keil's avatar
Sylvester Keil committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
        content_tag reference_tagname, reference,
          :id => [prefix, entry.key].compact.join('-')
      end

      def missing_reference
        config['missing_reference']
      end

      def reference_tagname
        config['reference_tagname'] || :span
      end

      def bibliography_template
        config['bibliography_template'] || '%{reference}'
      end

      def bibliography_tag(entry)
        return missing_reference unless entry

        bibliography_template % {
          :reference => reference_tag(entry),
          :key => entry.key
        }
112 113
      end

114 115 116
      def generate_details?
        site.layouts.key?(File.basename(config['details_layout'], '.html'))
      end
117

118 119
      def details_file_for(entry)
        name = entry.key.to_s.dup
120

121
        name.gsub!(/[:\s]+/, '_')
122

123 124
        [name, 'html'].join('.')
      end
125

Sylvester Keil's avatar
Sylvester Keil committed
126
      def details_link_for(entry, base = base_url)
127
        File.join(base, details_path, details_file_for(entry))
Sylvester Keil's avatar
Sylvester Keil committed
128
      end
129

Sylvester Keil's avatar
Sylvester Keil committed
130
      def base_url
131
        @base_url ||= site.config['baseurl'] || site.config['base_url'] || ''
132
      end
133

134 135 136
      def details_path
        config['details_dir']
      end
137

Sylvester Keil's avatar
Sylvester Keil committed
138
      def cite(key)
139 140 141
        context['cited'] ||= []
        context['cited'] << key

Sylvester Keil's avatar
Sylvester Keil committed
142
        if bibliography.key?(key)
143
          entry = bibliography[key].convert(:latex)
Sylvester Keil's avatar
Sylvester Keil committed
144 145
          citation = CiteProc.process entry.to_citeproc, :style => config['style'],
            :locale => config['locale'], :format => 'html', :mode => :citation
146

147
          link_to "##{[prefix, entry.key].compact.join('-')}", citation.join
Sylvester Keil's avatar
Sylvester Keil committed
148
        else
149
          '(missing reference)'
Sylvester Keil's avatar
Sylvester Keil committed
150
        end
151 152
      rescue
        "(#{key})"
Sylvester Keil's avatar
Sylvester Keil committed
153
      end
Sylvester Keil's avatar
Sylvester Keil committed
154

155
      def cite_details(key, text)
Hiren Patel's avatar
Hiren Patel committed
156
        if bibliography.key?(key)
Sylvester Keil's avatar
Sylvester Keil committed
157
          link_to details_link_for(bibliography[key]), text || config['details_link']
Hiren Patel's avatar
Hiren Patel committed
158
        else
159
          '(missing reference)'
Hiren Patel's avatar
Hiren Patel committed
160 161
        end
      end
162

Sylvester Keil's avatar
Sylvester Keil committed
163 164 165 166 167 168
      def content_tag(name, content_or_attributes, attributes = {})
        if content_or_attributes.is_a?(Hash)
          content, attributes = nil, content_or_attributes
        else
          content = content_or_attributes
        end
169

Sylvester Keil's avatar
Sylvester Keil committed
170
        attributes = attributes.map { |k,v| %Q(#{k}="#{v}") }
171

Sylvester Keil's avatar
Sylvester Keil committed
172 173 174 175 176 177
        if content.nil?
          "<#{[name, attributes].flatten.compact.join(' ')}/>"
        else
          "<#{[name, attributes].flatten.compact.join(' ')}>#{content}</#{name}>"
        end
      end
178

Sylvester Keil's avatar
Sylvester Keil committed
179 180 181
      def link_to(href, content, attributes = {})
        content_tag :a, content || href, attributes.merge(:href => href)
      end
182

183 184 185 186
      def cited_references
        context && context['cited'] || []
      end

Sylvester Keil's avatar
Sylvester Keil committed
187
      def set_context_to(context)
188
        @context, @site, = context, context.registers[:site]
Sylvester Keil's avatar
Sylvester Keil committed
189 190
        config.merge!(site.config['scholar'] || {})
      end
191
    end
192

193
  end
Hiren Patel's avatar
Hiren Patel committed
194
end