utilities.rb 4.98 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
        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

105
      def bibliography_tag(entry, index)
Sylvester Keil's avatar
Sylvester Keil committed
106 107 108 109
        return missing_reference unless entry

        bibliography_template % {
          :reference => reference_tag(entry),
110
          :key => entry.key,
111
          :type => entry.type,
112
          :index => index
Sylvester Keil's avatar
Sylvester Keil committed
113
        }
114 115
      end

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

120 121
      def details_file_for(entry)
        name = entry.key.to_s.dup
122

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

125 126
        [name, 'html'].join('.')
      end
127

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

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

136 137 138
      def details_path
        config['details_dir']
      end
139

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

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

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

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

Sylvester Keil's avatar
Sylvester Keil committed
165 166 167 168 169 170
      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
171

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

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

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

185 186 187 188
      def cited_references
        context && context['cited'] || []
      end

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

195
  end
Hiren Patel's avatar
Hiren Patel committed
196
end