utilities.rb 5.14 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
43 44 45 46 47
        config['bibtex_options'] ||= {}
      end

      def bibtex_filters
        config['bibtex_filters'] ||= []
48
      end
49

50 51 52
      def bibtex_path
        @bibtex_path ||= extend_path(bibtex_file)
      end
53

54 55
      def bibliography
        @bibliography ||= BibTeX.open(bibtex_path, bibtex_options)
56 57
      end

58
      def entries
59
        b = bibliography[query || config['query']]
60 61

        unless config['sort_by'] == 'none'
62
          b = b.sort_by { |e| e[config['sort_by']].to_s }
63 64
          b.reverse! if config['order'] =~ /^(desc|reverse)/i
        end
65

66 67
        b
      end
68

69 70 71 72
      def cited_only?
        !!@cited
      end

73 74 75 76
      def extend_path(name)
        if name.nil? || name.empty?
          name = config['bibliography']
        end
77

78 79
        # return as is if it is an absolute path
        return name if name.start_with?('/') && File.exists?(name)
80

81 82 83 84
        p = File.join(config['source'], name)
        p << '.bib' unless File.exists?(p)
        p
      end
85

86
      def reference_tag(entry)
Sylvester Keil's avatar
Sylvester Keil committed
87
        return missing_reference unless entry
88

89
        entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?
90 91 92
        reference = CiteProc.process entry.to_citeproc,
          :style => config['style'], :locale => config['locale'], :format => 'html'

Sylvester Keil's avatar
Sylvester Keil committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
        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

109
      def bibliography_tag(entry, index)
Sylvester Keil's avatar
Sylvester Keil committed
110 111 112 113
        return missing_reference unless entry

        bibliography_template % {
          :reference => reference_tag(entry),
114
          :key => entry.key,
115
          :type => entry.type,
116
          :index => index
Sylvester Keil's avatar
Sylvester Keil committed
117
        }
118 119
      end

120 121 122
      def generate_details?
        site.layouts.key?(File.basename(config['details_layout'], '.html'))
      end
123

124 125
      def details_file_for(entry)
        name = entry.key.to_s.dup
126

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

129 130
        [name, 'html'].join('.')
      end
131

Sylvester Keil's avatar
Sylvester Keil committed
132
      def details_link_for(entry, base = base_url)
133
        File.join(base, details_path, details_file_for(entry))
Sylvester Keil's avatar
Sylvester Keil committed
134
      end
135

Sylvester Keil's avatar
Sylvester Keil committed
136
      def base_url
137
        @base_url ||= site.config['baseurl'] || site.config['base_url'] || ''
138
      end
139

140 141 142
      def details_path
        config['details_dir']
      end
143

Sylvester Keil's avatar
Sylvester Keil committed
144
      def cite(key)
145 146 147
        context['cited'] ||= []
        context['cited'] << key

Sylvester Keil's avatar
Sylvester Keil committed
148
        if bibliography.key?(key)
149 150 151
          entry = bibliography[key]
          entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?

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

155
          link_to "##{[prefix, entry.key].compact.join('-')}", citation.join
Sylvester Keil's avatar
Sylvester Keil committed
156
        else
157
          missing_reference
Sylvester Keil's avatar
Sylvester Keil committed
158
        end
159 160
      rescue
        "(#{key})"
Sylvester Keil's avatar
Sylvester Keil committed
161
      end
Sylvester Keil's avatar
Sylvester Keil committed
162

163
      def cite_details(key, text)
Hiren Patel's avatar
Hiren Patel committed
164
        if bibliography.key?(key)
Sylvester Keil's avatar
Sylvester Keil committed
165
          link_to details_link_for(bibliography[key]), text || config['details_link']
Hiren Patel's avatar
Hiren Patel committed
166
        else
167
          missing_reference
Hiren Patel's avatar
Hiren Patel committed
168 169
        end
      end
170

Sylvester Keil's avatar
Sylvester Keil committed
171 172 173 174 175 176
      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
177

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

Sylvester Keil's avatar
Sylvester Keil committed
180 181 182 183 184 185
        if content.nil?
          "<#{[name, attributes].flatten.compact.join(' ')}/>"
        else
          "<#{[name, attributes].flatten.compact.join(' ')}>#{content}</#{name}>"
        end
      end
186

Sylvester Keil's avatar
Sylvester Keil committed
187 188 189
      def link_to(href, content, attributes = {})
        content_tag :a, content || href, attributes.merge(:href => href)
      end
190

191 192 193 194
      def cited_references
        context && context['cited'] || []
      end

Sylvester Keil's avatar
Sylvester Keil committed
195
      def set_context_to(context)
196
        @context, @site, = context, context.registers[:site]
Sylvester Keil's avatar
Sylvester Keil committed
197 198
        config.merge!(site.config['scholar'] || {})
      end
199
    end
200

201
  end
Hiren Patel's avatar
Hiren Patel committed
202
end