algoliasearch-jekyll 0.9.1 → 1.0.0.beta.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|