Compare commits

..

No commits in common. "develop" and "1.1.4" have entirely different histories.

220 changed files with 1622 additions and 6821 deletions

4
.gitignore vendored
View File

@ -1,14 +1,10 @@
Gemfile.lock
.envrc
pkg/
coverage/
docs-dev/
gemfiles/*.lock
spec/site/_site
spec/integration/site/_site
spec/site/.jekyll-cache/
.jekyll-cache/
.DS_Store
.*.sw[a-z]

View File

@ -3,9 +3,9 @@ cache: bundler
before_script: bundle update
script: bundle exec rake test
rvm:
- 2.6.2
- 2.4.2
- 2.3.5
- 2.3.0
notifications:
email:
on_success: never

View File

@ -38,16 +38,6 @@ group :jekyll_plugins do
end
```
## Running integration tests
Integration tests will do a full jekyll run, and push data to an Algolia index,
checking that records and settings are correctly saved. It is the slowest
possible kind of tests, but also the one closest to a real implementation.
Running those tests requires a real Algolia plan. You need to define
`ALGOLIA_APPLICATION_ID`, `ALGOLIA_API_KEY` and `ALGOLIA_INDEX_NAME` (we suggest
using `direnv` for that), and then run `./scripts/test_integration`.
## Linting
Run `rake lint` to check the style of all ruby files. Run `rake

View File

@ -1,14 +1,9 @@
# frozen_string_literal: true
# Live-reload unit tests
# Launch tests whenever a file in ./lib or ./spec changes
guard :rspec, cmd: 'bundle exec rspec --color --format progress' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) do |match|
"spec/#{match[1]}_spec.rb"
end
watch(%r{^lib/jekyll/algolia/overwrites/jekyll-algolia-site\.rb$}) do
'spec/jekyll-algolia_spec.rb'
end
watch('spec/spec_helper.rb') { 'spec' }
end

View File

@ -1,9 +0,0 @@
# frozen_string_literal: true
# Live-reload integration tests
guard :rspec, cmd: 'bundle exec rspec --color --format progress' do
watch(%r{^spec/integration/.+_spec\.rb$})
watch('spec/integration/spec_helper.rb') { 'spec/integration' }
end
notification :off

View File

@ -1,4 +0,0 @@
# Maintainers list to contact for any security issue
# You can find all contributors in the GitHub interface or the git log
Tim Carry (@pixelastic)

View File

@ -1,16 +1,15 @@
# Jekyll Algolia Plugin
[![gem version][1]][16]
[![gem version][1]](https://rubygems.org/gems/jekyll-algolia)
![ruby][2]
![jekyll][3]
[![build master][4]][17]
[![build develop][6]][17]
[![coverage master][5]][18]
[![build master][4]](https://travis-ci.org/algolia/jekyll-algolia)
[![coverage master][5]](https://coveralls.io/github/algolia/jekyll-algolia?branch=master)
[![build develop][6]](https://travis-ci.org/algolia/jekyll-algolia)
[![coverage develop][7]](https://coveralls.io/github/algolia/jekyll-algolia?branch=develop)
Add fast and relevant search to your Jekyll site.
> While this plugin was created by Algolia, it is not an officially supported API client. It is possible that future major versions of Jekyll break compatibility, or require changes.
## Usage
```shell
@ -22,7 +21,7 @@ This will push the content of your Jekyll website to your Algolia index.
## Documentation
Full documentation can be found on
[https://community.algolia.com/jekyll-algolia/][20]
[https://community.algolia.com/jekyll-algolia/](https://community.algolia.com/jekyll-algolia/getting-started.html)
## Installation
@ -43,89 +42,63 @@ Once this is done, download all dependencies with `bundle install`.
## Basic configuration
You need to provide certain Algolia credentials for this plugin to _index_ your
You need to provide certain Algolia credentials for this plugin to *index* your
site.
_If you don't yet have an Algolia account, we suggest that you open a free
[Community plan here][8]. You can find more information about the Algolia plans
[in our FAQ][10]._
*If you don't yet have an Algolia account, you can open a free [Community plan
here][8]. Once signed in, you can get your
credentials from [your dashboard][9].*
Once signed in, you should get your application ID from [your dashboard][9] and
define it inside your `_config.yml` file like this:
Once you have your credentials, you should define your `application_id` and
`index_name` inside your `_config.yml` file like this:
```yaml
# _config.yml
algolia:
application_id: 'your_application_id'
index_name: 'your_index_name'
```
## Run it
Once your application ID is setup, you can run the indexing by running the
Once your credentials are setup, you can run the indexing by running the
following command:
```shell
ALGOLIA_API_KEY='your_admin_api_key' bundle exec jekyll algolia
ALGOLIA_API_KEY='{your_admin_api_key}' bundle exec jekyll algolia
```
Note that `ALGOLIA_API_KEY` should be set to your admin API key.
## More about the Community plan
The Algolia [Community plan][11] lets you host up to 10k records and perform up
to 100k add/edit/delete operations per month (search operations are free). The
plan is entirely free, with no time limit.
The Algolia [Community plan][10] lets you host up to 10k records and perform up to
100k add/edit/delete operations per month (search operations are free). The plan
is entirely free, with no time limit.
What we ask in exchange is that you display a "Search by Algolia" logo next to
your search results. Our [InstantSearch libraries][12] have a simple boolean
your search results. Our [InstantSearch libraries][11] have a simple boolean
option to toggle that on an off. If you want more flexibility, you can find
all versions of our logo [here][13].
If you need more information about the other Algolia plans, you can [check our
FAQ][10].
all versions of our logo [here][12].
# Thanks
Thanks to [Anatoliy Yastreb][14] for a [great tutorial][15] on creating Jekyll
Thanks to [Anatoliy Yastreb][13] for a [great tutorial][14] on creating Jekyll
plugins.
[1]: https://badge.fury.io/rb/jekyll-algolia.svg
[2]: https://img.shields.io/badge/ruby-%3E%3D%202.3.0-green.svg
[3]: https://img.shields.io/badge/jekyll-%3E%3D%203.6.0-green.svg
[4]: https://img.shields.io/badge/dynamic/json.svg?label=build%3Amaster&query=value&uri=https%3A%2F%2Fimg.shields.io%2Ftravis%2Falgolia%2Fjekyll-algolia.json%3Fbranch%3Dmaster
[5]: https://coveralls.io/repos/github/algolia/jekyll-algolia/badge.svg?branch=master
[5]: https://img.shields.io/badge/dynamic/json.svg?label=coverage%3Amaster&colorB=&prefix=&suffix=%25&query=$.coverage_change&uri=https%3A%2F%2Fcoveralls.io%2Fgithub%2Falgolia%2Fjekyll-algolia.json%3Fbranch%3Dmaster
[6]: https://img.shields.io/badge/dynamic/json.svg?label=build%3Adevelop&query=value&uri=https%3A%2F%2Fimg.shields.io%2Ftravis%2Falgolia%2Fjekyll-algolia.json%3Fbranch%3Ddevelop
[7]: https://coveralls.io/repos/github/algolia/jekyll-algolia/badge.svg?branch=develop
[7]: https://img.shields.io/badge/dynamic/json.svg?label=coverage%3Adevelop&colorB=&prefix=&suffix=%25&query=$.coverage_change&uri=https%3A%2F%2Fcoveralls.io%2Fgithub%2Falgolia%2Fjekyll-algolia.json%3Fbranch%3Ddevelop
[8]: #more-about-the-community-plan
[9]: https://www.algolia.com/api-keys
[10]: https://community.algolia.com/jekyll-algolia/faq.html#how-many-records-will-the-plugin-need
[11]: https://www.algolia.com/users/sign_up/hacker
[12]: https://community.algolia.com/instantsearch.js/
[13]: https://www.algolia.com/press/?section=brand-guidelines
[14]: https://github.com/ayastreb/
[15]: https://ayastreb.me/writing-a-jekyll-plugin/
[16]: https://rubygems.org/gems/jekyll-algolia
[17]: https://travis-ci.org/algolia/jekyll-algolia
[18]: https://coveralls.io/github/algolia/jekyll-algolia?branch=master
[19]: https://coveralls.io/github/algolia/jekyll-algolia?branch=develop
[20]: https://community.algolia.com/jekyll-algolia/getting-started.html
[9]: https://www.algolia.com/licensing
[10]: https://www.algolia.com/users/sign_up/hacker
[11]: https://community.algolia.com/instantsearch.js/
[12]: https://www.algolia.com/press#resources
[13]: https://github.com/ayastreb/
[14]: https://ayastreb.me/writing-a-jekyll-plugin/

130
Rakefile
View File

@ -9,14 +9,10 @@ rescue Bundler::BundlerError => e
warn 'Run `bundle install` to install missing gems'
exit e.status_code
end
require 'algoliasearch'
require 'rake'
require 'rspec/core'
require 'rspec/core/rake_task'
require 'rubocop/rake_task'
# LINT
desc 'Check files for linting issues'
require 'rubocop/rake_task'
RuboCop::RakeTask.new(:lint) do |task|
task.patterns = [
'lib/**/*.rb',
@ -29,7 +25,9 @@ RuboCop::RakeTask.new(:lint) do |task|
end
# TEST
desc 'Run unit tests'
require 'rspec/core'
require 'rspec/core/rake_task'
desc 'Run tests (with simple progress)'
RSpec::Core::RakeTask.new(:test) do |task|
task.rspec_opts = '--color --format progress'
task.pattern = [
@ -37,76 +35,35 @@ RSpec::Core::RakeTask.new(:test) do |task|
'spec/jekyll/**/*.rb'
]
end
namespace 'test' do
desc 'Run tests in all Ruby versions'
task :all_ruby_versions do
puts 'Please, run ./scripts/test_all_ruby_versions manually'
end
# Generate locally browsable coverage files
task :coverage do
ENV['COVERAGE'] = 'true'
Rake::Task['test'].execute
end
desc 'Live-reload unit tests'
task :watch do
# We specifically watch for ./lib and ./spec and not the whole dir because:
# 1. It's the only directories we are interested in
# 2. Listening to the whole parent dir might throw Guard errors if we have
# symlink
sh 'bundle exec guard --clear --watchdir lib spec'
end
# Integration tests need to run `bundle exec jekyll build/algolia`. Using
# bundle from inside a Rakefile does not seem to work, so the scripts have to
# be run manually. Each script run the needed commands to prepare the test
# site, then actually run the _run and _watch_run tasks below.
desc 'Run integration tests'
task :integration do
puts 'Please, run ./scripts/test_integration manually'
end
namespace 'integration' do
desc 'Live-reload integration tests'
task :watch do
puts 'Please, run ./scripts/test_integration_watch manually'
end
# Delete the test indices
task :_delete_indices do
Algolia.init(
application_id: ENV['ALGOLIA_APPLICATION_ID'],
api_key: ENV['ALGOLIA_API_KEY']
)
Algolia::Index.new(ENV['ALGOLIA_INDEX_NAME']).delete_index!
Algolia::Index
.new("#{ENV['ALGOLIA_INDEX_NAME']}_object_ids").delete_index!
end
# Run only the integration tests
desc ''
RSpec::Core::RakeTask.new(:_run) do |task|
task.rspec_opts = '--color --format progress'
task.pattern = [
# Check that the default build has the expected results
'spec/integration/main_spec.rb',
# Check various config and its impact on the settings
'spec/integration/settings_spec.rb',
# Check that object ids are stored in dedicated index
'spec/integration/object_ids_spec.rb'
]
end
# Live-reloading integration tests
# It will reload the tests whenever they are changed. It will not
# live-rebuild everything, you still have to run rake
# ./scripts/test_integration_prepare for that
task :_watch_run do
sh 'bundle exec guard '\
'--clear '\
'--watchdir lib spec/integration '\
'--guardfile Guardfile_integration'
end
end
desc 'Run tests (with full details)'
RSpec::Core::RakeTask.new(:test_details) do |task|
task.rspec_opts = '--color --format documentation'
task.pattern = [
'spec/*.rb',
'spec/jekyll/**/*.rb'
]
end
desc 'Run tests in all Ruby versions (with full details)'
task :test_all_ruby_versions do
puts 'Please, run ./scripts/test_all_ruby_versions manually'
end
# COVERAGE
desc 'Generate locally browsable coverage files'
task :coverage do
ENV['COVERAGE'] = 'true'
Rake::Task['test'].execute
end
# WATCH
desc 'Watch for changes in files and reload tests'
task :watch do
# We specifically watch for ./lib and ./spec and not the whole dir because:
# 1. It's the only directories we are interested in
# 2. Listening to the whole parent dir might throw Guard errors if we have
# symlink
sh 'bundle exec guard --clear --watchdir lib spec'
end
task watch: 'test:watch'
# GEM RELEASE
desc 'Release a new version of the gem'
@ -118,14 +75,14 @@ task release: %i[lint test] do
Rake::Task['release:update_master_from_develop'].invoke
end
namespace 'release' do
# Getting up to date from master
desc 'Getting up to date from master'
task :update_develop_from_master do
sh 'git checkout master --quiet'
sh 'git pull --rebase origin master --quiet'
sh 'git checkout develop --quiet'
sh 'git rebase master --quiet'
end
# Update current version
desc 'Update current version'
task :update_version do
version_file_path = 'lib/jekyll/algolia/version.rb'
require_relative version_file_path
@ -143,24 +100,15 @@ namespace 'release' do
# Commit it in git
sh "git commit -a -m 'release #{new_version}'"
# Create the git tag
last_tag = `git describe --tags --abbrev=0`.strip
changelog = `git log #{last_tag}..HEAD --format=%B`.gsub("\n\n", "\n")
tag_name = new_version
sh 'git tag '\
"-a #{tag_name} "\
"-m \"#{changelog}\""\
' 2>/dev/null'
sh "git tag #{tag_name} #{tag_name} -f -a"
sh "git tag -am 'tag v#{new_version}' #{new_version}"
end
# Build the gem
desc 'Build the gem'
task :build do
sh 'bundle install'
sh 'gem build jekyll-algolia.gemspec'
end
# Push the gem to rubygems
desc 'Push the gem to rubygems'
task :push do
# This will throw a warning because we're redefining a constant. That's ok.
load 'lib/jekyll/algolia/version.rb'
@ -169,7 +117,7 @@ namespace 'release' do
sh "rm jekyll-algolia-#{current_version}.gem"
sh "git push origin #{current_version}"
end
# Update master
desc 'Update master'
task :update_master_from_develop do
sh 'git checkout master --quiet'
sh 'git rebase develop --quiet'
@ -196,7 +144,7 @@ namespace 'docs' do
Rake::Task['docs:build'].invoke
sh 'git add ./docs'
sh "git commit -m 'Updating documentation website' || true"
sh "git commit -m 'Updating documentation website'"
sh 'git checkout master --quiet'
sh 'git rebase develop --quiet'

