utilities.rb 7.33 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
      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|
21 22
            @bibtex_file ||= []
            @bibtex_file << file
23 24 25 26 27 28 29 30 31 32 33 34 35
          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
36 37 38

          opts.on('-s', '--style STYLE') do |style|
            @style = style
39
          end
40 41 42 43

          opts.on('-T', '--template TEMPLATE') do |template|
            @bibliography_template = template
          end
44 45
        end

46
        argv = arguments.split(/(\B-[cfqptTs]|\B--(?:cited|file|query|prefix|text|style|template|))/)
47 48 49

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

51
      def bibtex_options
52 53 54 55 56
        config['bibtex_options'] ||= {}
      end

      def bibtex_filters
        config['bibtex_filters'] ||= []
57
      end
58

59 60 61
      def bibtex_path
        @bibtex_path ||= extend_path(bibtex_file)
      end
62

63
      def bibliography
64
        unless @bibliography
65 66 67
          tmp = ""
          bibtex_path.each{|s| tmp << IO.read(s)}
          @bibliography = BibTeX.parse(tmp, bibtex_options)
68 69 70 71
          @bibliography.replace_strings if replace_strings?
        end

        @bibliography
72 73
      end

74
      def entries
75
        b = bibliography[query || config['query']]
76 77

        unless config['sort_by'] == 'none'
78
          b = b.sort_by { |e| e[config['sort_by']].to_s }
79 80
          b.reverse! if config['order'] =~ /^(desc|reverse)/i
        end
81

82 83
        b
      end
84

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
      def repository?
        !config['repository'].nil? && !config['repository'].empty?
      end

      def repository
        @repository ||= load_repository
      end

      def load_repository
        return {} unless repository?

        Hash[Dir[File.join(repository_path, '**/*.{pdf,ps}')].map { |path|
          [File.basename(path).sub(/\.(pdf|ps)$/, ''), path]
        }]
      end

      def repository_path
        config['repository']
      end

105 106 107 108
      def replace_strings?
        config['replace_strings']
      end

109 110 111 112
      def cited_only?
        !!@cited
      end

113 114
      def extend_path(name)
        if name.nil? || name.empty?
115
          name = [config['bibliography']]
116
        end
117

118
        ret = []
119

120 121 122 123 124 125 126 127 128 129 130
        name.each { |file|
          # return as is if it is an absolute path
          if file.start_with?('/') && File.exists?(file)
            ret << file
          else
            p = File.join(config['source'], file)
            p << '.bib' unless File.exists?(p)
            ret << p
          end
        }
        ret
131
      end
132

133
      def reference_tag(entry)
Sylvester Keil's avatar
Sylvester Keil committed
134
        return missing_reference unless entry
135

136
        entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?
137
        reference = CiteProc.process entry.to_citeproc,
138
          :style => style, :locale => config['locale'], :format => 'html'
139

Sylvester Keil's avatar
Sylvester Keil committed
140 141 142 143
        content_tag reference_tagname, reference,
          :id => [prefix, entry.key].compact.join('-')
      end

144 145 146 147
      def style
        @style || config['style']
      end

Sylvester Keil's avatar
Sylvester Keil committed
148 149 150 151 152 153 154 155 156
      def missing_reference
        config['missing_reference']
      end

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

      def bibliography_template
157 158 159 160 161
        @bibliography_template || config['bibliography_template']
      end

      def liquid_template
        return @liquid_template if @liquid_template
162

163
        tmp = bibliography_template
164 165

        case
166
        when tmp.nil?, tmp.empty?
167 168 169 170 171
          tmp = '{{reference}}'
        when site.layouts.key?(tmp)
          tmp = site.layouts[tmp].content
        end

172
        @liquid_template = Liquid::Template.parse(tmp)
Sylvester Keil's avatar
Sylvester Keil committed
173 174
      end

175
      def bibliography_tag(entry, index)
Sylvester Keil's avatar
Sylvester Keil committed
176 177
        return missing_reference unless entry

178
        liquid_template.render({
Sylvester Keil's avatar
Sylvester Keil committed
179
          'entry' => liquidify(entry),
180 181 182 183 184 185
          'reference' => reference_tag(entry),
          'key' => entry.key,
          'type' => entry.type,
          'link' => repository_link_for(entry),
          'index' => index
        })
