algoliasearch-jekyll 0.9.1 → 1.0.0.beta.pre.1
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/.travis.yml +3 -4
- data/CONTRIBUTING.md +8 -1
- data/Gemfile +4 -5
- data/README.md +318 -11
- data/Rakefile +7 -12
- data/algoliasearch-jekyll.gemspec +66 -62
- data/gemfiles/jekyll_v2.gemfile +3 -3
- data/gemfiles/jekyll_v3.gemfile +4 -4
- data/gemfiles/jekyll_v3_1_3.gemfile +24 -0
- data/gemfiles/jekyll_v3_1_6.gemfile +24 -0
- data/lib/algoliasearch-jekyll.rb +1 -3
- data/lib/credential_checker.rb +2 -1
- data/lib/error_handler.rb +6 -0
- data/lib/push.rb +81 -19
- data/lib/record_extractor.rb +120 -140
- data/lib/utils.rb +13 -0
- data/lib/version.rb +1 -1
- data/scripts/release +13 -12
- data/scripts/test_v3 +1 -1
- data/scripts/watch +4 -0
- data/spec/error_handler_spec.rb +17 -0
- data/spec/fixtures/jekyll_version_2/404.html +8 -0
- data/spec/fixtures/jekyll_version_2/404.md +9 -0
- data/spec/fixtures/jekyll_version_2/_my-collection/collection-item.md +3 -0
- data/spec/fixtures/jekyll_version_2/_posts/2015-07-02-test-post.md +1 -1
- data/spec/fixtures/jekyll_version_2/about.md +3 -0
- data/spec/fixtures/jekyll_version_2/front_matter.md +15 -0
- data/spec/fixtures/jekyll_version_2/index.html +3 -1
- data/spec/fixtures/jekyll_version_2/only-divs.md +15 -0
- data/spec/fixtures/jekyll_version_2/only-paragraphs.md +15 -0
- data/spec/fixtures/jekyll_version_3/404.html +8 -0
- data/spec/fixtures/jekyll_version_3/404.md +9 -0
- data/spec/fixtures/jekyll_version_3/_config.yml +1 -1
- data/spec/fixtures/jekyll_version_3/_my-collection/collection-item.md +3 -0
- data/spec/fixtures/jekyll_version_3/_posts/2015-07-02-test-post.md +1 -1
- data/spec/fixtures/jekyll_version_3/about.md +3 -0
- data/spec/fixtures/jekyll_version_3/front_matter.md +15 -0
- data/spec/fixtures/jekyll_version_3/index.html +4 -1
- data/spec/fixtures/jekyll_version_3/only-divs.md +15 -0
- data/spec/fixtures/jekyll_version_3/only-paragraphs.md +15 -0
- data/spec/push_spec.rb +211 -8
- data/spec/record_extractor_spec.rb +296 -358
- data/spec/spec_helper.rb +32 -11
- data/txt/record_too_big +19 -0
- metadata +40 -51
- data/scripts/watch +0 -1
data/lib/utils.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Generic util helpers
|
2
|
+
class AlgoliaSearchUtils
|
3
|
+
# Check the current Jekyll version
|
4
|
+
def self.restrict_jekyll_version(more_than: nil, less_than: nil)
|
5
|
+
jekyll_version = Gem::Version.new(Jekyll::VERSION)
|
6
|
+
minimum_version = Gem::Version.new(more_than)
|
7
|
+
maximum_version = Gem::Version.new(less_than)
|
8
|
+
|
9
|
+
return false if !more_than.nil? && jekyll_version < minimum_version
|
10
|
+
return false if !less_than.nil? && jekyll_version > maximum_version
|
11
|
+
true
|
12
|
+
end
|
13
|
+
end
|
data/lib/version.rb
CHANGED
data/scripts/release
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
git
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
# Stop if any command fails
|
4
|
+
set -e
|
5
|
+
|
6
|
+
git checkout master
|
7
|
+
git pull
|
8
|
+
|
9
|
+
git rebase develop
|
10
|
+
bundle install
|
11
|
+
appraisal install
|
12
|
+
rake release
|
13
|
+
|
14
|
+
git checkout develop
|
15
|
+
git rebase master
|
data/scripts/test_v3
CHANGED
data/scripts/watch
ADDED
data/spec/error_handler_spec.rb
CHANGED
@@ -121,6 +121,23 @@ describe(AlgoliaSearchErrorHandler) do
|
|
121
121
|
expect(actual).to eq('check_key_acl_to_tmp_index')
|
122
122
|
end
|
123
123
|
|
124
|
+
it 'should warn about big records' do
|
125
|
+
# Given
|
126
|
+
parsed = {
|
127
|
+
'http_error' => 400,
|
128
|
+
'json' => {
|
129
|
+
'message' => 'Record is too big size=220062 bytes'
|
130
|
+
}
|
131
|
+
}
|
132
|
+
allow(@error_handler).to receive(:parse_algolia_error).and_return(parsed)
|
133
|
+
|
134
|
+
# When
|
135
|
+
actual = @error_handler.readable_algolia_error('error')
|
136
|
+
|
137
|
+
# Then
|
138
|
+
expect(actual).to eq('record_too_big')
|
139
|
+
end
|
140
|
+
|
124
141
|
it 'should return false if no nice message found' do
|
125
142
|
# Given
|
126
143
|
parsed = false
|
@@ -0,0 +1,8 @@
|
|
1
|
+
---
|
2
|
+
title: 404 Not Found
|
3
|
+
---
|
4
|
+
|
5
|
+
This is a 404.html error page. [GitHub pages](https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/)
|
6
|
+
suggested that it should be a `.md` file, but the Hyde theme uses a `.html`, so we handle it as well.
|
7
|
+
|
8
|
+
It should not be indexed.
|
@@ -3,7 +3,9 @@ layout: default
|
|
3
3
|
title: Home
|
4
4
|
---
|
5
5
|
|
6
|
-
This default index page is used to display the
|
6
|
+
This default index page is usually used to display the list of posts, or briefly explain the product.
|
7
|
+
|
8
|
+
I feel that it should not be indexed.
|
7
9
|
|
8
10
|
{% for post in paginator.posts %}
|
9
11
|
<a href="{{ site.baseurl }}{{ post.url }}">
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
title: Only divs
|
3
|
+
---
|
4
|
+
|
5
|
+
<div>This is the first paragraph</div>
|
6
|
+
|
7
|
+
<div>This is the second paragraph</div>
|
8
|
+
|
9
|
+
<div>This is the third paragraph</div>
|
10
|
+
|
11
|
+
<div>This is the fourth paragraph</div>
|
12
|
+
|
13
|
+
<div>This is the fifth paragraph</div>
|
14
|
+
|
15
|
+
<div>This is the last paragraph</div>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
---
|
2
|
+
title: 404 Not Found
|
3
|
+
---
|
4
|
+
|
5
|
+
This is a 404.html error page. [GitHub pages](https://help.github.com/articles/creating-a-custom-404-page-for-your-github-pages-site/)
|
6
|
+
suggested that it should be a `.md` file, but the Hyde theme uses a `.html`, so we handle it as well.
|
7
|
+
|
8
|
+
It should not be indexed.
|
@@ -3,7 +3,9 @@ layout: default
|
|
3
3
|
title: Home
|
4
4
|
---
|
5
5
|
|
6
|
-
This default index page is used to display the
|
6
|
+
This default index page is usually used to display the list of posts, or briefly explain the product.
|
7
|
+
|
8
|
+
I feel that it should not be indexed.
|
7
9
|
|
8
10
|
{% for post in paginator.posts %}
|
9
11
|
<a href="{{ site.baseurl }}{{ post.url }}">
|
@@ -11,3 +13,4 @@ This default index page is used to display the paginated posts
|
|
11
13
|
</a>
|
12
14
|
{{ post.content }}
|
13
15
|
{% endfor %}
|
16
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
title: Only divs
|
3
|
+
---
|
4
|
+
|
5
|
+
<div>This is the first paragraph</div>
|
6
|
+
|
7
|
+
<div>This is the second paragraph</div>
|
8
|
+
|
9
|
+
<div>This is the third paragraph</div>
|
10
|
+
|
11
|
+
<div>This is the fourth paragraph</div>
|
12
|
+
|
13
|
+
<div>This is the fifth paragraph</div>
|
14
|
+
|
15
|
+
<div>This is the last paragraph</div>
|
data/spec/push_spec.rb
CHANGED
@@ -11,6 +11,9 @@ describe(AlgoliaSearchJekyllPush) do
|
|
11
11
|
let(:document_file) { site.file_by_name('collection-item.md') }
|
12
12
|
let(:html_document_file) { site.file_by_name('collection-item.html') }
|
13
13
|
let(:pagination_page) { site.file_by_name('page2/index.html') }
|
14
|
+
let(:err_404) { site.file_by_name('404.md') }
|
15
|
+
let(:err_404_html) { site.file_by_name('404.html') }
|
16
|
+
let(:homepage) { site.file_by_name('index.html') }
|
14
17
|
let(:items) do
|
15
18
|
[{
|
16
19
|
name: 'foo',
|
@@ -21,6 +24,12 @@ describe(AlgoliaSearchJekyllPush) do
|
|
21
24
|
}]
|
22
25
|
end
|
23
26
|
|
27
|
+
before(:each) do
|
28
|
+
allow(Jekyll.logger).to receive(:info)
|
29
|
+
allow(Jekyll.logger).to receive(:warn)
|
30
|
+
allow(Jekyll.logger).to receive(:error)
|
31
|
+
end
|
32
|
+
|
24
33
|
describe 'init_options' do
|
25
34
|
it 'sets options and config' do
|
26
35
|
# Given
|
@@ -37,6 +46,35 @@ describe(AlgoliaSearchJekyllPush) do
|
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
49
|
+
describe 'lazy_update?' do
|
50
|
+
it 'should return false by default' do
|
51
|
+
# Given
|
52
|
+
push.init_options(nil, {}, {})
|
53
|
+
|
54
|
+
# When
|
55
|
+
actual = push.lazy_update?
|
56
|
+
|
57
|
+
# Then
|
58
|
+
expect(actual).to eq false
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should return true if such an option is set in the config' do
|
62
|
+
# Given
|
63
|
+
config = {
|
64
|
+
'algolia' => {
|
65
|
+
'lazy_update' => true
|
66
|
+
}
|
67
|
+
}
|
68
|
+
push.init_options(nil, {}, config)
|
69
|
+
|
70
|
+
# When
|
71
|
+
actual = push.lazy_update?
|
72
|
+
|
73
|
+
# Then
|
74
|
+
expect(actual).to eq true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
40
78
|
describe 'indexable?' do
|
41
79
|
it 'exclude StaticFiles' do
|
42
80
|
expect(push.indexable?(static_file)).to eq false
|
@@ -65,6 +103,18 @@ describe(AlgoliaSearchJekyllPush) do
|
|
65
103
|
it 'does not index pagination pages' do
|
66
104
|
expect(push.indexable?(pagination_page)).to eq false
|
67
105
|
end
|
106
|
+
|
107
|
+
it 'does not index 404 pages (in markdown)' do
|
108
|
+
expect(push.indexable?(err_404)).to eq false
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'does not index 404 pages (in html)' do
|
112
|
+
expect(push.indexable?(err_404_html)).to eq false
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'does not index homepage' do
|
116
|
+
expect(push.indexable?(homepage)).to eq false
|
117
|
+
end
|
68
118
|
end
|
69
119
|
|
70
120
|
describe 'excluded_files?' do
|
@@ -147,7 +197,6 @@ describe(AlgoliaSearchJekyllPush) do
|
|
147
197
|
@error_handler_double = double('Error Handler double').as_null_object
|
148
198
|
push.init_options(nil, {}, {})
|
149
199
|
allow(@index_double).to receive(:set_settings).and_raise
|
150
|
-
allow(Jekyll.logger).to receive(:error)
|
151
200
|
end
|
152
201
|
|
153
202
|
it 'stops if API throw an error' do
|
@@ -269,6 +318,53 @@ describe(AlgoliaSearchJekyllPush) do
|
|
269
318
|
end
|
270
319
|
|
271
320
|
describe 'push' do
|
321
|
+
before(:each) do
|
322
|
+
allow_any_instance_of(AlgoliaSearchCredentialChecker)
|
323
|
+
.to receive(:assert_valid)
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'should do a lazy update if such is configured' do
|
327
|
+
# Given
|
328
|
+
allow(push).to receive(:lazy_update?).and_return(true)
|
329
|
+
allow(push).to receive(:lazy_update)
|
330
|
+
push.init_options(nil, {}, {})
|
331
|
+
items = ['foo']
|
332
|
+
|
333
|
+
# When
|
334
|
+
push.push(items)
|
335
|
+
|
336
|
+
# Then
|
337
|
+
expect(push).to have_received(:lazy_update).with(items)
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'should do a greedy update if such is configured' do
|
341
|
+
# Given
|
342
|
+
allow(push).to receive(:greedy_update?).and_return(true)
|
343
|
+
allow(push).to receive(:greedy_update)
|
344
|
+
push.init_options(nil, {}, {})
|
345
|
+
items = ['foo']
|
346
|
+
|
347
|
+
# When
|
348
|
+
push.push(items)
|
349
|
+
|
350
|
+
# Then
|
351
|
+
expect(push).to have_received(:greedy_update).with(items)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
describe 'batch_add_items' do
|
356
|
+
it 'should display an error if `add_objects!` failed' do
|
357
|
+
# Given
|
358
|
+
index = double('Algolia Index').as_null_object
|
359
|
+
allow(index).to receive(:add_objects!).and_raise
|
360
|
+
|
361
|
+
# When / Then
|
362
|
+
expect(-> { push.batch_add_items(items, index) })
|
363
|
+
.to raise_error SystemExit
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
describe 'greedy_update' do
|
272
368
|
let(:index_double) { double('Algolia Index').as_null_object }
|
273
369
|
let(:config) do
|
274
370
|
{
|
@@ -280,21 +376,19 @@ describe(AlgoliaSearchJekyllPush) do
|
|
280
376
|
|
281
377
|
before(:each) do
|
282
378
|
push.init_options(nil, {}, config)
|
283
|
-
# Mock all calls to not send anything
|
284
379
|
allow_any_instance_of(AlgoliaSearchCredentialChecker)
|
285
380
|
.to receive(:assert_valid)
|
286
381
|
allow(Algolia).to receive(:set_extra_header)
|
287
382
|
allow(Algolia).to receive(:init)
|
288
383
|
allow(Algolia).to receive(:move_index)
|
289
384
|
allow(Algolia::Index).to receive(:new).and_return(index_double)
|
290
|
-
allow(Jekyll.logger).to receive(:info)
|
291
385
|
end
|
292
386
|
|
293
387
|
it 'should create a temporary index' do
|
294
388
|
# Given
|
295
389
|
|
296
390
|
# When
|
297
|
-
push.
|
391
|
+
push.greedy_update(items)
|
298
392
|
|
299
393
|
# Then
|
300
394
|
expect(Algolia::Index).to have_received(:new).with('INDEXNAME_tmp')
|
@@ -330,12 +424,121 @@ describe(AlgoliaSearchJekyllPush) do
|
|
330
424
|
# Then
|
331
425
|
expect(Jekyll.logger).to have_received(:info).with(/of 2 items/i)
|
332
426
|
end
|
427
|
+
end
|
428
|
+
|
429
|
+
describe 'lazy_update' do
|
430
|
+
let(:items) do
|
431
|
+
[
|
432
|
+
{ objectID: 'foo' },
|
433
|
+
{ objectID: 'baz' }
|
434
|
+
]
|
435
|
+
end
|
436
|
+
let(:remote) { %w(foo bar) }
|
437
|
+
let(:local) { %w(foo baz) }
|
438
|
+
let(:index) { double.as_null_object }
|
333
439
|
|
334
|
-
|
335
|
-
|
440
|
+
describe 'remote_ids' do
|
441
|
+
it 'should call browse on the index with the attributesToRetrieve ' do
|
442
|
+
# Given
|
443
|
+
index = double.as_null_object
|
444
|
+
|
445
|
+
# Then
|
446
|
+
push.remote_ids(index)
|
447
|
+
|
448
|
+
# Then
|
449
|
+
expect(index).to have_received(:browse)
|
450
|
+
end
|
451
|
+
|
452
|
+
it 'should return an array of all objectID returned by browse' do
|
453
|
+
# Given
|
454
|
+
index = double.as_null_object
|
455
|
+
hit1 = { 'objectID' => 'foo' }
|
456
|
+
hit2 = { 'objectID' => 'bar' }
|
457
|
+
allow(index).to receive(:browse).and_yield(hit1).and_yield(hit2)
|
458
|
+
|
459
|
+
# Then
|
460
|
+
actual = push.remote_ids(index)
|
461
|
+
|
462
|
+
# Then
|
463
|
+
expect(actual).to eq %w(foo bar)
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
describe 'delete_remote_not_in_local' do
|
468
|
+
it 'calls delete_objects! with the array of items to delete' do
|
469
|
+
# Given
|
470
|
+
|
471
|
+
# When
|
472
|
+
push.delete_remote_not_in_local(index, local, remote)
|
473
|
+
|
474
|
+
# Then
|
475
|
+
expect(index).to have_received(:delete_objects!).with(['bar'])
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'displays the number of items deleted' do
|
479
|
+
# Given
|
480
|
+
|
481
|
+
# When
|
482
|
+
push.delete_remote_not_in_local(index, local, remote)
|
483
|
+
|
484
|
+
# Then
|
485
|
+
expect(Jekyll.logger).to have_received(:info).with('Deleting 1 items')
|
486
|
+
end
|
336
487
|
|
337
|
-
|
338
|
-
|
488
|
+
it 'should do not do an API call if there is nothing to delete' do
|
489
|
+
# Given
|
490
|
+
input = %w(foo bar)
|
491
|
+
|
492
|
+
# When
|
493
|
+
push.delete_remote_not_in_local(index, input, input)
|
494
|
+
|
495
|
+
# Then
|
496
|
+
expect(index).not_to have_received(:delete_objects!)
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
describe 'add_local_not_in_remote' do
|
501
|
+
it 'should push all local items not yet in remote' do
|
502
|
+
# Given
|
503
|
+
allow(push).to receive(:batch_add_items)
|
504
|
+
|
505
|
+
# When
|
506
|
+
push.add_local_not_in_remote(index, items, local, remote)
|
507
|
+
|
508
|
+
# Then
|
509
|
+
expected = [{ objectID: 'baz' }]
|
510
|
+
expect(push).to have_received(:batch_add_items).with(expected, index)
|
511
|
+
end
|
512
|
+
|
513
|
+
it 'should warn about pushing 0 records' do
|
514
|
+
# Given
|
515
|
+
input = %w(foo bar)
|
516
|
+
|
517
|
+
# When
|
518
|
+
push.add_local_not_in_remote(index, items, input, input)
|
519
|
+
|
520
|
+
# Then
|
521
|
+
expect(Jekyll.logger)
|
522
|
+
.to have_received(:info).with('Adding 0 items')
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
it 'should delete items from remote and push new ones' do
|
527
|
+
# Given
|
528
|
+
allow(push).to receive(:create_index).and_return(index)
|
529
|
+
allow(push).to receive(:remote_ids).and_return(remote)
|
530
|
+
allow(push).to receive(:delete_remote_not_in_local)
|
531
|
+
allow(push).to receive(:add_local_not_in_remote)
|
532
|
+
push.init_options(nil, {}, {})
|
533
|
+
|
534
|
+
# When
|
535
|
+
push.lazy_update(items)
|
536
|
+
|
537
|
+
# Then
|
538
|
+
expect(push).to have_received(:delete_remote_not_in_local)
|
539
|
+
.with(index, local, remote)
|
540
|
+
expect(push).to have_received(:add_local_not_in_remote)
|
541
|
+
.with(index, items, local, remote)
|
339
542
|
end
|
340
543
|
end
|
341
544
|
end
|