Class: Jekyll::Lunr::Indexer

Inherits:
Object
  • Object
show all
Defined in:
lib/jekyll/lunr.rb

Overview

Generates a Lunr index from documents

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(site) ⇒ Indexer

Returns a new instance of Indexer.



64
65
66
# File 'lib/jekyll/lunr.rb', line 64

def initialize(site)
  @site = site
end

Instance Attribute Details

#siteObject (readonly)

Returns the value of attribute site.



62
63
64
# File 'lib/jekyll/lunr.rb', line 62

def site
  @site
end

Instance Method Details

#cleanup(data) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/jekyll/lunr.rb', line 98

def cleanup(data)
  cleaned_data = data.dup

  if (lang = lang&.to_sym)
    sieve = Stopwords::Snowball::WordSieve.new
    words = cleaned_data.split(' ').map(&:strip)

    cleaned_data = site.filter(lang: lang, words: words).join(' ')
  end

  cleaned_data
end

#dataObject

The data is the register where Lunr looks for results. TODO: Write a single data file per doc?



70
71
72
73
74
75
76
# File 'lib/jekyll/lunr.rb', line 70

def data
  @data ||= site.documents.select do |doc|
    doc.respond_to? :to_data
  end.reject do |doc|
    doc.data['sitemap'] == false
  end.map(&:to_data)
end

#data_fileObject



78
79
80
# File 'lib/jekyll/lunr.rb', line 78

def data_file
  @data_file ||= Jekyll::StaticFile.new(site, site.source, '.', 'data.json')
end

#dirObject



119
120
121
# File 'lib/jekyll/lunr.rb', line 119

def dir
  File.realpath(File.join([__dir__, '..', '..']))
end

#envObject



131
132
133
# File 'lib/jekyll/lunr.rb', line 131

def env
  @env ||= { 'NODE_PATH' => File.join(site.source, 'node_modules') }
end

#fieldsObject

Indexable fields



163
164
165
# File 'lib/jekyll/lunr.rb', line 163

def fields
  @fields ||= Set.new((site.config.dig('jekyll-lunr', 'fields') || []) + %w[title description]).freeze
end

#freeObject



167
168
169
170
# File 'lib/jekyll/lunr.rb', line 167

def free
  @data = nil
  @indexable_data = nil
end

#indexObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/jekyll/lunr.rb', line 135

def index
  Open3.popen2(env, *indexer) do |stdin, stdout, wait|
    indexable_data.each do |data|
      stdin.puts(data.transform_values do |val|
        case val
        when String then cleanup val
        else val
        end
      end.to_json)
    end
    stdin.close

    File.open(index_file.path, 'w') do |idx|
      idx.write(stdout.read)
    end

    site.static_files << index_file

    wait.value
  end
end

#index_fileObject



123
124
125
# File 'lib/jekyll/lunr.rb', line 123

def index_file
  @index_file ||= Jekyll::StaticFile.new(site, site.source, '.', 'idx.json')
end

#indexable_dataObject

Convert data to strings since Lunr can’t index objects



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/jekyll/lunr.rb', line 83

def indexable_data
  @indexable_data ||= data.map do |d|
    d.transform_values do |v|
      case v
      when Array
        v.map do |vv|
          vv.is_a?(Hash) ? vv['title'] : vv
        end.compact.join(', ')
      when Hash then v['title'] || v.values.map(&:to_s).join(', ')
      else v.to_s
      end
    end
  end
end

#indexerObject



127
128
129
# File 'lib/jekyll/lunr.rb', line 127

def indexer
  @indexer ||= ['node', File.join(dir, 'lib', 'assets', 'javascript', 'indexer.js'), lang].freeze
end

#langObject

Site lang



158
159
160
# File 'lib/jekyll/lunr.rb', line 158

def lang
  @lang ||= site.config['lang'].freeze
end

#writeObject



111
112
113
114
115
116
117
# File 'lib/jekyll/lunr.rb', line 111

def write
  File.open(data_file.path, 'w') do |df|
    df.write data.to_json
  end

  site.static_files << data_file
end