pebble/devsite/plugins/generator_algolia.rb
2025-02-24 18:58:29 -08:00

236 lines
7.2 KiB
Ruby

# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'htmlentities'
require 'algoliasearch'
require 'slugize'
require 'dotenv'
require 'securerandom'
module Jekyll
class GeneratorAlgolia < Generator
# Do this last so everything else has been processed already.
priority :lowest
def initialize(_config)
Dotenv.load
end
def generate(site)
@site = site
return unless check_config?
@prefix = site.config['algolia_prefix'] || ''
@random_code = random_code
Algolia.init(application_id: site.config['algolia_app_id'],
api_key: site.config['algolia_api_key'])
@indexes = setup_indexes
generate_all
end
private
def check_config?
if @site.config['algolia_app_id'].nil? || @site.config['algolia_app_id'].empty?
Jekyll.logger.warn(
'Config Warning:',
'You did not provide a ALGOLIA_APP_ID environment variable.'
)
return false
end
if @site.config['algolia_api_key'].nil? || @site.config['algolia_api_key'].empty?
Jekyll.logger.warn(
'Config Warning:',
'You did not provide a ALGOLIA_API_KEY environment variable.'
)
return false
end
true
end
def generate_all
generate_blog_posts
generate_guides
generate_documentation
generate_none_guide_guides
generate_other
end
def random_code
SecureRandom.hex
end
def setup_indexes
indexes = {}
@site.data['search_indexes'].each do |name, properties|
index = Algolia::Index.new(@prefix + name)
unless properties['settings'].nil?
index.set_settings(properties['settings'])
end
indexes[name] = index
end
indexes
end
def generate_documentation
return if @site.data['docs'].nil?
documents = @site.data['docs'][:symbols].map do |item|
next if item[:language] == 'c_preview'
if item[:summary].nil? || item[:summary].strip.length == 0
Jekyll.logger.warn(
'Search Warning:',
"There was no summary for the symbol '#{item[:name]}' in #{item[:language]}."
)
end
{
'objectID' => item[:url],
'title' => item[:name],
'splitTitle' => item[:name].split(/(?=[A-Z])/).join(' '),
'url' => item[:url],
'summary' => item[:summary],
'kind' => item[:kind],
'language' => item[:language],
'type' => 'documentation',
'ranking' => doc_language_rank[item[:language]] * 1000,
'randomCode' => @random_code
}
end.compact
@indexes['documentation'].save_objects(documents)
end
def generate_blog_posts
documents = []
@site.posts.docs.each do | post |
# Calculate the age of the post so we can prioritise newer posts
# over older ones.
# NOTE: post.date is actually a Time object, despite its name
age = (Time.now - post.date).round
author = post.data['author']
post.get_sections.each do | section |
# Ignore sections without any contents.
if section[:contents].strip.size == 0
next
end
if section[:title].nil?
url = post.url
else
url = post.url + '#' + section[:title].slugize
end
document = {
'objectID' => url,
'title' => post.data['title'],
'sectionTitle' => section[:title],
'url' => url,
'urlDisplay' => post.url,
'author' => author,
'content' => HTMLEntities.new.decode(section[:contents]),
'posted' => post.date,
'age' => age,
'type' => 'blog post',
'randomCode' => @random_code
}
documents << document
end
end
@indexes['blog-posts'].save_objects(documents)
end
def generate_guides
documents = []
return if @site.collections['guides'].nil?
@site.collections['guides'].docs.each do | guide |
group = @site.data['guides'][guide.data['guide_group']]
unless group.nil? || group['subgroups'].nil? || guide.data['guide_subgroup'].nil?
subgroup = group.nil? ? '' : group['subgroups'][guide.data['guide_subgroup']]
end
guide.get_sections.each do | section |
url = guide.url
unless section[:title].nil?
url = url + '#' + section[:title].slugize
end
document = {
'objectID' => url,
'title' => guide.data['title'],
'sectionTitle' => section[:title],
'url' => url,
'urlDisplay' => guide.url,
'content' => HTMLEntities.new.decode(section[:contents]),
'group' => group.nil? ? '' : group['title'],
'subgroup' => subgroup.nil? ? '' : subgroup['title'],
'type' => 'guide',
'randomCode' => @random_code
}
documents << document
end
end
@indexes['guides'].save_objects(documents)
end
def generate_none_guide_guides
documents = []
gs_pages = @site.pages.select { |page| page.data['search_index'] }
gs_pages.each do |page|
page.get_sections.each do |section|
url = page.url
url = url + '#' + section[:title].slugize unless section[:title].nil?
document = {
'objectID' => url,
'title' => page.data['title'],
'sectionTitle' => section[:title],
'url' => url,
'urlDisplay' => page.url,
'content' => HTMLEntities.new.decode(section[:contents]),
'group' => page.data['search_group'],
'subgroup' => page.data['sub_group'],
'type' => 'not-guide',
'randomCode' => @random_code
}
documents << document
end
end
@indexes['guides'].save_objects(documents)
end
def generate_other
documents = @site.data['search-other'].map do |other|
{
'objectID' => other['id'],
'title' => other['title'],
'url' => other['url'],
'content' => other['description'],
'randomCode' => @random_code
}
end
@indexes['other'].save_objects(documents)
end
def doc_language_rank
{
'c' => 10,
'rockyjs' => 9,
'pebblekit_js' => 8,
'pebblekit_android' => 6,
'pebblekit_ios' => 4
}
end
end
end