jekyll-algolia 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/errors/invalid_credentials.txt +5 -6
- data/lib/errors/invalid_index_name.txt +5 -7
- data/lib/errors/missing_api_key.txt +9 -11
- data/lib/errors/missing_application_id.txt +7 -8
- data/lib/errors/missing_index_name.txt +11 -12
- data/lib/errors/no_records_found.txt +8 -14
- data/lib/errors/record_too_big.txt +16 -21
- data/lib/errors/settings_manually_edited.txt +17 -0
- data/lib/errors/unknown_application_id.txt +9 -13
- data/lib/errors/unknown_settings.txt +8 -11
- data/lib/jekyll-algolia.rb +108 -29
- data/lib/jekyll/algolia/configurator.rb +38 -44
- data/lib/jekyll/algolia/extractor.rb +2 -2
- data/lib/jekyll/algolia/file_browser.rb +91 -68
- data/lib/jekyll/algolia/indexer.rb +132 -62
- data/lib/jekyll/algolia/logger.rb +8 -7
- data/lib/jekyll/algolia/overwrites.rb +13 -0
- data/lib/jekyll/algolia/progress_bar.rb +27 -0
- data/lib/jekyll/algolia/utils.rb +52 -4
- data/lib/jekyll/algolia/version.rb +1 -1
- data/lib/jekyll/commands/algolia.rb +3 -14
- metadata +21 -4
@@ -15,45 +15,49 @@ module Jekyll
|
|
15
15
|
'nodes_to_index' => 'p',
|
16
16
|
'indexing_batch_size' => 1000,
|
17
17
|
'settings' => {
|
18
|
-
|
19
|
-
'
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
# Searchable attributes
|
19
|
+
'searchableAttributes' => %w[
|
20
|
+
title
|
21
|
+
headings
|
22
|
+
unordered(content)
|
23
|
+
collection,categories,tags
|
24
24
|
],
|
25
|
+
# Custom Ranking
|
25
26
|
'customRanking' => [
|
26
27
|
'desc(date)',
|
27
|
-
'desc(
|
28
|
-
'asc(
|
28
|
+
'desc(custom_ranking.heading)',
|
29
|
+
'asc(custom_ranking.position)'
|
29
30
|
],
|
30
|
-
'
|
31
|
-
|
32
|
-
'searchableAttributes' => %w[
|
33
|
-
title
|
34
|
-
hierarchy.lvl0
|
35
|
-
hierarchy.lvl1
|
36
|
-
hierarchy.lvl2
|
37
|
-
hierarchy.lvl3
|
38
|
-
hierarchy.lvl4
|
39
|
-
hierarchy.lvl5
|
40
|
-
unordered(content)
|
41
|
-
collection,unordered(categories),unordered(tags)
|
31
|
+
'unretrievableAttributes' => [
|
32
|
+
'custom_ranking'
|
42
33
|
],
|
43
|
-
#
|
34
|
+
# Highlight
|
44
35
|
'attributesToHighlight' => %w[
|
45
36
|
title
|
46
|
-
|
47
|
-
hierarchy.lvl1
|
48
|
-
hierarchy.lvl2
|
49
|
-
hierarchy.lvl3
|
50
|
-
hierarchy.lvl4
|
51
|
-
hierarchy.lvl5
|
37
|
+
headings
|
52
38
|
content
|
53
39
|
html
|
54
40
|
collection
|
55
41
|
categories
|
56
42
|
tags
|
43
|
+
],
|
44
|
+
'highlightPreTag' => '<em class="ais-Highlight">',
|
45
|
+
'highlightPostTag' => '</em>',
|
46
|
+
# Snippet
|
47
|
+
'attributesToSnippet' => %w[
|
48
|
+
content:55
|
49
|
+
],
|
50
|
+
'snippetEllipsisText' => '…',
|
51
|
+
# Distinct
|
52
|
+
'distinct' => true,
|
53
|
+
'attributeForDistinct' => 'url',
|
54
|
+
# Faceting
|
55
|
+
'attributesForFaceting' => %w[
|
56
|
+
type
|
57
|
+
searchable(collection)
|
58
|
+
searchable(categories)
|
59
|
+
searchable(tags)
|
60
|
+
searchable(title)
|
57
61
|
]
|
58
62
|
}
|
59
63
|
}.freeze
|
@@ -68,7 +72,6 @@ module Jekyll
|
|
68
72
|
Logger.silent { config = Jekyll.configuration } if config.nil?
|
69
73
|
|
70
74
|
@config = config
|
71
|
-
@config['exclude'] = files_excluded_from_render
|
72
75
|
|
73
76
|
@config = disable_other_plugins(@config)
|
74
77
|
|
@@ -212,23 +215,14 @@ module Jekyll
|
|
212
215
|
false
|
213
216
|
end
|
214
217
|
|
215
|
-
# Public:
|
218
|
+
# Public: Returns true if the command should always update the settings
|
216
219
|
#
|
217
|
-
#
|
218
|
-
#
|
219
|
-
def self.
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
excluded_files = site_exclude + algolia_exclude
|
224
|
-
|
225
|
-
# 404 pages are not Jekyll defaults but a convention adopted by GitHub
|
226
|
-
# pages. We don't want to index those.
|
227
|
-
# https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/
|
228
|
-
excluded_files << '404.html'
|
229
|
-
excluded_files << '404.md'
|
230
|
-
|
231
|
-
excluded_files
|
220
|
+
# When set to true, the index settings will always be updated, no matter
|
221
|
+
# if they've been modified or not
|
222
|
+
def self.force_settings?
|
223
|
+
value = get('force_settings')
|
224
|
+
return true if value == true
|
225
|
+
false
|
232
226
|
end
|
233
227
|
|
234
228
|
# Public: Disable features from other Jekyll plugins that might interfere
|
@@ -12,7 +12,7 @@ module Jekyll
|
|
12
12
|
#
|
13
13
|
# file - The Jekyll file to process
|
14
14
|
def self.run(file)
|
15
|
-
# Getting all
|
15
|
+
# Getting all nodes from the HTML input
|
16
16
|
raw_records = extract_raw_records(file.content)
|
17
17
|
# Getting file metadata
|
18
18
|
shared_metadata = FileBrowser.metadata(file)
|
@@ -47,7 +47,7 @@ module Jekyll
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Public: Extract raw records from the file, including content for each
|
50
|
-
# node
|
50
|
+
# node and its headings
|
51
51
|
#
|
52
52
|
# content - The HTML content to parse
|
53
53
|
def self.extract_raw_records(content)
|
@@ -14,46 +14,72 @@ module Jekyll
|
|
14
14
|
module FileBrowser
|
15
15
|
include Jekyll::Algolia
|
16
16
|
|
17
|
-
# Public: Check if the specified file is a static Jekyll asset
|
18
|
-
#
|
19
|
-
# file - The Jekyll file
|
20
|
-
#
|
21
|
-
# We don't index static assets (js, css, images)
|
22
|
-
def self.static_file?(file)
|
23
|
-
file.is_a?(Jekyll::StaticFile)
|
24
|
-
end
|
25
|
-
|
26
17
|
# Public: Return the absolute path of a Jekyll file
|
27
18
|
#
|
28
19
|
# file - The Jekyll file to inspect
|
29
|
-
|
30
|
-
|
31
|
-
# (pages) or as an absolute paths (posts and static assets). We make sure
|
32
|
-
# we have a consistent way of accessing it
|
33
|
-
def self.absolute_path(file)
|
34
|
-
pathname = Pathname.new(file.path)
|
20
|
+
def self.absolute_path(filepath)
|
21
|
+
pathname = Pathname.new(filepath)
|
35
22
|
return pathname.cleanpath.to_s if pathname.absolute?
|
36
23
|
|
37
|
-
File.expand_path(File.join(Configurator.get('source'),
|
24
|
+
File.expand_path(File.join(Configurator.get('source'), filepath))
|
38
25
|
end
|
39
26
|
|
40
27
|
# Public: Return the path of a Jekyll file relative to the Jekyll source
|
41
28
|
#
|
42
29
|
# file - The Jekyll file to inspect
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
30
|
+
def self.relative_path(filepath)
|
31
|
+
pathname = Pathname.new(filepath)
|
32
|
+
config_source = Configurator.get('source') || ''
|
33
|
+
jekyll_source = Pathname.new(File.expand_path(config_source))
|
34
|
+
|
35
|
+
# Removing any starting ./
|
36
|
+
if pathname.relative?
|
37
|
+
fullpath = File.expand_path(File.join(jekyll_source, pathname))
|
38
|
+
return fullpath.gsub(%r{^#{jekyll_source}/}, '')
|
39
|
+
end
|
50
40
|
|
51
|
-
jekyll_source = Pathname.new(
|
52
|
-
File.expand_path(Configurator.get('source'))
|
53
|
-
)
|
54
41
|
pathname.relative_path_from(jekyll_source).cleanpath.to_s
|
55
42
|
end
|
56
43
|
|
44
|
+
# Public: Check if the file should be indexed
|
45
|
+
#
|
46
|
+
# file - The Jekyll file
|
47
|
+
#
|
48
|
+
# There are many reasons a file should not be indexed. We need to exclude
|
49
|
+
# all the static assets, only keep the actual content.
|
50
|
+
def self.indexable?(file)
|
51
|
+
return false if static_file?(file)
|
52
|
+
return false if is_404?(file)
|
53
|
+
return false unless allowed_extension?(file)
|
54
|
+
return false if excluded_from_config?(file)
|
55
|
+
return false if excluded_from_hook?(file)
|
56
|
+
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Check if the specified file is a static Jekyll asset
|
61
|
+
#
|
62
|
+
# file - The Jekyll file
|
63
|
+
#
|
64
|
+
# We don't index static assets (js, css, images)
|
65
|
+
def self.static_file?(file)
|
66
|
+
file.is_a?(Jekyll::StaticFile)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Public: Check if the file is a 404 error page
|
70
|
+
#
|
71
|
+
# file - The Jekyll file
|
72
|
+
#
|
73
|
+
# 404 pages are not Jekyll defaults but a convention adopted by GitHub
|
74
|
+
# pages. We don't want to index those.
|
75
|
+
# Source: https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/
|
76
|
+
#
|
77
|
+
# rubocop:disable Naming/PredicateName
|
78
|
+
def self.is_404?(file)
|
79
|
+
['404.md', '404.html'].include?(File.basename(file.path))
|
80
|
+
end
|
81
|
+
# rubocop:enable Naming/PredicateName
|
82
|
+
|
57
83
|
# Public: Check if the file has one of the allowed extensions
|
58
84
|
#
|
59
85
|
# file - The Jekyll file
|
@@ -74,18 +100,13 @@ module Jekyll
|
|
74
100
|
def self.excluded_from_config?(file)
|
75
101
|
excluded_patterns = Configurator.algolia('files_to_exclude')
|
76
102
|
jekyll_source = Configurator.get('source')
|
103
|
+
path = absolute_path(file.path)
|
77
104
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
excluded_patterns.each do |pattern|
|
82
|
-
Dir.glob(pattern).each do |match|
|
83
|
-
excluded_files << File.expand_path(match)
|
84
|
-
end
|
85
|
-
end
|
105
|
+
excluded_patterns.each do |pattern|
|
106
|
+
pattern = File.expand_path(File.join(jekyll_source, pattern))
|
107
|
+
return true if File.fnmatch(pattern, path, File::FNM_PATHNAME)
|
86
108
|
end
|
87
|
-
|
88
|
-
excluded_files.include?(absolute_path(file))
|
109
|
+
false
|
89
110
|
end
|
90
111
|
|
91
112
|
# Public: Check if the file has been excluded by running a custom user
|
@@ -96,20 +117,6 @@ module Jekyll
|
|
96
117
|
Hooks.should_be_excluded?(file.path)
|
97
118
|
end
|
98
119
|
|
99
|
-
# Public: Check if the file should be indexed
|
100
|
-
#
|
101
|
-
# file - The Jekyll file
|
102
|
-
#
|
103
|
-
# There are many reasons a file should not be indexed. We need to exclude
|
104
|
-
# all the static assets, only keep the actual content.
|
105
|
-
def self.indexable?(file)
|
106
|
-
return false if static_file?(file)
|
107
|
-
return false unless allowed_extension?(file)
|
108
|
-
return false if excluded_from_hook?(file)
|
109
|
-
|
110
|
-
true
|
111
|
-
end
|
112
|
-
|
113
120
|
# Public: Return a hash of all the file metadata
|
114
121
|
#
|
115
122
|
# file - The Jekyll file
|
@@ -121,6 +128,8 @@ module Jekyll
|
|
121
128
|
raw_data = raw_data(file)
|
122
129
|
specific_data = {
|
123
130
|
collection: collection(file),
|
131
|
+
tags: tags(file),
|
132
|
+
categories: categories(file),
|
124
133
|
date: date(file),
|
125
134
|
excerpt_html: excerpt_html(file),
|
126
135
|
excerpt_text: excerpt_text(file),
|
@@ -153,6 +162,11 @@ module Jekyll
|
|
153
162
|
end
|
154
163
|
data.delete('excerpt')
|
155
164
|
|
165
|
+
# Delete other keys added by Jekyll that are not in the front-matter and
|
166
|
+
# not needed for search
|
167
|
+
data.delete('draft')
|
168
|
+
data.delete('ext')
|
169
|
+
|
156
170
|
# Convert all values to a version that can be serialized to JSON
|
157
171
|
data = Utils.jsonify(data)
|
158
172
|
|
@@ -184,30 +198,39 @@ module Jekyll
|
|
184
198
|
file.url
|
185
199
|
end
|
186
200
|
|
187
|
-
# Public: Returns
|
201
|
+
# Public: Returns the list of tags of a file, defaults to an empty array
|
188
202
|
#
|
189
203
|
# file - The Jekyll file
|
204
|
+
def self.tags(file)
|
205
|
+
file.data['tags'] || []
|
206
|
+
end
|
207
|
+
|
208
|
+
# Public: Returns the list of tags of a file, defaults to an empty array
|
190
209
|
#
|
191
|
-
#
|
192
|
-
|
193
|
-
|
210
|
+
# file - The Jekyll file
|
211
|
+
def self.categories(file)
|
212
|
+
file.data['categories'] || []
|
213
|
+
end
|
214
|
+
|
215
|
+
# Public: Returns a timestamp of the file date
|
194
216
|
#
|
195
|
-
#
|
217
|
+
# file - The Jekyll file
|
196
218
|
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
#
|
200
|
-
# while they haven't.
|
219
|
+
# Posts have their date coming from the filepath, or the front-matter.
|
220
|
+
# Pages and other collection items can only have a date set in
|
221
|
+
# front-matter.
|
201
222
|
def self.date(file)
|
202
|
-
date
|
203
|
-
|
223
|
+
# Collections get their date from .date, while pages read it from .data.
|
224
|
+
# Jekyll by default will set the date of collection to the current date,
|
225
|
+
# but we overwrote this.
|
226
|
+
date = if file.respond_to?(:date)
|
227
|
+
file.date
|
228
|
+
else
|
229
|
+
file.data['date']
|
230
|
+
end
|
204
231
|
|
205
|
-
|
206
|
-
|
207
|
-
# was nil and has been overwritten by Jekyll
|
208
|
-
return nil if date.to_i == Jekyll::Algolia.start_time.to_i
|
209
|
-
|
210
|
-
date.to_i
|
232
|
+
return nil if date.nil?
|
233
|
+
date.to_time.to_i
|
211
234
|
end
|
212
235
|
|
213
236
|
# Public: Returns the raw excerpt of a file, directly as returned by
|
@@ -224,7 +247,7 @@ module Jekyll
|
|
224
247
|
return file.data['excerpt'].to_s
|
225
248
|
end
|
226
249
|
rescue StandardError
|
227
|
-
|
250
|
+
nil
|
228
251
|
end
|
229
252
|
|
230
253
|
# Public: Returns the HTML version of the excerpt
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'algoliasearch'
|
4
|
+
require 'yaml'
|
5
|
+
require 'algolia_html_extractor'
|
4
6
|
|
5
7
|
module Jekyll
|
6
8
|
module Algolia
|
@@ -17,8 +19,16 @@ module Jekyll
|
|
17
19
|
application_id: Configurator.application_id,
|
18
20
|
api_key: Configurator.api_key
|
19
21
|
)
|
22
|
+
@index = ::Algolia::Index.new(Configurator.index_name)
|
20
23
|
|
21
24
|
set_user_agent
|
25
|
+
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: Returns the Algolia index object
|
30
|
+
def self.index
|
31
|
+
@index
|
22
32
|
end
|
23
33
|
|
24
34
|
# Public: Set the User-Agent to send to the API
|
@@ -38,33 +48,11 @@ module Jekyll
|
|
38
48
|
::Algolia.set_extra_header('User-Agent', user_agent)
|
39
49
|
end
|
40
50
|
|
41
|
-
# Public: Returns an Algolia Index object from an index name
|
42
|
-
#
|
43
|
-
# index_name - String name of the index
|
44
|
-
def self.index(index_name)
|
45
|
-
::Algolia::Index.new(index_name)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Public: Check if an index exists
|
49
|
-
#
|
50
|
-
# index_name - Name of the index
|
51
|
-
#
|
52
|
-
# Note: there is no API endpoint to do that, so we try to get the settings
|
53
|
-
# instead, which will fail if the index does not exist
|
54
|
-
def self.index?(index_name)
|
55
|
-
index(index_name).get_settings
|
56
|
-
return true
|
57
|
-
rescue StandardError
|
58
|
-
return false
|
59
|
-
end
|
60
|
-
|
61
51
|
# Public: Returns an array of all the objectIDs in the index
|
62
52
|
#
|
63
|
-
# index - Algolia Index to target
|
64
|
-
#
|
65
53
|
# The returned array is sorted. It won't have any impact on the way it is
|
66
54
|
# processed, but makes debugging easier when comparing arrays is needed.
|
67
|
-
def self.remote_object_ids
|
55
|
+
def self.remote_object_ids
|
68
56
|
list = []
|
69
57
|
Logger.verbose(
|
70
58
|
"I:Inspecting existing records in index #{index.name}..."
|
@@ -88,49 +76,22 @@ module Jekyll
|
|
88
76
|
records.map { |record| record[:objectID] }.compact.sort
|
89
77
|
end
|
90
78
|
|
91
|
-
# Public: Update settings of the index
|
92
|
-
#
|
93
|
-
# index - The Algolia Index
|
94
|
-
#
|
95
|
-
# Does nothing in dry run mode
|
96
|
-
# Settings will only be updated in the first push, and if custom settings
|
97
|
-
# are defined in _config.yml. Otherwise, they are left untouched, allowing
|
98
|
-
# users to configure them through their dashboard.
|
99
|
-
def self.update_settings(index)
|
100
|
-
has_custom_settings = !Configurator.algolia('settings').nil?
|
101
|
-
index_exists = index?(index.name)
|
102
|
-
|
103
|
-
# No need to update the settings if the index is already configured and
|
104
|
-
# the user did not specify custom settings
|
105
|
-
return if index_exists && !has_custom_settings
|
106
|
-
|
107
|
-
Logger.verbose('I:Updating settings')
|
108
|
-
return if Configurator.dry_run?
|
109
|
-
settings = Configurator.settings
|
110
|
-
begin
|
111
|
-
index.set_settings!(settings)
|
112
|
-
rescue StandardError => error
|
113
|
-
ErrorHandler.stop(error, settings: settings)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
79
|
# Public: Update records of the index
|
118
80
|
#
|
119
|
-
# index_name - The Algolia index
|
120
81
|
# old_records_ids - Ids of records to delete from the index
|
121
82
|
# new_records - Records to add to the index
|
122
83
|
#
|
123
84
|
# Note: All operations will be done in one batch, assuring an atomic
|
124
85
|
# update
|
125
86
|
# Does nothing in dry run mode
|
126
|
-
def self.update_records(
|
87
|
+
def self.update_records(old_records_ids, new_records)
|
127
88
|
# Stop if nothing to change
|
128
89
|
if old_records_ids.empty? && new_records.empty?
|
129
|
-
Logger.log('I:
|
90
|
+
Logger.log('I:Content is already up to date.')
|
130
91
|
return
|
131
92
|
end
|
132
93
|
|
133
|
-
Logger.log("I:Updating records in index #{
|
94
|
+
Logger.log("I:Updating records in index #{index.name}...")
|
134
95
|
Logger.log("I:Records to delete: #{old_records_ids.length}")
|
135
96
|
Logger.log("I:Records to add: #{new_records.length}")
|
136
97
|
return if Configurator.dry_run?
|
@@ -141,19 +102,31 @@ module Jekyll
|
|
141
102
|
operations = []
|
142
103
|
old_records_ids.each do |object_id|
|
143
104
|
operations << {
|
144
|
-
action: 'deleteObject', indexName:
|
105
|
+
action: 'deleteObject', indexName: index.name,
|
145
106
|
body: { objectID: object_id }
|
146
107
|
}
|
147
108
|
end
|
148
109
|
operations += new_records.map do |new_record|
|
149
|
-
{ action: 'addObject', indexName:
|
110
|
+
{ action: 'addObject', indexName: index.name, body: new_record }
|
150
111
|
end
|
151
112
|
|
152
113
|
# Run the batches in slices if they are too large
|
153
114
|
batch_size = Configurator.algolia('indexing_batch_size')
|
154
|
-
operations.each_slice(batch_size)
|
115
|
+
slices = operations.each_slice(batch_size).to_a
|
116
|
+
|
117
|
+
should_have_progress_bar = (slices.length > 1)
|
118
|
+
if should_have_progress_bar
|
119
|
+
progress_bar = ProgressBar.create(
|
120
|
+
total: slices.length,
|
121
|
+
format: 'Pushing records (%j%%) |%B|'
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
slices.each do |slice|
|
155
126
|
begin
|
156
127
|
::Algolia.batch!(slice)
|
128
|
+
|
129
|
+
progress_bar.increment if should_have_progress_bar
|
157
130
|
rescue StandardError => error
|
158
131
|
records = slice.map do |record|
|
159
132
|
record[:body]
|
@@ -163,6 +136,106 @@ module Jekyll
|
|
163
136
|
end
|
164
137
|
end
|
165
138
|
|
139
|
+
# Public: Get a unique settingID for the current settings
|
140
|
+
#
|
141
|
+
# The settingID is generated as a hash of the current settings. As it will
|
142
|
+
# be stored in the userData key of the resulting config, we exclude that
|
143
|
+
# key from the hashing.
|
144
|
+
def self.local_setting_id
|
145
|
+
settings = Configurator.settings
|
146
|
+
settings.delete('userData')
|
147
|
+
AlgoliaHTMLExtractor.uuid(settings)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Public: Get the settings of the remote index
|
151
|
+
#
|
152
|
+
# In case the index is not accessible, it will return nil
|
153
|
+
def self.remote_settings
|
154
|
+
index.get_settings
|
155
|
+
rescue StandardError
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
|
159
|
+
# Public: Smart update of the settings of the index
|
160
|
+
#
|
161
|
+
# This will first compare the settings about to be pushed with the
|
162
|
+
# settings already pushed. It will compare userData.settingID for that.
|
163
|
+
# If the settingID is the same, we don't push as this won't change
|
164
|
+
# anything. We will still check if the remote config seem to have been
|
165
|
+
# manually altered though, and warn the user that this is not the
|
166
|
+
# preferred way of doing so.
|
167
|
+
#
|
168
|
+
# If the settingID are not matching, it means our config is different, so
|
169
|
+
# we push it, overriding the settingID for next push.
|
170
|
+
def self.update_settings
|
171
|
+
current_remote_settings = remote_settings || {}
|
172
|
+
remote_setting_id = current_remote_settings.dig('userData', 'settingID')
|
173
|
+
|
174
|
+
settings = Configurator.settings
|
175
|
+
setting_id = local_setting_id
|
176
|
+
|
177
|
+
are_settings_forced = Configurator.force_settings?
|
178
|
+
|
179
|
+
# The config we're about to push is the same we pushed previously. We
|
180
|
+
# won't push again.
|
181
|
+
if setting_id == remote_setting_id && !are_settings_forced
|
182
|
+
Logger.log('I:Settings are already up to date.')
|
183
|
+
# Check if remote config has been changed outside of the plugin, so we
|
184
|
+
# can warn users that they should not alter their config from outside
|
185
|
+
# of the plugin.
|
186
|
+
current_remote_settings.delete('userData')
|
187
|
+
changed_keys = Utils.diff_keys(settings, current_remote_settings)
|
188
|
+
unless changed_keys.nil?
|
189
|
+
warn_of_manual_dashboard_editing(changed_keys)
|
190
|
+
end
|
191
|
+
|
192
|
+
return
|
193
|
+
end
|
194
|
+
|
195
|
+
# Settings have changed, we push them
|
196
|
+
settings['userData'] = {
|
197
|
+
'settingID' => setting_id,
|
198
|
+
'pluginVersion' => VERSION
|
199
|
+
}
|
200
|
+
|
201
|
+
Logger.log("I:Updating settings of index #{index.name}")
|
202
|
+
return if Configurator.dry_run?
|
203
|
+
set_settings(settings)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Public: Set new settings to an index
|
207
|
+
#
|
208
|
+
# Will dispatch to the error handler if it fails
|
209
|
+
# rubocop:disable Naming/AccessorMethodName
|
210
|
+
def self.set_settings(settings)
|
211
|
+
index.set_settings!(settings)
|
212
|
+
rescue StandardError => error
|
213
|
+
ErrorHandler.stop(error, settings: settings)
|
214
|
+
end
|
215
|
+
# rubocop:enable Naming/AccessorMethodName
|
216
|
+
|
217
|
+
# Public: Warn users that they have some settings manually configured in
|
218
|
+
# their dashboard
|
219
|
+
#
|
220
|
+
# When users change some settings in their dashboard, those settings might
|
221
|
+
# get overwritten by the pluging. We can't prevent that, but we can warn
|
222
|
+
# them when we detect they changed something.
|
223
|
+
def self.warn_of_manual_dashboard_editing(changed_keys)
|
224
|
+
# Transform the hash into readable YAML
|
225
|
+
yaml_lines = changed_keys
|
226
|
+
.to_yaml(indentation: 2)
|
227
|
+
.split("\n")[1..-1]
|
228
|
+
yaml_lines.map! do |line|
|
229
|
+
line = line.gsub(/^ */) { |spaces| ' ' * spaces.length }
|
230
|
+
line = line.gsub('- ', ' - ')
|
231
|
+
"W: #{line}"
|
232
|
+
end
|
233
|
+
Logger.known_message(
|
234
|
+
'settings_manually_edited',
|
235
|
+
settings: yaml_lines.join("\n")
|
236
|
+
)
|
237
|
+
end
|
238
|
+
|
166
239
|
# Public: Push all records to Algolia and configure the index
|
167
240
|
#
|
168
241
|
# records - Records to push
|
@@ -180,14 +253,11 @@ module Jekyll
|
|
180
253
|
exit 1
|
181
254
|
end
|
182
255
|
|
183
|
-
index_name = Configurator.index_name
|
184
|
-
index = index(index_name)
|
185
|
-
|
186
256
|
# Update settings
|
187
|
-
update_settings
|
257
|
+
update_settings
|
188
258
|
|
189
259
|
# Getting list of objectID in remote and locally
|
190
|
-
remote_ids = remote_object_ids
|
260
|
+
remote_ids = remote_object_ids
|
191
261
|
local_ids = local_object_ids(records)
|
192
262
|
|
193
263
|
# Getting list of what to add and what to delete
|
@@ -196,7 +266,7 @@ module Jekyll
|
|
196
266
|
new_records = records.select do |record|
|
197
267
|
new_records_ids.include?(record[:objectID])
|
198
268
|
end
|
199
|
-
update_records(
|
269
|
+
update_records(old_records_ids, new_records)
|
200
270
|
|
201
271
|
Logger.log('I:✔ Indexing complete')
|
202
272
|
end
|