View File

@ -27,7 +27,6 @@ const sidebarMenu = [
items: [
{ title: 'Getting Started', url: 'getting-started.html' },
{ title: 'How it works', url: 'how-it-works.html' },
{ title: 'FAQ', url: 'faq.html' },
],
},
{
@ -43,7 +42,6 @@ const sidebarMenu = [
items: [
{ title: 'Deploying on Netlify', url: 'netlify.html' },
{ title: 'Deploying on Github Pages', url: 'github-pages.html' },
{ title: 'Themes', url: 'themes.html' },
{ title: 'Migration guide', url: 'migration-guide.html' },
],
},

View File

@ -35,7 +35,7 @@
"hasha": "3.0.0",
"http-server": "0.10.0",
"jstransformer-markdown-it": "2.0.0",
"lodash": "4.17.5",
"lodash": "4.17.4",
"markdown-it": "8.4.0",
"markdown-it-anchor": "4.0.0",
"metalsmith": "2.3.0",
@ -45,7 +45,7 @@
"metalsmith-sass": "1.4.0",
"ms-webpack": "2.0.0",
"node-sass": "4.7.2",
"nodemon": "1.18.7",
"nodemon": "1.12.5",
"postcss": "6.0.14",
"postcss-loader": "2.0.9",
"postcss-scss": "1.0.2",
@ -66,8 +66,8 @@
"webpack-hot-middleware": "2.21.0"
},
"engines": {
"node": ">=9.2.0",
"yarn": ">=1.3.2"
"node": "^9.2.0",
"yarn": "^1.3.2"
},
"renovate": {
"extends": [

0
docs-src/src/assets/fonts/algolia-brands-iconfont.eot Normal file → Executable file
View File

0
docs-src/src/assets/fonts/algolia-brands-iconfont.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 214 KiB

After

Width:  |  Height:  |  Size: 214 KiB

0
docs-src/src/assets/fonts/algolia-brands-iconfont.ttf Normal file → Executable file
View File

0
docs-src/src/assets/fonts/algolia-brands-iconfont.woff Normal file → Executable file
View File

0
docs-src/src/assets/fonts/algolia-website-iconfont.eot Normal file → Executable file
View File

0
docs-src/src/assets/fonts/algolia-website-iconfont.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

0
docs-src/src/assets/fonts/algolia-website-iconfont.ttf Normal file → Executable file
View File

View File

0
docs-src/src/assets/images/github-icon.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 848 B

After

Width:  |  Height:  |  Size: 848 B

0
docs-src/src/assets/js/activateClipboard.js Normal file → Executable file
View File

0
docs-src/src/assets/js/main.js Normal file → Executable file
View File

View File

@ -74,17 +74,11 @@ exist yet.
In that file, we'll add the following content. It's a lot of code in one go, but
don't worry, we'll explain it all right after.
_Note that for the sake of readability we will be using JavaScript features
that might not be available in all browsers (namely [const][5], [template
literals][6] and [arrow functions][7]). If you need compatibility with browsers
that do not ship those features, we recommend you use [Babel][8] to
automatically transpile your code._
```html
<!-- Including InstantSearch.js library and styling -->
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.0/dist/instantsearch.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.0/dist/instantsearch.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.0/dist/instantsearch-theme-algolia.min.css">
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@2.5.1"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.5.1/dist/instantsearch.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.5.1/dist/instantsearch-theme-algolia.min.css">
<script>
// Instanciating InstantSearch.js with Algolia credentials
@ -115,9 +109,9 @@ search.start();
### Including the InstantSearch.js library
The first lines will include the [InstantSearch.js][9] library as well as
The first lines will include the [InstantSearch.js][5] library as well as
minimal styling, directly from the jsDeliver CDN. Those files are also available
through [Yarn][10]/[NPM][11] if you need them locally.
through [Yarn][6]/[NPM][7] if you need them locally.
### Instanciating the library
@ -129,7 +123,7 @@ Both `application_id` and `index_name` should already be in your `_config.yml`
file. The `search_only_api_key` should be new, though.
Add a new entry in your `_config.yml` file, under the `algolia` namespace with
the value of your Search API Key (you can find it in your [Dashboard][12]):
the value of your Search API Key (you can find it in your [Dashboard][8]):
```yml
# _config.yml
@ -159,7 +153,7 @@ InstantSearch loads, it will replace the list with its own results.
This is what it should look like at this stage. We have a search bar, but
results are displayed in a raw JSON format. Let's work on styling this.
![Minimal InstantSearch.js styling][13]
![Minimal InstantSearch.js styling][9]
## Templating
@ -189,7 +183,7 @@ search.addWidget(
);
```
![InstantSearch.js styling][14]
![InstantSearch.js styling][10]
This looks much better already. By using a template, we managed to make the
result look close to what the initial display was. In the next section, we'll
@ -204,7 +198,7 @@ default we display it exactly as it was saved in the Algolia index: as a UNIX
timestamp.
Because our template is a JavaScript function, we can reformat data before
rendering it. Here we will use the [moment.js][15] library to format our date.
rendering it. Here we will use the [moment.js][11] library to format our date.
Using `moment.unix(hit.date).format('MMM D, YYYY');` we'll transform
`1513764761` into `Dec 20, 2017`.
@ -234,38 +228,42 @@ All HTML nodes added by InstantSearch.js come with a custom `.ais-*` class added
to them. This makes altering the styling of the elements to match your overall
theme easy to achieve.
### Headings
### Edge-case handling
With the current configuration, we will sometimes end up with results that look
irrelevant: nothing is highlighted neither in the title or the content.
This is because by default the plugin is searching not only in the content and
the title, but also in the headings (`<h1>` to `<h6>` of the page). Because we
currently only display the title and content, it make some perfectly relevant
result look odd, because nothing is highlighted.
This is because by default the plugin is searching into different fields
(including `tags`, `categories` and the parent heading hierarchy of each
paragraph). Because we chose to only display the title and content, it means that
when a match in another attribute is occurring, we have no way to visually signal
it to the user. It makes the result look irrelevant, while it is actually
relevant (but we're not explaining why).
To fix that, we'll add the highlighted headings to the display when they are
matching. We'll create a new variable called `breadcrumbs`, filled with the
highlighted headings, and add it to our template only when not empty.
We also update the url to include the `#` anchor that will point the link
directly to the closest matching heading.
One way to work around this issue is to manually tell the API in which field it
should search, by using the [restrictSearchableAttributes][12] option.
### Final code
Here is the complete new version of the `_includes/algolia.html` file.
```html
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.0/dist/instantsearch.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@2.3.3/dist/instantsearch.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.0/dist/instantsearch.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.6.0/dist/instantsearch-theme-algolia.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.3.3/dist/instantsearch.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/instantsearch.js@2.3.3/dist/instantsearch-theme-algolia.min.css">
<script>
const search = instantsearch({
appId: '{{ site.algolia.application_id }}',
apiKey: '{{ site.algolia.search_only_api_key }}',
indexName: '{{ site.algolia.index_name }}'
indexName: '{{ site.algolia.index_name }}',
searchParameters: {
restrictSearchableAttributes: [
'title',
'content'
]
}
});
const hitTemplate = function(hit) {
@ -273,25 +271,14 @@ const hitTemplate = function(hit) {
if (hit.date) {
date = moment.unix(hit.date).format('MMM D, YYYY');
}
let url = `{{ site.baseurl }}${hit.url}#${hit.anchor}`;
const url = hit.url;
const title = hit._highlightResult.title.value;
let breadcrumbs = '';
if (hit._highlightResult.headings) {
breadcrumbs = hit._highlightResult.headings.map(match => {
return `<span class="post-breadcrumb">${match.value}</span>`
}).join(' > ')
}
const content = hit._highlightResult.html.value;
return `
<div class="post-item">
<span class="post-meta">${date}</span>
<h2><a class="post-link" href="${url}">${title}</a></h2>
{{#breadcrumbs}}<a href="${url}" class="post-breadcrumbs">${breadcrumbs}</a>{{/breadcrumbs}}
<div class="post-snippet">${content}</div>
</div>
`;
@ -331,49 +318,31 @@ search.start();
font-style: normal;
text-decoration: underline;
}
.post-breadcrumbs {
color: #424242;
display: block;
}
.post-breadcrumb {
font-size: 18px;
color: #424242;
}
.post-breadcrumb .ais-Highlight {
font-weight: bold;
font-style: normal;
}
.post-snippet .ais-Highlight {
color: #2a7ae2;
font-style: normal;
font-weight: bold;
}
.post-snippet img {
display: none;
}
</style>
```
## Final result
You can check the [final result live here][16], and have a look at all the code
from the [GitHub repository][17].
You can check the [final result live here][13], and have a look at all the code from
the [GitHub repository][14].
[1]: https://github.com/jekyll/minima
[2]: ./getting-started.html
[3]: ./assets/images/minima-search.gif
[4]: https://raw.githubusercontent.com/jekyll/minima/master/_layouts/home.html
[5]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
[6]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
[7]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
[8]: https://babeljs.io/
[9]: https://community.algolia.com/instantsearch.js/
[10]: https://yarnpkg.com/en/package/instantsearch.js
[11]: https://www.npmjs.com/package/instantsearch.js
[12]: https://www.algolia.com/api-keys
[13]: ./assets/images/instantsearch-nostyling.png
[14]: ./assets/images/instantsearch-styling.png
[15]: https://momentjs.com/docs/
[16]: https://community.algolia.com/jekyll-algolia-example/
[17]: https://github.com/algolia/jekyll-algolia-example
[5]: https://community.algolia.com/instantsearch.js/
[6]: https://yarnpkg.com/en/package/instantsearch.js
[7]: https://www.npmjs.com/package/instantsearch.js
[8]: https://www.algolia.com/api-keys
[9]: ./assets/images/instantsearch-nostyling.png
[10]: ./assets/images/instantsearch-styling.png
[11]: https://momentjs.com/docs/
[12]: https://www.algolia.com/doc/api-reference/api-parameters/restrictSearchableAttributes/
[13]: https://community.algolia.com/jekyll-algolia-example/
[14]: https://github.com/algolia/jekyll-algolia-example

View File

@ -17,9 +17,11 @@ Here is the list of command line options you can pass to the `jekyll algolia` co
| Flag | Description |
| ---- | ----- |
| `--config ./_config.yml` | You can here specify the config file to use. Default is `_config.yml` |
| `--future` | With this flag, the command will also index posts with a future date |
| `--limit_posts 10` | Limits the number of posts to parse and index |
| `--drafts` | Index drafts in the `_drafts` folder as well |
| `--dry-run` or `-n` | Do a dry run, do not actually push anything to your index |
| `--verbose` | Display more information about what is going to be indexed |
| `--force-settings` | Force update of the index settings |
## Environment variables
@ -30,9 +32,10 @@ to overwrite those values.
key | value
---------------------- | ----------------------
ALGOLIA_APPLICATION_ID | Your Application ID, available in [your dashboard](https://www.algolia.com/api-keys).
ALGOLIA_INDEX_NAME | Your Index name, any string will work
ALGOLIA_API_KEY | Your Admin API Key, available in [your dashboard](https://www.algolia.com/api-keys).
ALGOLIA_APPLICATION_ID | `your_application_id`
ALGOLIA_INDEX_NAME | `your_index_name`
ALGOLIA_API_KEY | `your_api_key`
## `_algolia_api_key` file

View File

@ -1,100 +0,0 @@
---
title: Frequently Asked Questions
layout: content-with-menu.pug
---
# Frequently Asked Questions
## How many records will the plugin need?
The plugin will not create an exact mapping of `1 page = 1 record`. Instead, it
will split all pages into smaller chunks, and each chunk will be saved as a
record. Splitting into small chunks is key to offer the best relevance of
results.
The default chunking mechanism is to create one chunk per paragraph of content.
So, for a blog post that is made up of 10 paragraphs of text, it will create 10
records.
Estimating the number of records you will need can be tricky as it depends on
both the number of pages you have, and on the average length of them. Some
configuration options (such as [nodes_to_index][1]) can also influence the final
result.
The following table should give you a ballpark estimate of what to expect. All
calculations were done with an average of **15 paragraphs per page**, on a
timeline of **one year**.
| update frequency | # of new pages | # of records | Algolia plan |
| --------------------------- | -------------- | ------------ | -------------- |
| ~1 new page per week | ~50 | ~750 | [Community][2] |
| ~1 new page per day | ~400 | ~6.000 | [Community][3] |
| ~2 new pages per day | ~700 | ~10.500 | [Essential][4] |
| ~1 new page per hour | ~8800 | ~132.000 | [Essential][5] |
| ~1 new page every 5 minutes | ~105.000 | ~1.575.000 | [Plus][6] |
| More? | More? | More? | [Business][7] |
## One of my records is too big. What can I do?
If you get an error about one of your records being too big, be sure to update
the plugin to the latest version. We keep improving the plugin with ways of
making the records smaller.
If you're still having an error, you should check the `.json` log file that has
been created in your source directory. This will contain the content of the
record that has been rejected. It might give you hints about what went wrong.
A common cause for this issue often lies in the page HTML. Maybe the HTML is
malformed (a tag is not closed for example), or instead of several small
paragraphs there is only one large paragraph. This can cause the parser to take
the whole page content (instead of small chunks of it) to create the records.
If you don't find where the issue is coming from, feel free to open a [GitHub
issue][8] with a copy of the log file and we'll be happy to help you.
## How can I tweak the relevance ranking?
The plugin default configuration will rank results based on their textual
relevance. You can adapt the ranking to fit your needs by using a
combination of front-matter and Algolia index settings.
For example, if you know some of your blog posts are popular, you might want to
give them a boost in their ranking. To do so, add a `popular: true` entry to the
front-matter of such posts. Any custom key added to a front-matter is
automatically pushed to their corresponding records.
Then, you would have to edit your `_config.yml` file to pass a custom
`settings.customRanking` value. The `customRanking` is one of the way ranking
can be configured in an Algolia index and follows a tie-breaking algorithm. You
can find more information about the way it works either in the [official
documentation][9] or in [this video][10].
The default `customRanking` used by the plugin is [defined here][11] and use the
date, weight of the header and position in the page by default. You can
overwrite it to also take the `popular` flag into account like:
```yml
algolia:
settings:
customRanking:
- desc(popular)
- desc(date)
- desc(custom_ranking.heading)
- asc(custom_ranking.position)
```
This will rank popular posts matching your keywords before other posts. You can
use either boolean or numeric values for the `customRanking`.
[1]: options.html#nodes-to-index
[2]: https://www.algolia.com/pricing
[3]: https://www.algolia.com/pricing
[4]: https://www.algolia.com/pricing
[5]: https://www.algolia.com/pricing
[6]: https://www.algolia.com/pricing
[7]: https://www.algolia.com/pricing
[8]: https://github.com/algolia/jekyll-algolia/issues
[9]: https://community.algolia.com/jekyll-algolia/options.html#settings
[10]: https://www.youtube.com/watch?v=H6crAohtUBw
[11]:
https://github.com/algolia/jekyll-algolia/blob/develop/lib/jekyll/algolia/configurator.rb#L27-L30

View File

@ -10,8 +10,6 @@ layout: content-with-menu.pug
`jekyll-algolia` is a Jekyll plugin that lets you push all your content in an
Algolia index.
> While this plugin was created by Algolia, it is not an officially supported API client. It is possible that future major versions of Jekyll break compatibility, or require changes.
## Requirements
You'll need:
@ -58,7 +56,7 @@ Once you have your credentials, you should define your `application_id` and
algolia:
application_id: your_application_id
index_name: jekyll # You can replace that with whatever name you want
index_name: your_index_name
```
## Usage
@ -67,7 +65,7 @@ Once your credentials are setup, you can run the indexing by running the
following command:
```shell
ALGOLIA_API_KEY='your_admin_api_key' bundle exec jekyll algolia
ALGOLIA_API_KEY='{your_admin_api_key}' bundle exec jekyll algolia
```
Note that `ALGOLIA_API_KEY` should be set to your admin API key. This key has
@ -100,7 +98,7 @@ theme.
[2]: https://www.ruby-lang.org/en/
[3]: http://bundler.io/
[4]: https://www.algolia.com/users/sign_up/hacker
[5]: https://www.algolia.com/api-keys
[5]: https://www.algolia.com/licensing
[6]: ./assets/images/getting-started.gif
[7]: ./commandline.html#algolia-api-key-file
[8]: https://github.com/rvm/rubygems-bundler

View File

@ -30,11 +30,11 @@ your GitHub Pages is done.
Here are the steps to follow to setup your Travis account for your project:
- Go to [travis-ci.org][5] and open an account
- Click on your avatar and "Profile"
- Click on your avatar and "Accounts"
- Find your GitHub repository in the list and activate it
_You should also uncheck the "Build pull request updates" in the options.
This will avoid re-indexing your data every time you receive a pull request._
This will avoid re-indexing your date every time you receive a pull request._
![Travis configuration](./assets/images/travis-config.png)
@ -50,8 +50,6 @@ keeping track of the configuration easier.
# This file should be at the root of your project
language: ruby
cache: bundler
before_install:
- gem install bundler
script:
- bundle exec jekyll algolia
branches:
@ -70,16 +68,6 @@ You might have to edit the `branches.only` value to either `master` or
`gh-pages`, depending on which branch is configured to be deployed in your
GitHub Pages configuration.
### Ignoring vendors
Travis bundles all gems in the `vendor` directory on its servers, which Jekyll
will mistakenly read. This will likely make the process fail. To avoid this,
add `vendor` to the `exclude` list in your `_config.yml` file.
```yml
exclude: [vendor]
```
## Adding the API Key
The plugin will need your Admin API key to push data. Because you don't want to

View File

@ -67,21 +67,20 @@ end
## `before_indexing_each`
This hook will be called on every single record before indexing them. It gives
you a way to edit the record before pushing it. You can use this hook to add,
edit or delete keys from the record. If the hook returns `nil`, the record will
not be indexed.
This hook will be called on every single record before indexing them. It gives you
a way to edit the record before pushing it. You can use this hook to add, edit
or delete keys from the record. If the hook returns `nil`, the
record will not be indexed.
The hook will receive three arguments: `record`, `node` and `context`. `record`
is the hash of the record, ready to be pushed to Algolia. `node` is
a [Nokogiri][5] representation of the HTML node the record was extracted from
(as specified in [nodes_to_index][6]). `context` gives more information about
the whole indexing process (check the following table for more details).
The hook will receive two arguments: `record` and `node`. `record` is the hash
of the record, ready to be pushed to Algolia. `node` is a [Nokogiri][5]
representation of the HTML node the record was extracted from (as specified in
[nodes_to_index][6].
| Key | Value |
| ---- | ---- |
| Signature | `before_indexing_each(record, node, context)` |
| Arguments | <ul><li>`record`: A hash of the record that will be pushed</li><li>`node`: A [Nokogiri][7] representation of the HTML node used to extract the content</li><li>`context`: More information about the whole website. <ul><li>`context.data`: Any data defined in the `_data` folder</li><li>`context.config`: Settings defined in `_config.yml`</li><li>`data.collections`: Custom collections and posts</li></ul></li></ul> |
| Signature | `before_indexing_each(record, node)` |
| Arguments | <ul><li>`record`: A hash of the record that will be pushed</li><li>`node`: A [Nokogiri][7] representation of the HTML node it was extracted from</li></ul> |
| Expected returns | <ul><li>A hash of the record to be indexed</li><li>`nil` if the record should not be indexed</li></ul> |
### Example
@ -90,9 +89,9 @@ the whole indexing process (check the following table for more details).
module Jekyll
module Algolia
module Hooks
def self.before_indexing_each(record, node, context)
def self.before_indexing_each(record, node)
# Do not index deprecation warnings
return nil if node.matches?('.deprecation-notice')
return nil if node.attr('class') =~ 'deprecation-notice'
# Add my name as an author to each record
record[:author] = 'Myself'
@ -105,22 +104,20 @@ end
## `before_indexing_all`
This hook is similar to [before_index_each][8], but instead of being called
This hook is very similar to [before_index_each][8], but instead of being called
on every record, it is called only once, on the full list of record, right
before pushing them.
It will be called with two arguments: `records` will be the full list of records
to be pushed, and `context` will contain more information about the current
indexing (check the following table for more details). The method expects a list
of records to be returned.
It will be called with one argument, `records`, being the full list of records
to be pushed, and expects a list of records to be returned.
You can use this hook to add, edit or delete complete records from the list,
knowing the full context of what is going to be pushed.
| Key | Value |
| ---- | ---- |
| Signature | `before_indexing_all(records, context)` |
| Arguments | <ul><li>`records`: An array of hashes representing the records that are going to be pushed</li><li>`context`: More information about the whole website. <ul><li>`context.data`: Any data defined in the `_data` folder</li><li>`context.config`: Settings defined in `_config.yml`</li><li>`data.collections`: Custom collections and posts</li></ul></li></ul> |
| Signature | `before_indexing_all(records)` |
| Arguments | <ul><li>`records`: An array of hashes representing the records that are going to be pushed</li></ul> |
| Expected returns | <ul><li>An array of hashes to be pushed as records</li></ul> |
### Example
@ -129,7 +126,7 @@ knowing the full context of what is going to be pushed.
module Jekyll
module Algolia
module Hooks
def self.before_indexing_all(records, context)
def self.before_indexing_all(records)
# Add a tags array to each record
records.each do |record|
record[:tags] = []
@ -146,12 +143,11 @@ module Jekyll
end
```
[1]: ./options.html
[2]: https://jekyllrb.com/docs/plugins/#installing-a-plugin
[3]: ./options.html#extensions-to-index
[4]: ./options.html#files-to-exclude
[5]: http://www.nokogiri.org
[6]: ./options.html#nodes-to-index
[7]: https://github.com/sparklemotion/nokogiri/wiki/Cheat-sheet
[7]: http://www.nokogiri.org
[8]: hooks.html#hook-before-indexing-each

View File

@ -6,8 +6,8 @@ layout: content-with-menu.pug
# How does this work?
This page will give you a bit more insight about how the internals of the plugin
are working. This should give you more context to better understand the options
you can configure.
are working. This should give you more context to better understand the various
options you can configure.
## Extracting data
@ -28,6 +28,9 @@ Here is an example of what a record looks like:
"title": "New experimental version of Hacker News Search built with Algolia",
"type": "post",
"url": "/2015/01/12/try-new-experimental-version-hn-search.html",
"draft": false,
"layout": "post",
"ext": ".md",
"date": 1421017200,
"excerpt_html": "<p>Exactly a year ago, we began to power […]</p>",
"excerpt_text": "Exactly a year ago, we began to power […]",
@ -35,12 +38,14 @@ Here is an example of what a record looks like:
"html": "<p>We've learned a lot from your comments […]</p>",
"content": "We've learned a lot from your comments […]",
"headings": [
"Applying more UI best practices",
"Focus on readability"
],
"tag_name": "p",
"hierarchy": {
"lvl0": null,
"lvl1": "Applying more UI best practices",
"lvl2": "Focus on readability",
},
"anchor": "focus-on-readability",
"custom_ranking": {
"weight": {
"position": 8,
"heading": 70
}
@ -50,37 +55,30 @@ Here is an example of what a record looks like:
Each record created that way will contain a mix of shared data and specific
data. Shared data is the metadata of the page it was extracted from (`title`,
`slug`, `url`, `tags`, etc, as well as any custom field added to the
front-matter). Specific data is the paragraph content and, if applicable, the
list of parent headings (based on the `<h1>` and `<h6>` of the page).
front-matter). Specific data is the paragraph content, and information
about its position in the page (where its situated in the hierarchy of headings
in the page).
Using the [distinct setting][1] of the Algolia API, the best matching
Using the [distinct setting][1] of the Algolia API, only the best matching
paragraph of each page is returned for a specific query. This greatly improves
the perceived relevance of the search results as you can highlight specifically
the part that was matching.
Also note that the response you'll get from the API might be enriched with
[\_highlightResult][2] and [\_snippetResult][3] keys. Those keys are
automatically added when performing a search and are not part of the saved
record.
## Pushing data
The plugin tries to be smart by using as less operations as possible, to be
mindful of your Algolia quota. Whenever you run `jekyll algolia`, records
mindful of your Algolia quota. Whenever you run `jekyll algolia`, only records
that changed since your last push will be updated.
This is made possible because each record is attributed a unique `objectID`,
computed as a hash of the actual content of the record. Whenever the content of
the record changes, its `objectID` will change as well. This allows us to
compare what is available in your index and what is about to be
pushed, to update what actually changed.
the record changes, its `objectID` will change as well. This allows us to compare
what is current available in your index and what is about to be pushed, to only
update what actually changed.
Previous outdated records will be deleted, and new updated records will be added
instead. All those operations are grouped into a batch call, making sure that
the changes are done atomically: your index will never be in an inconsistent
state where records are partially updated.
state where records are only partially updated.
[1]: https://www.algolia.com/doc/guides/ranking/distinct/?language=ruby#distinct-to-index-large-records
[2]: https://www.algolia.com/doc/api-reference/api-methods/search/?language=ruby#method-response-_highlightresult
[3]: https://www.algolia.com/doc/api-reference/api-methods/search/?language=ruby#method-response-_snippetresult

View File

@ -17,7 +17,7 @@ section.footer-new-cta.footer-new.h300.pos-rel
.button-holder.h200.p-r-large
.spacer16.hidden-md.hidden-sm
span.inline.pos-rel
a.btn.btn-static-primary.btn-static-shadow-dark(href='https://www.algolia.com/users/sign_up/hacker')
a.btn.btn-static-primary.btn-static-shadow-dark(href='https://algolia.com/users/sign_up')
| Get Started
i.icon.icon-arrow-right.color-bunting.m-l-small

View File

@ -86,6 +86,9 @@ Here is an example of a record extracted by the plugin:
"title": "New experimental version of Hacker News Search built with Algolia",
"type": "post",
"url": "/2015/01/12/try-new-experimental-version-hn-search.html",
"draft": false,
"layout": "post",
"ext": ".md",
"date": 1421017200,
"excerpt_html": "<p>Exactly a year ago, we began to power […]</p>",
"excerpt_text": "Exactly a year ago, we began to power […]",
@ -93,12 +96,14 @@ Here is an example of a record extracted by the plugin:
"html": "<p>We've learned a lot from your comments […]</p>",
"content": "We've learned a lot from your comments […]",
"headings": [
"Applying more UI best practices",
"Focus on readability"
],
"tag_name": "p",
"hierarchy": {
"lvl0": null,
"lvl1": "Applying more UI best practices",
"lvl2": "Focus on readability",
},
"anchor": "focus-on-readability",
"custom_ranking": {
"weight": {
"position": 8,
"heading": 70
}

View File

@ -26,21 +26,16 @@ you might want to update the value like this:
```yml
algolia:
# Also index AsciiDoc and Textile files
extensions_to_index:
- html
- md
- adoc
- textile
extensions_to_index: 'html,md,adoc,textile'
```
## `files_to_exclude`
This option lets you define a list of source files you don't want to index.
This option lets you define a blacklist of source files you don't want to index.
By default it will exclude the `index.html` and `index.md` files found at the
root. Those files are usually not containing much text (landing pages) or
containing redundant text (latest blog articles) so they are not included by
default.
By default it will exclude all the `index.html` and `index.md` files. Those
files are usually not containing much text (landing pages) or containing
redundant text (latest blog articles) so they are not included by default.
If you want to index those files, you should set the value to an empty array.
@ -51,7 +46,7 @@ algolia:
```
If you want to exclude more files, you should add them to the array. Note that
you can use glob patterns (`*` and `**`) to exclude several files at once.
you can use glob patterns to exclude several files at once.
```yml
algolia:
@ -62,7 +57,6 @@ algolia:
- excluded-file.html
- _posts/2017-01-20-date-to-forget.md
- subdirectory/*.html
- **/*.tmp.html
```
_Note that some files (pagination pages, static assets, etc) will **always** be
@ -106,17 +100,7 @@ algolia:
```
Settings defined here will take precedence over any setting you manually defined
through the [Algolia dashboard][5] UI, though. If you'd like this not to happen
at all, and only take the dashboard settings in account, pass `false` to the
settings configuration.
```yml
algolia:
settings: false
```
We suggest users to at least run with the default settings once, so that the default
relevance settings are set, which you can override via the dashboard after.
through the [Algolia dashboard][5] UI, though.
## `indexing_batch_size`
@ -136,24 +120,6 @@ algolia:
indexing_batch_size: 500
```
## `max_record_size`
**This is an advanced option. It has no effect on Community plans.**
If you're using a paid Algolia plan, you can push records that weight up to 20Kb
(as opposed to 10Kb with the free Community plan). This option allows you to
adjust the maximum size of one record (in bytes).
```yml
algolia:
# Recommended setting for paid plans
max_record_size: 20000
```
_Note that if you push a record that is larger than your allowed limit,
the push will be rejected by the API. This might result in incomplete data being
uploaded._
[1]: ./how-it-works.html
[2]: http://www.methods.co.nz/asciidoc/

View File

@ -127,7 +127,11 @@ $offset-height: 64px;
li {
line-height: 26px;
} } }
&:before {
content: '-';
float: left;
margin-right: 6px;
color: $logan; } } } }
.content {
position: relative;

0
docs-src/src/stylesheets/vendors/bootstrap/_alerts.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_badges.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_breadcrumbs.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_button-groups.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_buttons.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_carousel.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_close.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_code.scss vendored Normal file → Executable file
View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/_dropdowns.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_forms.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_glyphicons.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_grid.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_input-groups.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_jumbotron.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_labels.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_list-group.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_media.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_mixins.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_modals.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_navbar.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_navs.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_normalize.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_pager.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_pagination.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_panels.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_popovers.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_print.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_progress-bars.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_responsive-embed.scss vendored Normal file → Executable file
View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/_scaffolding.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_tables.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_theme.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_thumbnails.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_tooltip.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_type.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_utilities.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_variables.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/_wells.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_alerts.scss vendored Normal file → Executable file
View File

View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_buttons.scss vendored Normal file → Executable file
View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_clearfix.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_forms.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_gradients.scss vendored Normal file → Executable file
View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_grid.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_hide-text.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_image.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_labels.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_list-group.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_nav-divider.scss vendored Normal file → Executable file
View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_opacity.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_pagination.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_panels.scss vendored Normal file → Executable file
View File

View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_resize.scss vendored Normal file → Executable file
View File

View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_size.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_tab-focus.scss vendored Normal file → Executable file
View File

0
docs-src/src/stylesheets/vendors/bootstrap/mixins/_table-row.scss vendored Normal file → Executable file
View File

View File

View File

Some files were not shown because too many files have changed in this diff Show More