utilities.rb 6.44 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
      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
35
36
37

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

41
        argv = arguments.split(/(\B-[cfqpts]|\B--(?:cited|file|query|prefix|text|style|))/)
42
43
44

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

46
      def bibtex_options
47
48
49
50
51
        config['bibtex_options'] ||= {}
      end

      def bibtex_filters
        config['bibtex_filters'] ||= []
52
      end
53

54
55
56
      def bibtex_path
        @bibtex_path ||= extend_path(bibtex_file)
      end
57

58
      def bibliography
59
60
61
62
63
64
        unless @bibliography
          @bibliography = BibTeX.open(bibtex_path, bibtex_options)
          @bibliography.replace_strings if replace_strings?
        end

        @bibliography
65
66
      end

67
      def entries
68
        b = bibliography[query || config['query']]
69
70

        unless config['sort_by'] == 'none'
71
          b = b.sort_by { |e| e[config['sort_by']].to_s }
72
73
          b.reverse! if config['order'] =~ /^(desc|reverse)/i
        end
74

75
76
        b
      end
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
      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

98
99
100
101
      def replace_strings?
        config['replace_strings']
      end

102
103
104
105
      def cited_only?
        !!@cited
      end

106
107
108
109
      def extend_path(name)
        if name.nil? || name.empty?
          name = config['bibliography']
        end
110

111
112
        # return as is if it is an absolute path
        return name if name.start_with?('/') && File.exists?(name)
113

114
115
116
117
        p = File.join(config['source'], name)
        p << '.bib' unless File.exists?(p)
        p
      end
118

119
      def reference_tag(entry)
Sylvester Keil's avatar
Sylvester Keil committed
120
        return missing_reference unless entry
121

122
        entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?
123
        reference = CiteProc.process entry.to_citeproc,
124
          :style => style, :locale => config['locale'], :format => 'html'
125

Sylvester Keil's avatar
Sylvester Keil committed
126
127
128
129
        content_tag reference_tagname, reference,
          :id => [prefix, entry.key].compact.join('-')
      end

130
131
132
133
      def style
        @style || config['style']
      end

Sylvester Keil's avatar
Sylvester Keil committed
134
135
136
137
138
139
140
141
142
      def missing_reference
        config['missing_reference']
      end

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

      def bibliography_template
143
144
145
146
147
148
149
150
151
152
153
154
        return @bibliography_template if @bibliography_template

        tmp = config['bibliography_template'] || '{{reference}}'

        case
        when tmp.nil?
          tmp = '{{reference}}'
        when site.layouts.key?(tmp)
          tmp = site.layouts[tmp].content
        end

        @bibliography_template = Liquid::Template.parse(tmp)
Sylvester Keil's avatar
Sylvester Keil committed
155
156
      end

157
      def bibliography_tag(entry, index)
Sylvester Keil's avatar
Sylvester Keil committed
158
159
        return missing_reference unless entry

160
161
162
163
164
165
166
167
        bibliography_template.render({
          'entry' => entry,
          'reference' => reference_tag(entry),
          'key' => entry.key,
          'type' => entry.type,
          'link' => repository_link_for(entry),
          'index' => index
        })
168
169
      end

170
171
172
      def generate_details?
        site.layouts.key?(File.basename(config['details_layout'], '.html'))
      end
173

174
175
      def details_file_for(entry)
        name = entry.key.to_s.dup
176

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

179
180
        [name, 'html'].join('.')
      end
181

182
183
184
185
186
187
188
      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
189
      def details_link_for(entry, base = base_url)
190
        File.join(base, details_path, details_file_for(entry))
Sylvester Keil's avatar
Sylvester Keil committed
191
      end
192

Sylvester Keil's avatar
Sylvester Keil committed
193
      def base_url
194
        @base_url ||= site.config['baseurl'] || site.config['base_url'] || ''
195
      end
196

197
198
199
      def details_path
        config['details_dir']
      end
200

Sylvester Keil's avatar
Sylvester Keil committed
201
      def cite(key)
202
203
204
        context['cited'] ||= []
        context['cited'] << key

Sylvester Keil's avatar
Sylvester Keil committed
205
        if bibliography.key?(key)
206
207
208
          entry = bibliography[key]
          entry = entry.convert(*bibtex_filters) unless bibtex_filters.empty?

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

212
          link_to "##{[prefix, entry.key].compact.join('-')}", citation.join
Sylvester Keil's avatar
Sylvester Keil committed
213
        else
214
          missing_reference
Sylvester Keil's avatar
Sylvester Keil committed
215
        end
216
217
      rescue
        "(#{key})"
Sylvester Keil's avatar
Sylvester Keil committed
218
      end
Sylvester Keil's avatar
Sylvester Keil committed
219

220
      def cite_details(key, text)
Hiren Patel's avatar
Hiren Patel committed
221
        if bibliography.key?(key)
Sylvester Keil's avatar
Sylvester Keil committed
222
          link_to details_link_for(bibliography[key]), text || config['details_link']
Hiren Patel's avatar
Hiren Patel committed
223
        else
224
          missing_reference
Hiren Patel's avatar
Hiren Patel committed
225
226
        end
      end
227

Sylvester Keil's avatar
Sylvester Keil committed
228
229
230
231
232
233
      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
234

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

Sylvester Keil's avatar
Sylvester Keil committed
237
238
239
240
241
242
        if content.nil?
          "<#{[name, attributes].flatten.compact.join(' ')}/>"
        else
          "<#{[name, attributes].flatten.compact.join(' ')}>#{content}</#{name}>"
        end
      end
243

Sylvester Keil's avatar
Sylvester Keil committed
244
245
246
      def link_to(href, content, attributes = {})
        content_tag :a, content || href, attributes.merge(:href => href)
      end
247

248
249
250
251
      def cited_references
        context && context['cited'] || []
      end

Sylvester Keil's avatar
Sylvester Keil committed
252
      def set_context_to(context)
253
        @context, @site, = context, context.registers[:site]
Sylvester Keil's avatar
Sylvester Keil committed
254
255
        config.merge!(site.config['scholar'] || {})
      end
256
    end
257

258
  end
Hiren Patel's avatar
Hiren Patel committed
259
end