186 187
      end

Sylvester Keil's avatar
Sylvester Keil committed
188 189 190 191 192 193
      def liquidify(entry)
        e = {}

        e['key'] = entry.key
        e['type'] = entry.type

194 195 196 197 198 199 200
        if entry.field?(:abstract)
          tmp = entry.dup
          tmp.delete :abstract
          e['bibtex'] = tmp.to_s
        else
          e['bibtex'] = entry.to_s
        end
Sylvester Keil's avatar
Sylvester Keil committed
201 202 203 204 205 206 207 208 209

        entry.fields.each do |key, value|
          value = value.convert(*bibtex_filters) unless bibtex_filters.empty?
          e[key.to_s] = value.to_s
        end

        e
      end

210 211 212
      def generate_details?
        site.layouts.key?(File.basename(config['details_layout'], '.html'))
      end
213

214 215
      def details_file_for(entry)
        name = entry.key.to_s.dup
216

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

219 220
        [name, 'html'].join('.')
      end
221

222 223 224 225 226 227 228
      def repository_link_for(entry, base = base_url)
        url = repository[entry.key]
        return unless url

        File.join(base, url)
      end

Sylvester Keil's avatar
Sylvester Keil committed
229
      def details_link_for(entry, base = base_url)
230
        File.join(base, details_path, details_file_for(entry))
Sylvester Keil's avatar
Sylvester Keil committed
231
      end
232

Sylvester Keil's avatar
Sylvester Keil committed
233
      def base_url
234
        @base_url ||= site.config['baseurl'] || site.config['base_url'] || ''
235
      end
236

237 238 239
      def details_path
        config['details_dir']
      end
240

Sylvester Keil's avatar
Sylvester Keil committed
241
      def cite(key)
242 243 244
        context['cited'] ||= []
        context['cited'] << key

Sylvester Keil's avatar
Sylvester Keil committed
245
        if bibliography.key?(key)
246 247 248
          entry = bibliography[key]
          entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?

249
          citation = CiteProc.process entry.to_citeproc, :style => style,
Sylvester Keil's avatar
Sylvester Keil committed
250
            :locale => config['locale'], :format => 'html', :mode => :citation
251

252
          link_to "##{[prefix, entry.key].compact.join('-')}", citation.join
Sylvester Keil's avatar
Sylvester Keil committed
253
        else
254
          missing_reference
Sylvester Keil's avatar
Sylvester Keil committed
255
        end
256 257
      rescue
        "(#{key})"
Sylvester Keil's avatar
Sylvester Keil committed
258
      end
Sylvester Keil's avatar
Sylvester Keil committed
259

260
      def cite_details(key, text)
Hiren Patel's avatar
Hiren Patel committed
261
        if bibliography.key?(key)
Sylvester Keil's avatar
Sylvester Keil committed
262
          link_to details_link_for(bibliography[key]), text || config['details_link']
Hiren Patel's avatar
Hiren Patel committed
263
        else
264
          missing_reference
Hiren Patel's avatar
Hiren Patel committed
265 266
        end
      end
267

Sylvester Keil's avatar
Sylvester Keil committed
268 269 270 271 272 273
      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
274

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

Sylvester Keil's avatar
Sylvester Keil committed
277 278 279 280 281 282
        if content.nil?
          "<#{[name, attributes].flatten.compact.join(' ')}/>"
        else
          "<#{[name, attributes].flatten.compact.join(' ')}>#{content}</#{name}>"
        end
      end
283

Sylvester Keil's avatar
Sylvester Keil committed
284 285 286
      def link_to(href, content, attributes = {})
        content_tag :a, content || href, attributes.merge(:href => href)
      end
287

288 289 290 291
      def cited_references
        context && context['cited'] || []
      end

Sylvester Keil's avatar
Sylvester Keil committed
292
      def set_context_to(context)
293
        @context, @site, = context, context.registers[:site]
Sylvester Keil's avatar
Sylvester Keil committed
294 295
        config.merge!(site.config['scholar'] || {})
      end
296
    end
297

298
  end
Hiren Patel's avatar
Hiren Patel committed
299
end