1
0
Fork 0

Merge branch 'master' into doc/update_content

This commit is contained in:
Sylvain Pace 2018-08-30 16:38:46 +02:00
commit 756aff5866
47 changed files with 16226 additions and 573 deletions

2
.gitignore vendored
View file

@ -6,6 +6,4 @@ dist/
npm-debug.log*
yarn-error.log
dist-es5-module/
yarn.lock
tmp
docs/build/

View file

@ -57,7 +57,9 @@ them with auto-reload.
- `yarn docs:build` will build the docs website in `./docs/dist`.
- `yarn docs:serve` will do the same, but with live-reload enabled
- `yarn docs:deploy` will deploy the doc website
- `yarn docs:deploy` will deploy the doc website manually
Refer to `./docs/README.md` for more information
## Release

1
docs/.eslintignore Normal file
View file

@ -0,0 +1 @@
!.*.js

15
docs/.prettierrc.js Normal file
View file

@ -0,0 +1,15 @@
/* eslint-disable import/no-commonjs */
module.exports = {
overrides: [
{
files: '*.md',
options: {
parser: 'markdown',
printWidth: 80,
proseWrap: 'always',
singleQuote: true,
trailingComma: 'es5',
},
},
],
};

36
docs/.remarkrc.js Normal file
View file

@ -0,0 +1,36 @@
/* eslint-disable import/no-commonjs */
const remarkMode = process.env.REMARK_MODE;
/**
* Linting config.
* Check the following links for the list of all rules:
* - https://github.com/remarkjs/remark-lint/tree/master/packages/remark-preset-lint-consistent
* - https://github.com/remarkjs/remark-lint/tree/master/packages/remark-preset-lint-recommended
* - https://github.com/remarkjs/remark-lint/tree/master/packages/remark-preset-lint-markdown-style-guide
**/
const lintConfig = {
plugins: [
'frontmatter',
'remark-preset-lint-consistent',
'remark-preset-lint-recommended',
'preset-lint-markdown-style-guide',
// Following rules are configured to fit what prettier does
'lint-no-trailing-spaces', // No trailing spaces
['lint-emphasis-marker', '_'], // Italic with _, bold with **
['lint-list-item-spacing', false], // No need to add lines between list items
['lint-list-item-indent', 'space'], // Indent list items with one space
['lint-maximum-heading-length', 80], // Warn on heading that can be too long
['lint-maximum-line-length', 80], // Warn on lines that are too long
],
};
const fixConfig = {
plugins: {
frontmatter: true, // Frontmatter is needed to it does not choke on it
'reference-links': true, // Convert links to reference table at bottom of file
},
};
const config = remarkMode === 'fix' ? fixConfig : lintConfig;
exports.plugins = config.plugins;
exports.settings = config.settings;

209
docs/.textlint.terms.json Normal file
View file

@ -0,0 +1,209 @@
[
"3D",
"API",
"Airbnb",
"Ajax",
"Algolia",
"Android",
"BrowserStack",
"Browsersync",
"CSS",
"CodePen",
"CodeSandbox",
"Codecov",
"DocSearch",
"ECMAScript",
"ESLint",
"EditorConfig",
"GIF",
"GitHub",
"GraphQL",
"HTML",
"HTTPS",
"ID",
"InstantSearch",
"IoT",
"I/O",
"JPEG",
"JavaScript",
"JetBrains",
"LinkedIn",
"Lodash",
"MIME",
"MacBook",
"Markdown",
"OK",
"OpenType",
"PDF",
"PNG",
"PaaS",
"SaaS",
"Sass",
"SemVer",
"TypeScript",
"URL",
"UglifyJS",
"WebStorm",
"WordPress",
"YouTube",
"advancedSyntax",
"allowCompressionOfIntegerArray",
"allowTyposOnNumericTokens",
"alternativesAsExact",
"analyticsTags",
"aroundLatLngViaIP",
"aroundLatLng",
"aroundPrecision",
"aroundRadius",
"aroundRadius",
"attributeForDistinct",
"attributesForFaceting",
"attributesToHighlight",
"attributesToRetrieve",
"attributesToSnippet",
"camelCaseAttributes",
"clickAnalytics",
"customRanking",
"decompoundedAttributes",
"disableExactOnAttributes",
"disablePrefixOnAttributes",
"disableTypoToleranceOnAttributes",
"disableTypoToleranceOnWords",
"enableRules",
"exactOnSingleWordQuery",
"e-commerce",
"facetFilters",
"facetingAfterDistinct",
"getRankingInfo",
"highlightPostTag",
"highlightPreTag",
"hitsPerPage",
"iOS",
"ignorePlurals",
"insideBoundingBox",
"insidePolygon",
"jQuery",
"maxFacetHits",
"maxValuesPerFacet",
"minProximity",
"minWordSizefor1Typo",
"minWordSizefor2Typos",
"minimumAroundRadius",
"npm",
"numericAttributesForFiltering",
"numericFilters",
"open source",
"optionalFilters",
"optionalWords",
"pagehitsPerPagepagination",
"paginationLimitedTo",
"percentileComputation",
"queryType",
"removeStopWords",
"removeWordsIfNoResults",
"replaceSynonymsInHighlight",
"responseFields",
"restrictHighlightAndSnippetArrays",
"restrictSearchableAttributes",
"ruleContexts",
"searchableAttributes",
"searchableAttributes",
"separatorsToIndex",
"snippetEllipsisText",
"sortFacetValuesBy",
"sumOrFiltersScores",
"tagFilters",
"typoTolerance",
"unretrievableAttributes",
["3-D", "3D"],
["Aloglia", "Algolia"],
["CLI tool(s?)", "command-line tool$1"],
["HTTP[ /]2(?:\\.0)?", "HTTP/2"],
["I-O", "I/O"],
["JSDocs?", "JSDoc"],
["Mac ?OS", "macOS"],
["Nodejs", "Node.js"],
["OS X", "macOS"],
["React[ .]js", "React"],
["SauceLabs", "Sauce Labs"],
["StackOverflow", "Stack Overflow"],
["an URL", "a URL"],
["auto[- ]complete", "autocomplete"],
["auto[- ]fixing", "autofixing"],
["auto[- ]fix", "autofix"],
["auto[- ]format", "autoformat"],
["a npm", "an npm"],
["backwards compatible", "backward compatible"],
["back[- ]end(\\w*)", "backend$1"],
["bug[- ]fix(es?)", "bugfix$1"],
["build system(s?)", "build tool$1"],
["built ?in", "built-in"],
["check[- ]box(es?)", "checkbox$1"],
["client ?side", "client-side"],
["code-?review(s?)", "code review$1"],
["code-?splitting", "code splitting"],
["code[- ]base(es?)", "codebase$1"],
["command ?line", "command-line"],
["co[- ]locate(d?)", "colocate$1"],
["css-?in-?js", "CSS in JS"],
["datas", "data"],
["ecommerce", "e-commerce"],
["end ?to ?end", "end-to-end"],
["end-?user(s?)", "end user$1"],
["end[- ]point(s?)", "endpoint$1"],
["environemnt(s?)", "environment$1"],
["error ?prone", "error-prone"],
["e commerce", "e-commerce"],
["e[- ]mail(s?)", "email$1"],
["falsey", "falsy"],
["feedbacks", "feedback"],
["file-?type(s?)", "file type$1"],
["file[- ]name(s?)", "filename$1"],
["front[- ]end(\\w*)", "frontend$1"],
["he or she", "they"],
["he/she", "they"],
["higher ?order", "higher-order"],
["host[- ]name(s?)", "hostname$1"],
["hot[- ]key(s?)", "hotkey$1"],
["id(s?)", "ID$1"],
["informations", "information"],
["key[/ ]?value", "key-value"],
["life[- ]cycle", "lifecycle"],
["life[- ]stream(s?)", "lifestream$1"],
["lock[- ]file(s?)", "lockfile$1"],
["mark-up", "markup"],
["meta[- ]data", "metadata"],
["name[- ]space(s?)", "namespace$1"],
["one URLs", "one URL"],
["opensource([\\.,]?)", "open source$1"],
["open-source([\\.,]?)", "open source$1"],
["pacakge(s?)", "package$1"],
["pre[- ]condition(s?)", "precondition$1"],
["pre[- ]defined", "predefined"],
["pre[- ]release(s?)", "prerelease$1"],
["regexp?(s?)", "regular expression$1"],
["repo\\b", "repository"],
["run[- ]time", "runtime"],
["screen[- ]shot(s?)", "screenshot$1"],
["screen[- ]?snap(s?)", "screenshot$1"],
["server ?side", "server-side"],
["slave(s?)", "replica$1"],
["smartphone(s?)", "mobile phone$1"],
["source-?map(s?)", "source map$1"],
["styled ?components", "styled-components"],
["style-?guide(s?)", "style guide$1"],
["style-?sheet(s?)", "style sheet$1"],
["sub[- ]class((?:es|ing)?)", "subclass$1"],
["sub[- ]tree(s?)", "subtree$1"],
["tilda", "tilde"],
["time[- ]stamp(s?)", "timestamp$1"],
["touch[- ]screen(s?)", "touchscreen$1"],
["tree-?shaking", "tree shaking"],
["user-?base", "user base"],
["user[- ]name(s?)", "username$1"],
["walk[- ]through", "walkthrough"],
["web-?page(s?)", "web page$1"],
["white[- ]space", "whitespace"],
["wild[- ]card(s?)", "wildcard$1"],
["wi[- ]?fi", "Wi-Fi"]
]

22
docs/.textlintrc.js Normal file
View file

@ -0,0 +1,22 @@
/* eslint-disable import/no-commonjs */
module.exports = {
rules: {
alex: {
allow: ['color', 'hook', 'host-hostess', 'itch'],
},
'common-misspellings': true,
'en-capitalization': true,
'stop-words': {
exclude: [
'relative to', // We need to talk about links "relative to the root"
],
},
terminology: {
defaultTerms: false,
terms: `${__dirname}/.textlint.terms.json`,
},
'write-good': {
passive: false,
},
},
};

View file

@ -1,11 +1,11 @@
# Documentation website
This subdirectory holds the documentation website content as well as scripts to
generate it.
generate it.
# Main commands
## Main commands
## Building the website
### Building the website
You can build a new version of the website by running `yarn run build` in this
directory or `yarn run docs:build` at the repository root.
@ -13,42 +13,49 @@ directory or `yarn run docs:build` at the repository root.
It will read all source files in `./src` and build the final static website in
`./dist`.
## Local development
### Local development
You can run a local copy of the documentation website by running `yarn run
serve` in this directory or `yarn run docs:serve` at the repository root.
You can run a local copy of the documentation website by running
`yarn run serve`. This is an alias for running `yarn run docs:serve` at the
repository root.
This will build the website in `./dist` and expose it on `localhost`, along with
live-reload.
## Deploying the website
### Deploying the website
You can deploy the website by running `yarn run deploy` in this directory or
`yarn run docs:deploy` at the repository root.
You can deploy the website manually by running `yarn run deploy` in this
directory or `yarn run docs:deploy` at the repository root.
This will build the website and then commit the content of the `./dist` folder
to the `gh-pages` branch and push it to GitHub.
# Internals
Netlify is configured to listen to all commits on `master` and
run `netlify-master` (see`netlify.toml` in the root). This script will check if
any changes were made in the `./docs` subfolder. If no changes were made, it
will finish, otherwise it will build the website and push it to
`gh-pages`.
## Internals
The documentation generation is not using any existing static websites
generators, but custom javascript scripts.
generators, but custom JavaScript scripts.
The main two entry points are `./scripts/build.js` and `./scripts/serve.js`. The
second one adds a webserver with live-reload on top of the first one.
## HTML
### HTML
All markdown files situated in `./src` will be transformed into `.html` files in
All Markdown files situated in `./src` will be transformed into `.html` files in
`./dist`. They will be wrapped into the layout defined in their front-matter.
All the headers will be converted to their respective `<hX>` tag, along with
a unique `#id` to allow for easy anchoring.
All the headers will be converted to their respective `<hX>` tag, along with a
unique `#id` to allow for easy anchoring.
You can also use plain HTML inside those markdown files if you need more
You can also use plain HTML inside those Markdown files if you need more
advanced styling.
## Layouts
### Layouts
All layouts are saved in the `./src/_layouts` folder.
@ -60,10 +67,9 @@ You can also use mixins or include other files from the layouts.
_Note that the current layout logic is simple and might not handle complex
recursive cases, but should be enough for simple cases._
## CSS
### CSS
CSS is processed through PostCSS. It expects an entry file in
`./src/style.css`.
CSS is processed through PostCSS. It expects an entry file in `./src/style.css`.
We are using `postcss-import`, allowing you to `@import` files from the
`./src/_styles/` directory to better split your CSS code in logical chunks.
@ -72,10 +78,10 @@ Most of the styling based on tailwind.css, with the config file behing
`tailwind.config.js`. It contains default sizing and coloring to follow the
Algolia brand guidelines.
The final CSS files is then compressed through PurgeCSS (to keep CSS
classes that are actually used) and CleanCSS (to minify it).
The final CSS files is then compressed through PurgeCSS (to keep CSS classes
that are actually used) and CleanCSS (to minify it).
## JavaScript
### JavaScript
JavaScript code is processed through Babel. It will compile all files situated
in `./src/js`.
@ -83,16 +89,16 @@ in `./src/js`.
_Note that it compiles JS, and does not bundle it. We might add Webpack/Parcel
support later._
## Assets
### Assets
Any file with the following extensions found in the `./src` folder will be
automatically copied to the `./dist` folder with the same folder structure:
`gif`, `jpg`, `png`, `ico`, `html`, `svg` and `woff`.
## Placeholders
### Placeholders
Values defined in the `placeholders` key of the `config.json` file can be used
in JavaScript and Markdown files by using the `{{key}}` syntax.
in JavaScript and Markdown files by using the `{{key}}` syntax.
For example if you have:
@ -108,7 +114,7 @@ For example if you have:
Every occurrence of `{{projectVersion}}` in any `.md` or `.js` file will be
replaced with `1.4.2`.
## Sidebar
### Sidebar
The left sidebar of the documentation is generated based on the `sidebar` key of
the `config.json`. The key should contain an array where each key is a part of
@ -119,17 +125,12 @@ The layout will then automatically create all the links and color the active
page. Subsections inside the current page will also be added for every `h2`
element extracted from the markup of the current page.
## Redirects
### Redirects
The `config.json` file can hold a `redirects` array, with object containing both
a `from` and a `to` key. For each `from`, it will create a plain html page at
a `from` and a `to` key. For each `from`, it will create a plain HTML page at
this location, that will redirect anyone visiting it to the page defined in
`to`.
_Note that both those links must be defined as relative to the `site.url`
value._

View file

@ -83,7 +83,27 @@
}
],
"redirects": [
{
{
"from": "documentation/index.html",
"to": "what-is-docsearch.html"
},
{
"from": "documentation/docsearch/index.html",
"to": "what-is-docsearch.html"
},
{
"from": "documentation/docsearch/docsearch-autocomplete/index.html",
"to": "what-is-docsearch.html"
},
{
"from": "documentation/docsearch/docsearch-FAQ/index.html",
"to": "what-is-docsearch.html"
},
{
"from": "documentation/docsearch/docsearch-scraper/index.html",
"to": "what-is-docsearch.html"
},
{
"from": "documentation/docsearch/introduction/index.html",
"to": "what-is-docsearch.html"
},
@ -104,15 +124,18 @@
"to": "config-file.html"
},
{
"from": "documentation/docsearch-autocomplete/customize-autocomplete-styles/index.html",
"from":
"documentation/docsearch-autocomplete/customize-autocomplete-styles/index.html",
"to": "styling.html"
},
{
"from": "documentation/docsearch-autocomplete/configuring-the-search/index.html",
"from":
"documentation/docsearch-autocomplete/configuring-the-search/index.html",
"to": "behavior.html"
},
{
"from": "documentation/docsearch-FAQ/customize-configuration-file/index.html",
"from":
"documentation/docsearch-FAQ/customize-configuration-file/index.html",
"to": "config-file.html"
},
{

View file

@ -5,54 +5,72 @@
"build": "NODE_ENV=production babel-node ./scripts/build.js",
"deploy": "./scripts/deploy",
"lint": "./scripts/lint",
"precommit": "./scripts/precommit",
"lint:js": "./scripts/lint-js",
"lint:css": "./scripts/lint-css",
"lint:md": "./scripts/lint-md",
"lint:md:fix": "./scripts/lint-md-fix",
"prepush": "yarn lint",
"serve": "babel-node ./scripts/serve.js"
},
"devDependencies": {
"@babel/cli": "^7.0.0-beta.51",
"@babel/core": "^7.0.0-beta.51",
"@babel/node": "^7.0.0-beta.51",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0-beta.51",
"@babel/preset-env": "^7.0.0-beta.51",
"@fullhuman/postcss-purgecss": "^1.0.1",
"autoprefixer": "^8.6.4",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^8.2.3",
"babel-plugin-dynamic-import-node-sync": "^2.0.1",
"chalk": "^2.4.1",
"cheerio": "^1.0.0-rc.2",
"chokidar": "^2.0.4",
"cpx": "^1.5.0",
"@babel/cli": "7.0.0-rc.3",
"@babel/core": "7.0.0-rc.3",
"@babel/node": "7.0.0-rc.3",
"@babel/plugin-proposal-object-rest-spread": "7.0.0-rc.3",
"@babel/preset-env": "7.0.0-rc.3",
"@fullhuman/postcss-purgecss": "1.0.1",
"autoprefixer": "8.6.5",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "8.2.6",
"babel-plugin-dynamic-import-node-sync": "2.0.1",
"chalk": "2.4.1",
"cheerio": "1.0.0-rc.2",
"chokidar": "2.0.4",
"cpx": "1.5.0",
"eslint": "4.19.1",
"eslint-config-algolia": "^13.1.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-prettier": "^2.6.0",
"front-matter": "^2.3.0",
"fs-extra": "^7.0.0",
"glob": "^7.1.2",
"husky": "^0.14.3",
"inquirer": "^6.0.0",
"live-server": "^1.2.0",
"lodash": "^4.17.10",
"markdown-it": "^8.4.1",
"markdown-it-anchor": "^5.0.2",
"markdown-it-highlightjs": "^3.0.0",
"normalize.css": "^8.0.0",
"p-all": "^1.0.0",
"p-each-series": "^1.0.0",
"p-map": "^1.2.0",
"pify": "^3.0.0",
"postcss": "^6.0.23",
"postcss-clean": "^1.1.0",
"postcss-import": "^11.1.0",
"postcss-nested": "^3.0.0",
"prettier": "1.9.2",
"pug": "^2.0.3",
"puppeteer": "^1.6.1",
"stylelint": "^9.3.0",
"stylelint-csstree-validator": "^1.3.0",
"tailwindcss": "^0.6.4"
"eslint-config-algolia": "13.1.0",
"eslint-config-prettier": "2.10.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-prettier": "2.6.2",
"front-matter": "2.3.0",
"fs-extra": "7.0.0",
"gh-pages": "1.2.0",
"glob": "7.1.2",
"husky": "0.14.3",
"inquirer": "6.2.0",
"live-server": "1.2.0",
"lodash": "4.17.10",
"markdown-it": "8.4.2",
"markdown-it-anchor": "5.0.2",
"markdown-it-highlightjs": "3.0.0",
"normalize.css": "8.0.0",
"pify": "3.0.0",
"postcss": "6.0.23",
"postcss-clean": "1.1.0",
"postcss-import": "11.1.0",
"postcss-nested": "3.0.0",
"prettier": "1.14.2",
"pug": "2.0.3",
"p-all": "1.0.0",
"p-each-series": "1.0.0",
"p-map": "1.2.0",
"remark-cli": "5.0.0",
"remark-frontmatter": "1.2.1",
"remark-lint-no-trailing-spaces": "2.0.0",
"remark-preset-lint-consistent": "2.0.2",
"remark-preset-lint-markdown-style-guide": "2.1.2",
"remark-preset-lint-recommended": "3.0.2",
"remark-reference-links": "4.0.2",
"stylelint": "9.5.0",
"stylelint-csstree-validator": "1.3.0",
"tailwindcss": "0.6.5",
"textlint": "11.0.0",
"textlint-rule-alex": "1.3.1",
"textlint-rule-common-misspellings": "1.0.1",
"textlint-rule-en-capitalization": "2.0.1",
"textlint-rule-stop-words": "1.0.5",
"textlint-rule-terminology": "1.1.29",
"textlint-rule-write-good": "1.6.2"
},
"peerDependencies": {},
"dependencies": {

View file

@ -1,6 +1,8 @@
#!/usr/bin/env sh
set -e
yarn run lint
rm -rf ./dist
yarn run build
gh-pages -d dist

View file

@ -41,6 +41,8 @@ export default {
'./src',
_.replace(filepath, '.md', '.html')
);
const srcpath =
siteConfig.site.repo + _.replace(filepath, './', '/tree/master/docs/');
const destination = `./dist/${currentUrl}`;
// Read file, and extract front-matter from raw text
@ -86,6 +88,7 @@ export default {
current: {
url: currentUrl,
content: htmlBody,
src: srcpath,
...fileConfig,
},
};

View file

@ -1,5 +1,6 @@
#!/usr/bin/env sh
set -e
eslint ./scripts/**/*.js ./src/*.js ./*.js
stylelint ./src/style.css ./src/_styles/*.css
yarn run lint:js
yarn run lint:css
yarn run lint:md

3
docs/scripts/lint-css Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env sh
stylelint ./src/style.css ./src/_styles/*.css

7
docs/scripts/lint-js Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env sh
eslint \
./*.js \
./.*.js \
./src/**/*.js \
./scripts/**/*.js

16
docs/scripts/lint-md Executable file
View file

@ -0,0 +1,16 @@
#!/usr/bin/env sh
# Check markdown styling (links, spacing, etc)
remark \
--no-stdout \
--quiet \
--frail \
./*.md \
./src/*.md
# Check text content (misspelling, weasel words, offensive writing)
textlint \
./*.md \
./src/*.md

28
docs/scripts/lint-md-fix Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env sh
set -e
# This will attempt to automatically fix most of the Markdown linting issues
# detected.
# We will first transform the file according to remark config. This will mostly
# convert inline links to references at the bottom of the file.
REMARK_MODE=fix \
remark \
--quiet \
./*.md \
./src/*.md \
--output
# We then check the actual natural language content of the file, to fix
# misspellings, punctuation and other fixable issues.
textlint \
--fix \
./*.md \
./src/*.md
# Finally, we'll run everything through prettier to make sure all files are
# formatted the same way. This will remove trailing spaces, fit all content
# under 80 char long lines, etc
prettier \
--write \
./*.md \
./src/*.md

View file

@ -1,2 +0,0 @@
#!/usr/bin/env sh
yarn lint

View file

@ -58,7 +58,7 @@
.custom-search-wrapper.fln.h-60.w-100.rounded-auto.relative
label.absolute.pin-left.z-1.w-1.h-100.ml-05.text-solstice.fill-current.cursor-pointer(for="docsearch")
include ../assets/icons/magnifying-glass.svg
input.custom-search-input.w-100.h-100.outline-none.text-solstice.pl-2.rounded-auto.bg-moon.focus_bg-moon--1#docsearch(placeholder="Search the docs...")
input.custom-search-input.w-100.h-2x.leading-h-2x.outline-none.text-solstice.pl-2.rounded-auto.bg-moon.focus_bg-moon--1#docsearch(placeholder="Search the docs...")
//- Links
block nav

View file

@ -60,6 +60,9 @@ block content
.glide__slide
img(src="assets/logos/jekyll.jpg", alt="DocSearch + Jekyll", width=60)
.glide__caption Jekyll
.glide__slide
img(src="assets/logos/momentjs.jpg", alt="DocSearch + MomentJS", width=60)
.glide__caption MomentJS
.glide__slide
img(src="assets/logos/netlify.jpg", alt="DocSearch + Netlify", width=60)
.glide__caption Netlify
@ -81,9 +84,6 @@ block content
.glide__slide
img(src="assets/logos/socketio.jpg", alt="DocSearch + Socket.io" , width=60)
.glide__caption Socket.io
.glide__slide
img(src="assets/logos/stripe.jpg", alt="DocSearch + Stripe", width=60)
.glide__caption Stripe
.glide__slide
img(src="assets/logos/trello.jpg", alt="DocSearch + Trello", width=60)
.glide__caption Trello
@ -213,13 +213,13 @@ block content
img.h-2(src='assets/logos/react.jpg', alt='React')
.fla.pl-1.text-solstice.uppercase.bold React
.fln.w-100.sm_w-50.md_w-25.p-1.flex.flrnw
a.c-card.custom-demo.fla.flex.flcnw.p-05(href='https://stripe.com/docs')
a.c-card.custom-demo.fla.flex.flcnw.p-05(href='https://momentjs.com/')
.fln.flc.relative.text-0.max-w-5.m-auto
img(src='assets/demos/example-stripe.gif', alt='Stripe')
img(src='assets/demos/example-momentjs.gif', alt='MomentJS')
.fln.pt-1.flex.flrnw.flc
.fln.text-0
img.h-2(src='assets/logos/stripe.jpg', alt='Stripe')
.fla.pl-1.text-solstice.uppercase.bold Stripe
img.h-2(src='assets/logos/momentjs.jpg', alt='MomentJS')
.fla.pl-1.text-solstice.uppercase.bold MomentJS
.relative.bg-white-pure
.bg-footer

View file

@ -11,20 +11,20 @@ block nav
.md_hidden.flex.justify-start.items-center.mx-2
button.custom-toggle-nav.text-solstice.items-center.hover_text-grey-darker.focus_outline-none
svg.align-text-bottom.navigation-open.h-1x.w-1x.fill-current(role="button", xmlns="http://www.w3.org/2000/svg", viewBox="0 0 20 20")
path(d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z")
path(d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z")
svg.align-text-bottom.navigation-close.hidden.h-1x.w-1x.fill-current(role="button", xmlns="http://www.w3.org/2000/svg", viewBox="0 0 20 20")
path(d="M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z")
block content
.bgtb-moon-white-pure.relative
.md_flex.max-w-lg.m-auto
.navigation-sidebar.sticky.pin-t.top-3.h-100vh-3.overflow-y-auto.hidden.md_block.bg-white
.navigation-sidebar.sticky.pin-t.top-3.h-100vh-3.overflow-y-auto.hidden.md_block.bg-white.pl-1
// Adding subsections from markdown
.pt-2.w-5.m-auto.sm_flex.sm_w-90.md_block.md_w-100
each category in sidebar
.flcnw.flspa.sm_flex-auto.sm_w-33.sm_p-1.md_w-100.md_p-0
.category.text-nebula.poppins.uppercase.mb-1.text-2=category.title
ul.list-reset.text-1.mb-1.md_ml-0x
.category.text-nebula.poppins.uppercase.mb-05x.text-1x=category.title
ul.list-reset.mb-2
each page in category.pages
- var isCurrent = current.url === page.url
- var additionalClasses = isCurrent ? 'current-page text-nebula' : 'text-solstice'
@ -35,16 +35,20 @@ block content
ul.list-reset.pl-1.text-1
each heading in page.headings
li
a.block.py-0x.text-telluric.whitespace-pre(href=`${page.url}#${heading.anchor}`)=heading.title
a.block.py-0x.text-telluric(href=`${page.url}#${heading.anchor}`)=heading.title
.documentation-content.text-2.pt-2.pb-1.px-2.w_100.md_w-75
.block.md_hidden.mb-1
.md_hidden.mb-1
a(href=site.url) DocSearch
span &nbsp;>&nbsp;
a(href=`${site.url}/what-is-docsearch.html`) Documentation
.custom-main-title.text-5.lg_text-7.uppercase.tracking-poppins.text-solstice.bold.mb-2=current.title
h1.custom-main-title.text-5.lg_text-7.uppercase.tracking-poppins.text-solstice.bold.mb-2=current.title
!=current.content
// Include the apply form
if current.includeForm
.mt-2
include ../_includes/apply-form.pug
.my-3.italic
a(href=current.src) Edit this page

View file

@ -216,7 +216,7 @@
.form-control {
@apply rounded-auto;
border: solid 1px #dbdbe7;
@apply p-1;
@apply h-2x leading-h-2x px-1;
width: 100%;
}

View file

@ -9,6 +9,9 @@
@apply .leading-2 my-1;
}
/* Titles */
h1 {
@apply .leading-0;
}
h2 {
@apply .text-solstice .text-4 .normal;
@apply .mb-1 .mt-2;

View file

@ -6,19 +6,14 @@
.custom-search-wrapper:focus-within {
width: 100%;
}
/* Wrapper added by DocSearch */
/* purgecss start ignore */
/* Wrapper added by DocSearch */
.algolia-autocomplete {
@apply w-100;
}
/* purgecss end ignore */
/* Main search input */
.custom-search-input {
padding-top: calc(0.5rem + 2px);
@apply .pb-05;
}
/* Dropdown menu */
/* purgecss start ignore */
.ds-dropdown-menu {
@apply w-100;
}

View file

@ -4,7 +4,6 @@ title: Applying to DocSearch
includeForm: true
---
__Please make sure you [read the checklist][1] before applying.__
**Please make sure you [read the checklist][1] before applying.**
[1]: who-can-apply.html

View file

@ -1,72 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1440px" height="439px" viewBox="0 0 1440 439" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<svg width="3203px" height="542px" viewBox="0 0 3203 542" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 51.2 (57519) - http://www.bohemiancoding.com/sketch -->
<title>bg-docsearch</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Docsearch-V3" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="DocSearch_V3">
<g id="bg-docsearch" transform="translate(-62.000000, -44.000000)">
<g>
<path d="M1563,482 L861,482" id="Shape" stroke="#5468FF"></path>
<path d="M1563,445 C1521.35547,445 855,480 855,480" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,407 C1479.72547,407 849,476 849,476" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,371 C1438.12038,371 843,475 843,475" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,334 C1396.51832,334 837,472 837,472" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,296 C1354.9297,296 831,469 831,469" id="Shape" stroke="#C5C9E0"></path>
<path d="M1562,260 C1312.35784,260 824,467 824,467" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,222 C1271.4043,222 818,464 818,464" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,185 C1229.80235,185 812,462 812,462" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,148 C1188.21342,148 806,460 806,460" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,111 C1146.64306,111 800,456 800,456" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,74 C1104.48428,74 793,454 793,454" id="Shape" stroke="#C5C9E0"></path>
<path d="M1563,37 C1062.88406,37 787,452 787,452" id="Shape" stroke="#C5C9E0"></path>
<path d="M1562,0 C1020.94611,0 781,450 781,450" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,482 L861,482" id="Shape" stroke="#5468FF"></path>
<path d="M0,445 C41.6445262,445 708,480 708,480" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,407 C83.2745305,407 714,476 714,476" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,371 C124.890383,371 720,475 720,475" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,334 C166.489976,334 726,472 726,472" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,296 C208.077997,296 732,469 732,469" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,260 C249.652915,260 738,467 738,467" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,222 C291.606472,222 745,464 745,464" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,185 C333.203635,185 751,462 751,462" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,148 C374.792012,148 757,460 757,460" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,111 C416.367701,111 763,456 763,456" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,74 C458.526494,74 770,454 770,454" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,37 C500.115939,37 776,452 776,452" id="Shape" stroke="#C5C9E0"></path>
<path d="M0,0 C541.046441,0 781,450 781,450" id="Shape" stroke="#C5C9E0"></path>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="210" cy="138" r="6"></circle>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="462" cy="363" r="6"></circle>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="1093" cy="414" r="6"></circle>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="1346" cy="63" r="6"></circle>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(1219.500000, 147.500000) rotate(-45.000000) translate(-1219.500000, -147.500000) " x="1212" y="140" width="15" height="15"></rect>
<path d="M1220,143 L1220,152" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M1224,148 L1215,148" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(336.500000, 354.500000) rotate(-45.000000) translate(-336.500000, -354.500000) " x="329" y="347" width="15" height="15"></rect>
<path d="M336,350 L336,359" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M340,355 L331,355" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(83.500000, 153.500000) rotate(-45.000000) translate(-83.500000, -153.500000) " x="76" y="146" width="15" height="15"></rect>
<path d="M83,149 L83,158" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M88,154 L79,154" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(1471.500000, 379.500000) rotate(-45.000000) translate(-1471.500000, -379.500000) " x="1464" y="372" width="15" height="15"></rect>
<path d="M1472,375 L1472,384" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M1477,379 L1468,379" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(967.500000, 349.500000) rotate(-45.000000) translate(-967.500000, -349.500000) " x="960" y="342" width="15" height="15"></rect>
<path d="M968,345 L968,354" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M971,350 L962,350" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<g id="Group-4" transform="translate(583.000000, 309.000000)" fill="#FFFFFF" fill-rule="nonzero" stroke="#C5C9E0">
<rect id="Rectangle-path" transform="translate(10.968725, 10.928245) rotate(-45.000000) translate(-10.968725, -10.928245) " x="3.28958879" y="3.24910916" width="15.358272" height="15.358272"></rect>
<path d="M10.9647202,6.13628037 L10.9647202,15.7311981" id="Shape"></path>
<path d="M15.7675155,10.9284028 L6.17259781,10.9284028" id="Shape"></path>
</g>
<g id="Group-4-Copy" transform="translate(356.000000, 65.000000)" fill="#FFFFFF" fill-rule="nonzero" stroke="#C5C9E0">
<rect id="Rectangle-path" transform="translate(10.968725, 10.928245) rotate(-45.000000) translate(-10.968725, -10.928245) " x="3.28958879" y="3.24910916" width="15.358272" height="15.358272"></rect>
<path d="M10.9647202,6.13628037 L10.9647202,15.7311981" id="Shape"></path>
<path d="M15.7675155,10.9284028 L6.17259781,10.9284028" id="Shape"></path>
</g>
</g>
</g>
<g id="bg-docsearch" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M3209.5,541 L1681,541" id="Shape" stroke="#5468FF"></path>
<g id="Group" transform="translate(1601.000000, 59.000000)" stroke="#C5C9E0">
<path d="M1607.48047,445 L782,445 C740.355474,445 74,480 74,480" id="Shape"></path>
<path d="M1607.48047,407 L782,407 C698.72547,407 68,476 68,476" id="Shape"></path>
<path d="M1607.48047,371 L782,371 C657.120377,371 62,475 62,475" id="Shape"></path>
<path d="M1607.48047,334 L782,334 C615.518315,334 56,472 56,472" id="Shape"></path>
<path d="M1607.48047,296 L782,296 C573.929702,296 50,469 50,469" id="Shape"></path>
<path d="M1607.48047,260 L781,260 C531.357839,260 43,467 43,467" id="Shape"></path>
<path d="M1607.48047,222 L782,222 C490.404295,222 37,464 37,464" id="Shape"></path>
<path d="M1607.48047,185 L782,185 C448.802354,185 31,462 31,462" id="Shape"></path>
<path d="M1607.48047,148 L782,148 C407.213422,148 25,460 25,460" id="Shape"></path>
<path d="M1607.48047,111 L782,111 C365.643061,111 19,456 19,456" id="Shape"></path>
<path d="M1607.48047,74 L782,74 C323.48428,74 12,454 12,454" id="Shape"></path>
<path d="M1607.48047,37 L782,37 C281.884061,37 6,452 6,452" id="Shape"></path>
<path d="M1607.48047,0 L781,0 C239.946107,0 0,450 0,450" id="Shape"></path>
</g>
<g id="Group" transform="translate(793.000000, 299.000000) scale(-1, 1) translate(-793.000000, -299.000000) translate(-11.000000, 59.000000)" stroke="#C5C9E0">
<path d="M1607.48047,445 L782,445 C740.355474,445 74,480 74,480" id="Shape"></path>
<path d="M1607.48047,407 L782,407 C698.72547,407 68,476 68,476" id="Shape"></path>
<path d="M1607.48047,371 L782,371 C657.120377,371 62,475 62,475" id="Shape"></path>
<path d="M1607.48047,334 L782,334 C615.518315,334 56,472 56,472" id="Shape"></path>
<path d="M1607.48047,296 L782,296 C573.929702,296 50,469 50,469" id="Shape"></path>
<path d="M1607.48047,260 L781,260 C531.357839,260 43,467 43,467" id="Shape"></path>
<path d="M1607.48047,222 L782,222 C490.404295,222 37,464 37,464" id="Shape"></path>
<path d="M1607.48047,185 L782,185 C448.802354,185 31,462 31,462" id="Shape"></path>
<path d="M1607.48047,148 L782,148 C407.213422,148 25,460 25,460" id="Shape"></path>
<path d="M1607.48047,111 L782,111 C365.643061,111 19,456 19,456" id="Shape"></path>
<path d="M1607.48047,74 L782,74 C323.48428,74 12,454 12,454" id="Shape"></path>
<path d="M1607.48047,37 L782,37 C281.884061,37 6,452 6,452" id="Shape"></path>
<path d="M1607.48047,0 L781,0 C239.946107,0 0,450 0,450" id="Shape"></path>
</g>
<path d="M-7.5,541 L1681,541" id="Shape" stroke="#5468FF"></path>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="1030" cy="197" r="6"></circle>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="1282" cy="422" r="6"></circle>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="1913" cy="473" r="6"></circle>
<circle id="Oval" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" cx="2176" cy="234" r="6"></circle>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(2040.000000, 207.000000) rotate(-45.000000) translate(-2040.000000, -207.000000) " x="2033" y="200" width="14" height="14"></rect>
<path d="M2040,202 L2040,211" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M2045.5,207 L2035,207" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(1156.500000, 413.500000) rotate(-45.000000) translate(-1156.500000, -413.500000) " x="1149" y="406" width="15" height="15"></rect>
<path d="M1156,409 L1156,418" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M1160,414 L1151,414" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(903.500000, 212.500000) rotate(-45.000000) translate(-903.500000, -212.500000) " x="896" y="205" width="15" height="15"></rect>
<path d="M903,208 L903,217" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M908,213 L899,213" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(2291.500000, 438.500000) rotate(-45.000000) translate(-2291.500000, -438.500000) " x="2284" y="431" width="15" height="15"></rect>
<path d="M2292,434 L2292,443" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M2297,438 L2288,438" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<rect id="Rectangle-path" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero" transform="translate(1787.500000, 408.500000) rotate(-45.000000) translate(-1787.500000, -408.500000) " x="1780" y="401" width="15" height="15"></rect>
<path d="M1788,404 L1788,413" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<path d="M1791,409 L1782,409" id="Shape" stroke="#C5C9E0" fill="#FFFFFF" fill-rule="nonzero"></path>
<g id="Group-4" transform="translate(1403.000000, 368.000000)" fill="#FFFFFF" fill-rule="nonzero" stroke="#C5C9E0">
<rect id="Rectangle-path" transform="translate(10.968725, 10.928245) rotate(-45.000000) translate(-10.968725, -10.928245) " x="3.28958879" y="3.24910916" width="15.358272" height="15.358272"></rect>
<path d="M10.9647202,6.13628037 L10.9647202,15.7311981" id="Shape"></path>
<path d="M15.7675155,10.9284028 L6.17259781,10.9284028" id="Shape"></path>
</g>
<g id="Group-4-Copy" transform="translate(1176.000000, 124.000000)" fill="#FFFFFF" fill-rule="nonzero" stroke="#C5C9E0">
<rect id="Rectangle-path" transform="translate(10.968725, 10.928245) rotate(-45.000000) translate(-10.968725, -10.928245) " x="3.28958879" y="3.24910916" width="15.358272" height="15.358272"></rect>
<path d="M10.9647202,6.13628037 L10.9647202,15.7311981" id="Shape"></path>
<path d="M15.7675155,10.9284028 L6.17259781,10.9284028" id="Shape"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -29,10 +29,13 @@ redirect the browser to the page matching part of the page, but you can override
it to add your own behavior.
The method is called with three arguments:
- `input`, a reference to the search `input` element. It comes with the `.open()`,
`.close()`, `.getVal()` and `.setVal()` methods.
- `input`, a reference to the search `input` element. It comes with the
`.open()`, `.close()`, `.getVal()` and `.setVal()` methods.
- `event`, the actual event triggering the selection. This can come from a click
or a keyboard navigation.
- `suggestion`, the object representing the current selection.
```javascript
@ -60,9 +63,8 @@ docsearch({
## `transformData`
This method will be called on all suggestions before displaying them. It
doesn't do anything by default, but we provide this hook if you want to add your
own logic.
This method will be called on all suggestions before displaying them. It doesn't
do anything by default, but we provide this hook for you to add your own logic.
```javascript
docsearch({
@ -97,22 +99,21 @@ search.autocomplete.on('autocomplete:opened', event => {
## `algoliaOptions`
You can pass options to the Algolia API by using the `algoliaOptions`
key. You will find all Algolia API options in their [own documentation][3].
You can pass options to the Algolia API by using the `algoliaOptions` key. You
will find all Algolia API options in their [own documentation][3].
For example, you might want to increase the number of results displayed in the dropdown.
[`hitsPerPage `set the number of shown hits][4].
For example, you might want to increase the number of results displayed in the
dropdown. [`hitsPerPage` set the number of shown hits][4].
```javascript
docsearch({
algoliaOptions: {
hitsPerPage: 10,
// See https://www.algolia.com/doc/api-reference/api-parameters/
}
},
});
```
[1]: https://github.com/algolia/autocomplete.js
[2]: https://github.com/algolia/autocomplete.js#options
[3]: https://www.algolia.com/doc/api-reference/api-parameters/

View file

@ -12,9 +12,7 @@ A DocSearch looks like this:
```json
{
"index_name": "example",
"start_urls": [
"https://www.example.com/docs"
],
"start_urls": ["https://www.example.com/docs"],
"selectors": {
"lvl0": "#content header h1",
"lvl1": "#content article h1",
@ -23,18 +21,18 @@ A DocSearch looks like this:
"lvl4": "#content section h5",
"lvl5": "#content section h6",
"text": "#content header p,#content section p,#content section ol"
},
}
}
```
## ``index_name``
## `index_name`
This is the name of the Algolia index where your records will be pushed. The
`apiKey` we will share with you will be restricted to work on this index.
When using the free DocSearch crawler, the `indexName` will always be the name
of the config. If you're running DocSearch yourself, you can of course use any
name you'd like.
of the config. If you're running DocSearch yourself, you can use any name you'd
like.
```json
{
@ -44,15 +42,14 @@ name you'd like.
## `start_urls`
This array contains the list of urls that will be used to start crawling your
This array contains the list of URLs that will be used to start crawling your
website. The crawler will recursively follow any links on those pages. It will
not follow links that are on another domain and never follow links defined in `stop_urls`.
not follow links that are on another domain and never follow links defined in
`stop_urls`.
```json
{
"start_urls": [
"https://www.example.com/docs"
]
"start_urls": ["https://www.example.com/docs"]
}
```
@ -68,24 +65,24 @@ The following example will make it clearer:
```json
{
"start_urls": [
{
"url": "http://www.example.com/docs/(?P<lang>.*?)/(?P<version>.*?)/",
"variables": {
"lang": ["en", "fr"],
"version": ["latest", "3.3", "3.2"]
}
}
]
{
"url": "http://www.example.com/docs/(?P<lang>.*?)/(?P<version>.*?)/",
"variables": {
"lang": ["en", "fr"],
"version": ["latest", "3.3", "3.2"]
}
}
]
}
```
The beneficial side effect of using this syntax is that all records that will
then be extracted from crawling `http://www.example.com/docs/en/latest` will have
`lang: en` and `version: latest` added to it, allowing you to then filter based on
those values.
then be extracted from crawling `http://www.example.com/docs/en/latest` will
have `lang: en` and `version: latest` added to it, allowing you to then filter
based on those values.
The following example shows how you can filter results matching specifics
language and version from the front-end
language and version from the frontend
```js
docsearch({
@ -99,18 +96,18 @@ docsearch({
### Using custom tags
You can also apply custom tags to some pages without the need to use regular
expressions. In that case, add the list of tags to the `tags` key. Note
that those tags will be automatically added as facets in Algolia, allowing you
to filter based on their values as well.
expressions. In that case, add the list of tags to the `tags` key. Note that
those tags will be automatically added as facets in Algolia, allowing you to
filter based on their values as well.
```json
{
"start_urls": [
{
"url": "http://www.example.com/docs/concepts/",
"tags": ['concepts', 'terminology']
"tags": ["concepts", "terminology"]
}
]
]
}
```
@ -125,21 +122,21 @@ docsearch({
### Using Page Rank
If you want to give more weight to some pages to boost their ranking in the
results, you can attribute a custom `page_rank` to specific urls. Pages with
highest `page_rank` will be returned before pages with a lower `page_rank`. Note
that you can pass any numeric value, including negative values.
To give more weight to some pages to boost their ranking in the results, you can
attribute a custom `page_rank` to specific URLs. Pages with highest `page_rank`
will be returned before pages with a lower `page_rank`. Note that you can pass
any numeric value, including negative values.
```json
{
"start_urls": [
{
"url": "http://www.example.com/docs/concepts/",
"page_rank": 5,
"page_rank": 5
},
{
"url": "http://www.example.com/docs/contributors/",
"page_rank": 1,
"page_rank": 1
}
]
}
@ -206,7 +203,7 @@ record hierarchy. It can contains up to 6 levels (`lvl0`, `lvl1`, `lvl2`,
`lvl3`, `lvl4`, `lvl5`) and `text`.
A default config would be to target the page `title` or `h1` as `lvl0`, the `h2`
as `lvl1` and `h3` as `lvl2` and `p` as `text`, but this is highly dependent on
as `lvl1` and `h3` as `lvl2` and `p` as `text`, but this is highly dependent on
the markup.
The `text` key is mandatory, but we highly recommend setting also `lvl0`, `lvl1`
@ -222,7 +219,7 @@ and `lvl2` to have a decent level of relevance.
"lvl4": "#content section h5",
"lvl5": "#content section h6",
"text": "#content header p,#content section p,#content section ol"
},
}
}
```
@ -233,7 +230,7 @@ Other special keys can be set, as documented below.
{
"selectors": {
"lvl0": {
"selector": "#content header h1",
"selector": "#content header h1"
}
}
}
@ -242,8 +239,8 @@ Other special keys can be set, as documented below.
### Using global selectors
The default way of extracting content through selectors is to read the HTML
markup from top to bottom. This works well with semi-structured content, like
a hierarchy of headers. This breaks when relevant information is not part of the
markup from top to bottom. This works well with semi-structured content, like a
hierarchy of headers. This breaks when relevant information is not part of the
same node flow. For example when the title is in a header or a sidebar.
For that reason, you can set a selector as global, meaning that it will match on
@ -262,8 +259,8 @@ the whole page, and will be the same for all records extracted on this page.
### Setting a default value
If your selector might not match a valid element on the page, you can define
a `default_value` to fallback to.
If your selector might not match a valid element on the page, you can define a
`default_value` to fallback to.
```json
{
@ -342,7 +339,9 @@ recommend changing it as the default settings are meant to work for all
websites.
One use case would be to configure the `separatorsToIndex` setting. By default
Algolia will consider all special character as a word separator. In some contexts, like for method names, you might want `_`, `/` or `#` to keep their meaning.
Algolia will consider all special character as a word separator. In some
contexts, like for method names, you might want `_`, `/` or `#` to keep their
meaning.
```json
{
@ -354,18 +353,16 @@ Algolia will consider all special character as a word separator. In some context
Check the [Algolia documentation][2] for more information on the settings.
### `min_indexed_level` _Optional_
The default value is `0`. By increasing it, you can chose to not index some
records if they don't have enough `lvlX` matching. For example, with
a `min_indexed_level: 2`, records that have at least `lvl0`, `lvl1` and
`lvl2` matching something will be indexed.
records if they don't have enough `lvlX` matching. For example, with a
`min_indexed_level: 2`, records that have at least `lvl0`, `lvl1` and `lvl2`
matching something will be indexed.
This is useful when your documentation has pages that share the same `lvl0` and
`lvl1` for example. In that case, you don't want to index all the shared
records, but want to keep the one matching content that is different across
pages.
records, but want to keep the content different across pages.
```json
{
@ -377,16 +374,16 @@ pages.
`nb_hits` automatically updated by DocSearch every time it runs your config. It
is set to the number of records that were extracted and indexed. We check this
key internally to keep track of any unintended spike or drop that could reveal
a misconfiguration.
key internally to keep track of any unintended spike or drop that could reveal a
misconfiguration.
You don't have to touch, we're documenting it here in case you were
wondering what this was about.
You don't have to touch it, we're documenting it here in case you were wondering
what this was about.
### `only_content_level` _Optional_
When `only_content_level` is set to `true`, then the crawler won't create
records for each `lvlX` selectors, but only for the `text` selectors.
records for the `lvlX` selectors.
If used, `min_indexed_level` is ignored.
@ -399,8 +396,8 @@ If used, `min_indexed_level` is ignored.
### `scrape_start_urls` _Optional_
By default, the crawler will extract content from the pages defined in
`starts_urls`. If you do not have any valuable content on your `starts_urls` or that some pages are duplicates from another one, you should set
this to `false`.
`start_urls`. If you do not have any valuable content on your `starts_urls` or
if it's a duplicate of another page, you should set this to `false`.
```json
{
@ -413,15 +410,12 @@ this to `false`.
This expects an array of CSS selectors. Any element matching one of those
selectors will be removed from the page before any data is extracted from it.
This can be used to remove a table of content, a sidebar or a footer, to
make other selectors easier to write.
This can be used to remove a table of content, a sidebar or a footer, to make
other selectors easier to write.
```json
{
"selectors_exclude": [
".footer",
"ul.deprecated"
],
"selectors_exclude": [".footer", "ul.deprecated"]
}
```
@ -438,10 +432,7 @@ Note that this is often used to avoid duplicate content, by adding
```json
{
"stop_urls": [
"https://www.example.com/docs/index.html",
"license.html"
],
"stop_urls": ["https://www.example.com/docs/index.html", "license.html"]
}
```
@ -452,31 +443,27 @@ use it to define which pages to crawl.
### `sitemap_urls` _Optional_
You can pass an array of urls pointing to your sitemap(s) files. If this value
is set, DocSearch will try to read urls from your sitemap(s) instead of
You can pass an array of URLs pointing to your sitemap(s) files. If this value
is set, DocSearch will try to read URLs from your sitemap(s) instead of
following every link of your `starts_urls`.
```json
{
"sitemap_urls": [
"http://www.example.com/docs/sitemap.xml"
],
"sitemap_urls": ["http://www.example.com/docs/sitemap.xml"]
}
```
### `sitemap_alternate_links` _Optional_
Sitemaps can contain _alternative links_ for urls. Those are other versions of
the same page, in a different language, or with a different url. By default
DocSearch will ignore those urls.
Sitemaps can contain _alternative links_ for URLs. Those are other versions of
the same page, in a different language, or with a different URL. By default
DocSearch will ignore those URLs.
Set this to `true` if you want those other version to be crawled as well.
```json
{
"sitemap_urls": [
"http://www.example.com/docs/sitemap.xml"
],
"sitemap_urls": ["http://www.example.com/docs/sitemap.xml"],
"sitemap_alternate_links": true
}
```
@ -485,18 +472,18 @@ With the above config and the `sitemap.xml` below, both
`http://www.example.com/docs/` and `http://www.example.com/docs/de/` will be
crawled.
```
<url>
<loc>http://www.example.com/docs/</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://www.example.com/de/"/>
</url>
```html
<url>
<loc>http://www.example.com/docs/</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://www.example.com/de/"/>
</url>
```
## JavaScript rendering
By default DocSearch expect websites to have server-side rendering, meaning that
HTML source is returned directly by the server. If your content is generated by the
front-end, you have to tell DocSearch to emulate a browser through Selenium.
HTML source is returned directly by the server. If your content is generated by
the front-end, you have to tell DocSearch to emulate a browser through Selenium.
_As client-side crawling is way slower than server-side crawling, we highly
encourage you to update your website to enable server-side rendering._
@ -504,7 +491,7 @@ encourage you to update your website to enable server-side rendering._
### `js_render` _Optional_
Set this value to true if your website requires client-side rendering. This will
make DocSearch spawn a Selenium proxy to fetch all your webpages.
make DocSearch spawn a Selenium proxy to fetch all your web pages.
```json
{
@ -518,9 +505,9 @@ If your website is slow to load, you can use `js_wait` to tell DocSearch to wait
a specific amount of time (in seconds) for the page to load before extracting
its content.
Note that this option might have a large impact on the time required
to crawl your website and we would encourage you to enable server-side rendering
on your website instead.
Note that this option might have a large impact on the time required to crawl
your website and we would encourage you to enable server-side rendering on your
website instead.
This option has no impact if `js_render` is set to `false`.
@ -534,7 +521,7 @@ This option has no impact if `js_render` is set to `false`.
### `use_anchors` _Optional_
Websites using client-side rendering often don't use full urls, but instead take
advantage of the url hash (the part after the `#`).
advantage of the URL hash (the part after the `#`).
If your website is using such urls, you should set `use_anchors` to `true` for
DocSearch to index all your content.

View file

@ -12,18 +12,17 @@ any content, and will use the semantics of your HTML structure to construct its
records. This means that `h1`...`h6` titles will be used for the hierarchy, and
each `p` of text will be used as a potential result.
Those CSS selectors can of course be overwritten, and each website actually has
its own JSON configuration file that describe in more details how the crawling
should behave. You can find the complete list of options in [our
documentation][2].
Those CSS selectors can be overwritten, and each website actually has its own
JSON configuration file that describe in more details how the crawling should
behave. You can find the complete list of options in [our documentation][2].
We automatically run each config every 24h. This is done from our own
infrastructure, meaning that you don't need to install anything on your side.
We run this service entirely free of charge, we're just asking that you keep the
infrastructure, meaning that you don't need to install anything on your side. We
run this service entirely free of charge, but we're asking that you keep the
"powered by Algolia" logo next to the search results.
That being said, if you'd like to run DocSearch on your own, [all the code is
open-source][3] and even packaged as a Docker image. Just grab it, and run it
open source][3] and even packaged as a Docker image. Download it, and run it
with your own credentials.
[1]: https://scrapy.org/

View file

@ -8,23 +8,22 @@ the `docsearch.js` library into your website as per the following example. Your
`apiKey` and `indexName` credentials will be given to you as soon as we've
created your config.
```html
<!-- Before the closing </head> -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/docsearch.js@{{docSearchJSVersion}}/dist/cdn/docsearch.min.css"
/>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/docsearch.js@{{docSearchJSVersion}}/dist/cdn/docsearch.min.css"
/>
<!-- Before the closing </body> -->
<script
src="https://cdn.jsdelivr.net/npm/docsearch.js@{{docSearchJSVersion}}/dist/cdn/docsearch.min.js"></script>
<script>
docsearch({
// Your apiKey and indexName will be given to you once
<script
src="https://cdn.jsdelivr.net/npm/docsearch.js@{{docSearchJSVersion}}/dist/cdn/docsearch.min.js"></script>
<script>
docsearch({
// Your apiKey and indexName will be given to you once
// we create your config
apiKey: '<API_KEY>',
indexName: '<INDEX_NAME>',
// Replace inputSelector with a CSS selector
// Replace inputSelector with a CSS selector
// matching your search input
inputSelector: '<YOUR_CSS_SELECTOR>',
});
@ -37,8 +36,8 @@ If you're eager to test DocSearch but don't have credentials of your own yet,
you can use the one we use on this own website:
```javascript
docsearch({
apiKey: '25626fae796133dc1e734c6bcaaeac3c',
indexName: 'docsearch',
});
docsearch({
apiKey: '25626fae796133dc1e734c6bcaaeac3c',
indexName: 'docsearch',
});
```

View file

@ -3,25 +3,25 @@ layout: two-columns
title: FAQ
---
If you're not finding the answer to your question in the website, this
page will help you. If you're still unsure, don't hesitate to send [your
question to us][1] directly.
If you're not finding the answer to your question in the website, this page will
help you. If you're still unsure, don't hesitate to send [your question to
us][1] directly.
### How often will you crawl my website?
Every day.
The exact time of day might vary each day, but we'll crawl your
website at most every 24 hours. We will also trigger a manual crawling every time
your config is updated.
The exact time of day might vary each day, but we'll crawl your website at most
every 24 hours. We will also trigger a manual crawling every time your config is
updated.
### What do I need to install on my side?
Nothing.
The DocSearch crawler is running on our own infra. It will read HTML
content from your website and populate an Algolia index with it every day. All
you need to do is keep your website online, and we take care of the rest.
The DocSearch crawler is running on our own infra. It will read HTML content
from your website and populate an Algolia index with it every day. All you need
to do is keep your website online, and we take care of the rest.
### How much does it cost?
@ -29,24 +29,26 @@ Nothing.
We know that paying for search infrastructure is a cost not all Open Source
projects can afford. That's why we decided to keep DocSearch free for everyone.
All we ask in exchange is that you keep the _powered by
[Algolia][2]_ logo displayed next to the search results.
All we ask in exchange is that you keep the _powered by [Algolia][2]_ logo
displayed next to the search results.
If this is not possible for you, you're totally free to [open your own Algolia
If this is not possible for you, you're free to [open your own Algolia
account][3] and run DocSearch on your own without this limitation. In that case
though, depending on the size of your documentation, you might need a paid
account ([free accounts][4] can hold as much as 10k records).
### What data are you collecting?
The data we save in the index is the data we extract from your website
markup, in a custom JSON format instead of HTML. Which part of the
page is defined in your custom config.
The data we save in the index is the data we extract from your website markup,
in a custom JSON format instead of HTML. Which part of the page is defined in
your custom config.
As the website owner, we also give you access to the Algolia Analytics
dashboard, that will let you have more data about the anonymized searches that
were done on your website. You'll be able to see the most searched terms, or
those with no results.
were done on your website. You'll see the most searched terms, or those with no
results.
You will understand what people do not.
You will understand what people do not.
@ -55,14 +57,14 @@ _If you don't have Analytics access, send us an email and we'll enable it._
### Where is my data hosted?
All DocSearch data is hosted on Algolia's servers, with replication around the
globe. You can find more details about the actual [server specs here][5], and more
complete information in our [privacy policy][6].
globe. You can find more details about the actual [server specs here][5], and
more complete information in our [privacy policy][6].
### Can I use DocSearch on non-doc pages?
The free DocSearch we provide will crawl documentation pages. If you want
to use it on other parts of your website, you'll need to create your own Algolia
account and either:
The free DocSearch we provide will crawl documentation pages. To use it on other
parts of your website, you'll need to create your own Algolia account and
either:
- Run the [DocSearch crawler][7] on your own
- Use one of our other [framework integrations or API clients][8]
@ -71,9 +73,9 @@ account and either:
Yes, but we do not recommend it.
Code samples are a great way for humans to understand how a specific pattern
/ method should be used. It often requires boilerplate code though, repeated
across examples, which will add noise to the results.
Code samples are a great way for humans to understand how a specific pattern ap
alpha / method should be used. It often requires boilerplate code though,
repeated across examples, which will add noise to the results.
What we recommend instead is to exclude the code blocks from the indexing (by
using the `selectors_exclude` option in your config), and instead structure your
@ -81,33 +83,28 @@ content so the method names are actual headers.
### Why do I have duplicate content in my results?
This can happen when you have more than one urls pointing to the same content,
This can happen when you have more than one URL pointing to the same content,
for example with `./docs`, `./docs/` and `./docs/index.html` or even both `http`
and `https` in place.
This can be fixed by `stop_urls` to all the patterns you want to exclude. The
following example will exclude all urls ending with `/` or `index.html` as well
following example will exclude all URLs ending with `/` or `index.html` as well
as those starting with `http://`.
```json
{
"stop_urls": [
"/$",
"/index.html$",
"^http://"
]
"stop_urls": ["/$", "/index.html$", "^http://"]
}
```
### My favorite project documentation does not use DocSearch. What can I do?
### A documentation I like does not use DocSearch. What can I do?
We'd love to help!
If one of your favorite tool documentation is missing
DocSearch, we encourage you to file an issue in their repository explaining how
DocSearch could help. Feel free to ping `@docsearch` on GitHub in the issue as
well, and we'll provide all the help we can.
If one of your favorite tool documentation is missing DocSearch, we encourage
you to file an issue in their repository explaining how DocSearch could help.
Feel free to ping `@docsearch` on GitHub in the issue as well, and we'll provide
all the help we can.
[1]: mailto:docsearch@algolia.com
[2]: https://www.algolia.com/

View file

@ -3,36 +3,35 @@ layout: two-columns
title: How does it work?
---
Getting up and ready with DocSearch is a straightforward process that requires
a three steps: you apply, we configure the crawler for you, and you update your
front-end.
Getting up and ready with DocSearch is a straightforward process that requires a
three steps: you apply, we configure the crawler for you, and you update your
frontend.
<img src="./assets/docsearch-how-it-works.png" alt="How it works" class="mt-2"/>
### You apply
### 1. You apply
The first thing you'll need to do is to apply for DocSearch by filling the
form on this page (make sure to double check that you qualify first). We are
The first thing you'll need to do is to apply for DocSearch by filling the form
on this page (make sure to double check that you qualify first). We are
receiving a lot of requests, so this form makes sure we won't be forgetting
anyone.
We guarantee that we will answer to every request, but due to the amount of
applications we receive, please give us a couple of days to get back to you :)
We guarantee that we will answer to every request, but we receive a lot of
applications, so please give us a couple of days to get back to you :)
### 2. We create a configuration
### We create a configuration
Once we receive your application, we'll have a look at your website and create
a custom configuration file for it. This file defines which urls we
should crawl or ignore, as well as the specific CSS selectors to be used for
selecting headers, subheaders, etc. All configs are publicly available in our
[config repo][1].
Once we receive your application, we'll have a look at your website and create a
custom configuration file for it. This file defines which URLs we should crawl
or ignore, as well as the specific CSS selectors to be used for selecting
headers, subheaders, etc. All configs are publicly available in our [config
repository][1].
This step still requires some manual work, but thanks to the 900+ configs we
already created, we're able to automate most of it. Once done, we'll run a first
indexing of your website and have it run automatically every 24h.
### 3. You update your website
### You update your website
We'll then get back to you with the JavaScript snippet you'll need to add to
your website. This will bind your search `input` field to display results from
@ -49,6 +48,3 @@ All we ask is that you keep the "search by Algolia" logo next to your search
results.
[1]: https://github.com/algolia/docsearch-configs/tree/master/configs
[2]: https://github.com/algolia/docsearch-scraper
[3]: https://github.com/algolia/docsearch-scraper
[4]: https://www.sitemaps.org/

View file

@ -3,8 +3,8 @@ layout: two-columns
title: Inside the engine
---
This page will explain in more details how the crawler extracts content from your
page, and how it ranks it in the results.
This page will explain in more details how the crawler extracts content from
your page, and how it ranks it in the results.
## Crawling
@ -18,9 +18,9 @@ all pages.
## Extracting content
Then, for each page, it will read the HTML markup from top to bottom. It will
look for HTML elements matching your CSS `selectors`. It will specifically look
for elements matching your `text` selector (`<p>` by default). Each of those
matches will be later transformed into an Algolia record.
look for HTML elements matching your CSS `selectors`. It will look for elements
matching your `text` selector (`<p>` by default). Each of those matches will be
later transformed into an Algolia record.
For each matching `text` element, the crawler will also keep in memory the
current hierarchy of headers (identified by the `lvl0` to `lvl5` selectors) that
@ -36,30 +36,26 @@ overwrite your previous index.
## Ranking records
Algolia always returns the most relevant results first, using a [tie-breaking
approach][1]. DocSearch will first search for exact matches in your keywords then
fallback to partial matches. Those results will then be ordered based, once
approach][1]. DocSearch will first search for exact matches in your keywords
then fallback to partial matches. Those results will then be ordered based, once
again, on the page hierarchy, as extracted from the `selectors`.
The default strategy is to first look at the closest header of the matching
text. If a matching paragraph of text is under `Advanced Settings / API Options
/ verySpecificMethod()`, it will be ranked higher than if it is only found under
`Gettings Started > Installation`. The idea here is that if you have a match
under a very deep hierarchy, chances are that this match is very specific and
might be more interesting that something found in a very broad topic.
text. For example, a paragraph under `Settings / API / verySpecificMethod()`,
will be ranked higher than one under `Settings / API`. The idea here is that if
you have a match under a deep hierarchy, chances are that this match is specific
and might be more interesting that something found in a broad topic.
But this does not work in all cases as some documentations don't have deep
hierarchy. In that case, we use the paragraph position. The first paragraph of
the page will be ranked higher than the last one.
You also have a way to boost some pages directly in your config by using the
`page_rank` option. This accepts a numeric value, and all pages with
a `page_rank` of 5 will be returned before pages with a `page_rank` of 1.
`page_rank` option. This accepts a numeric value, and all pages with a
`page_rank` of 5 will be returned before pages with a `page_rank` of 1.
If you want to get fancy, you could even overwrite the default
`customRanking` used by the index by using the `custom_settings` option of
your config.
You could even overwrite the default `customRanking` used by the index by using
the `custom_settings` option of your config.
[1]: https://www.algolia.com/doc/guides/ranking/ranking-formula/#tie-breaking-approach
[2]: https://www.algolia.com/doc/guides/ranking/ranking-formula/#tie-breaking-approach
[3]: https://www.algolia.com/doc/guides/ranking/custom-ranking/
[1]:
https://www.algolia.com/doc/guides/ranking/ranking-formula/#tie-breaking-approach

View file

@ -4,21 +4,20 @@ title: Run your own
---
The version of DocSearch we provide for free is one hosted on our own servers,
running every 24 hours. If you need to update your results more often than that,
or need to index content sitting behind a firewall, you might want to run the
crawler yourself.
running every 24 hours. To update your results more often than that, or to index
content sitting behind a firewall, you might want to run the crawler yourself.
The code of DocSearch is Open-Source, and we packaged it as a Docker image to
The code of DocSearch is open source, and we packaged it as a Docker image to
make this even easier for you to use.
## Installation
Start by cloning [the repo][1] and then running `./docsearch docker:build` to
create the local image.
Start by cloning [the repository][1] and then running `./docsearch docker:build`
to create the local image.
Even if not recommended, you can run DocSearch directly from you host. For
that, you'll need to have `python` and `pip` installed, and then run `pip
install --user -r requirements.txt`.
Even if not recommended, you can run DocSearch directly from you host. For that,
you'll need to have `python` and `pip` installed, and then run
`pip install --user -r requirements.txt`.
## Configuration
@ -26,28 +25,29 @@ You'll need to set your Algolia application ID and admin API key as environment
variables. If you don't have an Algolia account, you should [create one][2].
- `APPLICATION_ID` should be set to your Application ID
- `API_KEY` should be set to your API Key. Make sure to use an API key with
**write** access to your index.
For convenience, you can create a `.env` file in the repository root with the
following format and DocSearch will use those values.
```
```sh
APPLICATION_ID=YOUR_APP_ID
API_KEY=YOUR_API_KEY
```
## Creating a new config
To create your config, run `./docsearch bootstrap`. A prompt will ask you for
a some information and will then output a JSON config you can use as a base.
To create your config, run `./docsearch bootstrap`. A prompt will ask you for a
some information and will then output a JSON config you can use as a base.
```sh
$ ./docsearch bootstrap
# Enter your documentation url
start url: http://www.example.com/docs/
start url: http://www.example.com/docs/
# You most probably don't need variables
Does the start_urls require variables ? [y/n]: n
Does the start_urls require variables ? [y/n]: n
# Pick another name, or press enter
index_name is example [enter to confirm]: <Enter>
@ -70,7 +70,7 @@ index_name is example [enter to confirm]: <Enter>
=================
```
Copy-paste the content into a file name `example.json`, we'll use it later to
Copy-paste the content into a filename `example.json`, we'll use it later to
start the crawling. You can find the complete list of available options in [our
documentation][3], or browse the [list of live configs][4].
@ -88,14 +88,14 @@ Algolia.
## Testing your results
You can test your results by running `./docsearch playground`. This will open
a web page with a search input where you can do live tests against the indexed
You can test your results by running `./docsearch playground`. This will open a
web page with a search input where you can do live tests against the indexed
results.
<img src="./assets/playground.png" alt="Playground" class="mt-2"/>
_Note that if the command fails (it can happen on non-Mac machines), you can get
the same result by running a live server in the `./playground` subdirectory.`_
the same result by running a live server in the `./playground` subdirectory.\`_
## Integration
@ -103,9 +103,8 @@ Once you're satisfied with your config, you can integrate the dropdown menu in
your website by following the [instructions here][5].
The difference is that you'll also have to add the `appId` key to your
`docsearch()` instance. Also don't forget to use a **search** API key here (ie.
not the **write** API key you used for the crawling).
`docsearch()` instance. Also don't forget to use a **search** API key here (in
other words, not the **write** API key you used for the crawling).
```javascript
docsearch({
@ -120,8 +119,8 @@ docsearch({
You can run `./docsearch` without any argument to see the list of all available
commands.
Note that we use this CLI tool internally at Algolia to run the free hosted
version, so you might not need all the listed commands.
Note that we use this command-line tool internally at Algolia to run the free
hosted version, so you might not need all the listed commands.
[1]: https://github.com/algolia/docsearch-scraper
[2]: https://www.algolia.com/pricing#community

View file

@ -12,6 +12,15 @@
-moz-osx-font-smoothing: grayscale;
}
/**
* We're centering text in input by using a line-height equal to the height.
* It's still a few px off when using the Hind font, so we compensate with some padding
**/
input {
padding: 0.3rem 0 0 0;
}
/* Global styles */
a,
a:active {

View file

@ -38,7 +38,7 @@ The following annotated example will help you style each part:
/* Description description (eg. Bootstrap currently works...) */
.algolia-autocomplete .algolia-docsearch-suggestion--text {
font-size: .8rem;
font-size: 0.8rem;
color: gray;
}
@ -55,7 +55,7 @@ and you're encouraged to style it to fit your own theming. All we ask is that
you keep the `search by Algolia` logo and link next to your search results.
The logo is automatically added in the dropdown with the default styling. It's
ok to hide it through CSS, as long as you re-add it somewhere else on your page
OK to hide it through CSS, as long as you re-add it somewhere else on your page
close to the search input or search results. It's our way to let more people
know about what do, and how they could also have from fast and relevant search
on their website.
@ -65,9 +65,8 @@ yourself][3], you don't have to keep the logo.
## Debugging
If you want to inspect the dropdown markup with your browser tools, you should
add `debug: true` to your `docsearch` call to prevent it from closing on
inspection.
To inspect the dropdown markup with your browser tools, you should add
`debug: true` to your `docsearch` call to prevent it from closing on inspection.
```javascript
docsearch({
@ -78,27 +77,24 @@ docsearch({
## Other considerations
Selected suggestion are wrapped in a `.ds-cursor` class. This means
that you can use `.ds-cursor .algolia-docsearch-suggestion--content` to style
the selected suggestion for example.
Selected suggestion are wrapped in a `.ds-cursor` class. This means that you can
use `.ds-cursor .algolia-docsearch-suggestion--content` to style the selected
suggestion for example.
On small screens, DocSearch reverts to a single column layout, while the
two-column layout shown in the screenshot is used on larger screens. You can
media queries (for example `@media (min-width: 768px) {}`) to target one or the
other display.
## Advanced styling
If you want to more heavily style the results, feel free to have a look at the
[SCSS source code][4].
`_variables.scss` contains all the default theming, sizing and breakpoints.
You can generate your own CSS file by cloning the repo and running `yarn run
build:css`. The resulting file will be generated in `./dist/cdn`, and should be
used instead of the default one.
To more heavily style the results, feel free to have a look at the [SCSS source
code][4]. `_variables.scss` contains all the default theming, sizing and
breakpoints.
You can generate your own CSS file by cloning the repository and running
`yarn run build:css`. The resulting file will be generated in `./dist/cdn`, and
should be used instead of the default one.
[1]: ./assets/default-colorscheme.png
[2]: https://www.algolia.com/pricing

View file

@ -4,8 +4,8 @@ title: Tips for a good search
---
DocSearch can work with almost any website, but we found that some site
structure yield more relevant result and/or faster indexing time. In this page
we'll share some tips on how you can make the most out of DocSearch.
structure yield more relevant result or faster indexing time. In this page we'll
share some tips on how you can make the most out of DocSearch.
### Use a `sitemap.xml`
@ -35,38 +35,36 @@ DocSearch uses this structure to fine-tune the relevance of results as well as
to provide potential filtering. Documentation that follow this pattern often
have better relevance of search results.
_Note that you don't have to use `<hX>` tags and can use `<span
class="title-X">` for example instead. Your crawling configuration file will
need to mirror those changes, though._
_Note that you don't have to use `<hX>` tags and can use
`<span class="title-X">` for example instead. Your crawling configuration file
will need to mirror those changes, though._
### Set a unique class to the element holding the content
As DocSearch is extracting content based on the HTML structure, it is important
to narrow its results to only the relevant content. In that regard, we
recommend that you add a custom `id` to the HTML element that will be the parent
of all your textual content.
DocSearch is extracting content based on the HTML structure. We recommend that
you add a custom `class` to the HTML element wrapping all your textual content.
This will help narrow selectors to the relevant content.
Having such a unique identifier will make your configuration more robust as it
will make sure all content that is indexed is relevant content. We found that
this is the most reliable way to exclude headers, sidebars and footers content
that are not relevant to the search.
will make sure all indexed content is relevant content. We found that this is
the most reliable way to exclude headers, sidebars and footers content that are
not relevant to the search.
### Add anchors to headings
When using headings (as mentioned above), you should also try to add a custom
anchor to each of them. Anchors are HTML attributes (`name` or `id`)
added to headers that will allow the browser to directly scroll to the right
position in the page when clicking a link with a `#` in it.
anchor to each of them. Anchors are HTML attributes (`name` or `id`) added to
headers that will allow the browser to directly scroll to the right position in
the page when clicking a link with a `#` in it.
DocSearch will honor such anchors and automatically bring your users to the
anchor closest to the search result they selected.
### Marking the active page(s) in the navigation
If you're using a multi-level navigation, we recommend that you mark
each active level with a custom CSS class. This will make it easier for
DocSearch to know _where_ the current page fits in the website
hierarchy.
If you're using a multi-level navigation, we recommend that you mark each active
level with a custom CSS class. This will make it easier for DocSearch to know
_where_ the current page fits in the website hierarchy.
For example, if your `troubleshooting.html` page is located under the
`Installation` menu in your sidebar, we recommend that you add a custom CSS
@ -75,5 +73,4 @@ class to the `Installation` and `Troubleshooting` links in your sidebar.
The name of the CSS class does not matter, as long as it's something that can be
used as part of a CSS selector.
[1]: https://www.sitemaps.org/index.html

View file

@ -4,24 +4,27 @@ title: What is DocSearch?
---
DocSearch is born out of the need to scratch our own itch. As developers, we
spent a lot of time reading documentation, and we often found it hard to find
relevant information we need quickly. We're not blaming anyone here; building
a good search is a challenge.
spent a lot of time reading documentation, and it can be hard to find relevant
information in large documentations. We're not blaming anyone here; building a
good search is a challenge.
It just happens that we are a search company and we actually have a lot of
experience building search interfaces. We wanted to put those skills to good
use. That's why we created a way to automatically extract content from tech
documentation and make it available to everyone with only a few keystrokes.
It happens that we are a search company and we actually have a lot of experience
building search interfaces. We wanted to use those skills to help others. That's
why we created a way to automatically extract content from tech documentation
and make it available to everyone from the first keystroke.
DocSearch itself is made of a crawler and a front-end library. We run the
crawler on our end every 24h to extract content from your website and push it to
an Algolia index. You'll then have to add the front-end library to your website
to redirect all the search requests to this index.
DocSearch itself is made of a crawler and a frontend library. We run the crawler
on our end every 24h to extract content from your website and push it to an
Algolia index. You'll then have to add the frontend library to your website to
redirect all the search requests to this index.
DocSearch is entirely free and mostly automated. The only thing we'll need from
you is to check that you're eligible (most tech projects are), and apply! After
that, we'll share with you the JavaScript snippet needed to add DocSearch to
your website. We just ask that you keep the "powered by Algolia" link displayed.
DocSearch is entirely free and automated. The one thing we'll need from you is
to read [our checklist][2] and apply! After that, we'll share with you the
JavaScript snippet needed to add DocSearch to your website. We ask that you keep
the "powered by Algolia" link displayed.
DocSearch is [one of our ways](https://opencollective.com/algolia) to give back
to the Open-Source community for everything it did for us already.
DocSearch is [one of our ways][1] to give back to the open source community for
everything it did for us already.
[1]: https://opencollective.com/algolia
[2]: ./who-can-apply.html

View file

@ -3,52 +3,54 @@ layout: two-columns
title: Who can apply?
---
DocSearch has been built from the ground up with the idea of improving search on
large technical documentation. For that reason, we only provide the free hosting
version to technical documentation websites.
DocSearch was built from the ground up with the idea of improving search on
large technical documentation. For that reason, we offering our free hosting
version to all technical documentations.
We're always sad to have to turn down applications, but with the number of
requests we received everyday, we had to focus on technical documentations.
We hope you understand.
requests we received everyday, we had to focus on technical documentations. We
hope you understand.
### The checklist
To have your request validated, please make sure you comply with the following
points:
To have your request validated, we'll ask that you valide all the following
points.
- You must be the **owner** of the website, or at least have the power to update
its content. You'll have to include a JavaScript snippet to enable DocSearch.
- Your website must be **publicly available**. We cannot index websites that are
sitting behind an authentication or available on your machine.
- Your website must be a **documentation website**. We do not index blogs and
commercial one-pagers.
- Your website must **have some content**. We won't index empty websites nor those
filled with lorem ipsum placeholder content. Please, wait until you have
- Your website must **have some content**. We won't index empty websites nor
those filled with lorem ipsum placeholder content. Please, wait until you have
written some documentation before applying.
If in doubt, don't hesitate to [apply][1] and we'll figure it out together.
Even if we cannot accept your request, this does not mean that you cannot enjoy
great search on your website. DocSearch is entirely open-source and you can run
great search on your website. DocSearch is entirely open source and you can run
it yourself, or use any of our other API clients to take advantage of the
features of Algolia.
### Priority
We're receiving many requests every day, and while we strive to answer them all
as fast as we can, we sometimes give priority to some of them based on the
We're receiving dozens of requests every day, and while we strive to answer them
all as fast as we can, we sometimes give priority to some of them based on the
following criteria:
- 🙂 If your project is Open-Source, we'll handle it before any other
close-source product. We care about the OSS community and want to help as much
as we can.
- 🙂 If your project is open source, We'll handle it before any other
close-source product. We love open source and want to help as much as we can.
- 🙂 If you're using one of our [official integrations][2], creating your config
will be much faster for us.
- ☹️ If your website is rendered in the browser through JavaScript, it means
that we'll have to crawl it through a browser emulation which is much slower
than a typical crawl. We highly recommend that you implement server-side
rendering if you can.
- ☹️ If your website is rendered in the browser through JavaScript, it means
that we'll have to crawl it through a much slower browser emulation. We highly
recommend that you put in place server-side rendering if you can.
[1]: ./apply.html
[2]: ./integrations.html

View file

@ -87,49 +87,15 @@ const colors = {
'white-90': 'rgba(255, 255, 255, .90)',
};
const dimensionScale = {
auto: 'auto',
'0': '0',
'1': '1rem',
'1x': '1.5rem',
'2': '2rem',
'2x': '3rem',
'3': '4rem',
'3x': '6rem',
'4': '8rem',
'4x': '12rem',
'5': '16rem',
'10': '10%',
'20': '20%',
'25': '25%',
'30': '30%',
'33': 'calc(100% / 3)',
'40': '40%',
'50': '50%',
'60': '60%',
'66': 'calc(100% / 1.5)',
'70': '70%',
'75': '75%',
'80': '80%',
'90': '90%',
'100': '100%',
full: '100%',
const screenSizes = {
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
};
const widthScale = {
...dimensionScale,
'100vw': '100vw',
};
const heightScale = {
...dimensionScale,
'100vh': '100vh',
};
const spacingScale = {
const dimensionScale = {
auto: 'auto',
'0': '0',
'0x': '.25rem',
'05': '.5rem',
@ -157,10 +123,9 @@ const spacingScale = {
'80': '80%',
'90': '90%',
'100': '100%',
};
const marginScale = {
...spacingScale,
auto: 'auto',
'100vw': '100vw',
'100vh': '100vh',
...screenSizes,
};
const fontScale = {
@ -177,6 +142,24 @@ const fontScale = {
'8': '3.5rem', // 56px
};
// Leading (line-height) uses values proportional to the current font-size.
// In addition, it also allows setting it to exact values found in the font and
// dimension scales.
// .leading-2 => Proportional to the current font size
// .leading-text-2 => Using exact font size
// .leading-h-2 => Using exact dimension size
const leadingScale = {
0: '1',
1: '1.25',
2: '1.5',
};
_.each(dimensionScale, (value, key) => {
leadingScale[`h-${key}`] = value;
});
_.each(fontScale, (value, key) => {
leadingScale[`text-${key}`] = value;
});
const fontWeights = {
hairline: 100,
thin: 200,
@ -219,6 +202,26 @@ const opacity = {
'100': '1',
};
const shadows = {
button:
'0 7px 14px -3px rgba(45, 35, 66, 0.3), 0 2px 4px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #cfd1e3',
'button-up':
'0 11px 16px -3px rgba(45, 35, 66, 0.3), 0 4px 5px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #cfd1e3',
'button-down':
'inset 0 2px 0 1px rgba(132, 138, 184, 0.11), inset 0 2px 9px 0 rgba(93, 100, 148, 0.5), inset 0 -1px 0 1px #fff',
'button-primary':
'0 7px 14px -3px rgba(45, 35, 66, 0.3), 0 2px 4px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #4b58ba;',
'button-primary-up':
'0 11px 16px -3px rgba(45, 35, 66, 0.3), 0 4px 5px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #4b58ba;',
'button-primary-down':
'inset 0 2px 0 1px rgba(132, 138, 184, 0.11), inset 0 2px 9px 0 rgba(93, 100, 148, 0.5), inset 0 -1px 0 1px #5468ff;',
'1':
'0 5px 15px 0 rgba(37, 44, 97, 0.15), 0 2px 4px 0 rgba(93, 100, 148, 0.2)',
none: 'none',
};
// Use font-weight without prefixes (.bold, .thin, etc)
const customFontWeight = _.reduce(fontWeights, (result, value, key) =>
_.assign(result, {
@ -292,9 +295,9 @@ const customFlexbox = {
justifyContent: 'space-between',
},
};
// Use the spacing scale for top/right/bottom/let positioning
// Use the dimension scale for top/right/bottom/left positioning
const customPositions = _.reduce(
spacingScale,
dimensionScale,
(result, value, key) =>
_.assign(result, {
[`top-${key}`]: { top: value },
@ -338,36 +341,37 @@ const plugins = [
];
module.exports = {
width: dimensionScale,
minWidth: dimensionScale,
maxWidth: dimensionScale,
height: dimensionScale,
minHeight: dimensionScale,
maxHeight: dimensionScale,
padding: dimensionScale,
margin: dimensionScale,
negativeMargin: dimensionScale,
textSizes: fontScale,
leading: leadingScale,
fontWeights,
width: widthScale,
minWidth: widthScale,
maxWidth: widthScale,
height: heightScale,
minHeight: heightScale,
maxHeight: heightScale,
padding: spacingScale,
margin: marginScale,
negativeMargin: marginScale,
colors,
textColors: colors,
backgroundColors: colors,
borderColors: global.Object.assign({ default: colors['grey-light'] }, colors),
zIndex,
opacity,
borderRadius,
shadows,
plugins,
screens: {
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
...screenSizes,
print: { raw: 'print' },
},
textColors: colors,
backgroundColors: colors,
borderWidths: {
default: '1px',
'0': '0',
@ -375,7 +379,6 @@ module.exports = {
'2': '4px',
'3': '8px',
},
borderColors: global.Object.assign({ default: colors['grey-light'] }, colors),
fonts: {
sans: [
'system-ui',
@ -412,14 +415,6 @@ module.exports = {
'monospace',
],
},
// Line-height
leading: {
'0': '0',
'01': 1,
'1': 1.25,
'2': 1.5,
'3': 2,
},
// Letter-spacing
tracking: {
tight: '-0.05em',
@ -427,25 +422,6 @@ module.exports = {
wide: '0.05em',
poppins: '1.5px',
},
shadows: {
button:
'0 7px 14px -3px rgba(45, 35, 66, 0.3), 0 2px 4px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #cfd1e3',
'button-up':
'0 11px 16px -3px rgba(45, 35, 66, 0.3), 0 4px 5px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #cfd1e3',
'button-down':
'inset 0 2px 0 1px rgba(132, 138, 184, 0.11), inset 0 2px 9px 0 rgba(93, 100, 148, 0.5), inset 0 -1px 0 1px #fff',
'button-primary':
'0 7px 14px -3px rgba(45, 35, 66, 0.3), 0 2px 4px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #4b58ba;',
'button-primary-up':
'0 11px 16px -3px rgba(45, 35, 66, 0.3), 0 4px 5px 0 rgba(45, 35, 66, 0.4), inset 0 -2px 0 0 #4b58ba;',
'button-primary-down':
'inset 0 2px 0 1px rgba(132, 138, 184, 0.11), inset 0 2px 9px 0 rgba(93, 100, 148, 0.5), inset 0 -1px 0 1px #5468ff;',
'1':
'0 5px 15px 0 rgba(37, 44, 97, 0.15), 0 2px 4px 0 rgba(93, 100, 148, 0.2)',
none: 'none',
},
svgFill: {
current: 'currentColor',
},

7090
docs/yarn.lock Normal file

File diff suppressed because it is too large Load diff

10
netlify.toml Normal file
View file

@ -0,0 +1,10 @@
[Settings]
[build]
[build.environment]
NODE_ENV = "development"
YARN_VERSION = "1.9.4"
# Deploy documentation website on each commit on master
[context.master]
command = "./scripts/netlify-master"

View file

@ -10,13 +10,13 @@
"docs:build": "cd ./docs && yarn build",
"docs:serve": "cd ./docs && yarn serve",
"docs:deploy": "cd ./docs && yarn deploy",
"doctoc": "doctoc --maxlevel 3 README.md CONTRIBUTING.md",
"lint": "./scripts/lint",
"release": "./scripts/release",
"release:beta": "./scripts/release-beta",
"serve": "./scripts/serve",
"test": "./scripts/test",
"test:watch": "./scripts/test-watch"
"test:watch": "./scripts/test-watch",
"postinstall": "cd ./docs && yarn install"
},
"files": [
"dist/"
@ -46,19 +46,18 @@
"babel-plugin-rewire": "1.1.0",
"babel-preset-env": "1.7.0",
"babel-preset-stage-3": "6.24.1",
"conventional-changelog-cli": "2.0.1",
"cssnano": "4.0.5",
"doctoc": "1.3.1",
"conventional-changelog-cli": "2.0.5",
"cssnano": "4.1.0",
"eslint": "5.4.0",
"eslint-config-algolia": "13.1.0",
"eslint-config-prettier": "2.10.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jest": "21.21.0",
"eslint-plugin-jest": "21.22.0",
"eslint-plugin-prettier": "2.6.2",
"jest": "23.0.0",
"jest": "23.5.0",
"jsdom": "11.12.0",
"json": "9.0.6",
"live-server": "^1.2.0",
"live-server": "1.2.0",
"mversion": "1.12.0",
"node-sass": "4.9.3",
"onchange": "4.1.0",
@ -67,9 +66,9 @@
"pretty-bytes-cli": "2.0.0",
"semver": "5.5.1",
"sinon": "6.1.5",
"uglify-js": "3.4.7",
"uglify-js": "3.4.8",
"webpack": "3.12.0",
"webpack-cli": "^3.1.0"
"webpack-cli": "3.1.0"
},
"peerDependencies": {},
"dependencies": {

54
scripts/netlify-master Executable file
View file

@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -e
# This file is run on Netlify for every new push on master (check netlify.toml
# for details)
# ===== STOP IF NO ./DOCS CHANGES
# We compare the date of last modification of the ./docs folder with the date of
# last deploy. If we have recent changes, we deploy, otherwise we skip
DOCS_UPDATE_LOCAL=$(git log -1 --pretty="format:%ct" ./docs)
DOCS_UPDATE_PRODUCTION=$(curl -s https://raw.githubusercontent.com/algolia/docsearch/gh-pages/last_update)
# This is the very first deploy, it should always go through
if ! [[ $DOCS_UPDATE_PRODUCTION =~ ^[0-9]*$ ]]; then
DOCS_UPDATE_PRODUCTION=0
fi
# Check if the local changes are fresher than the last push
TIME_DIFFERENCE=$((DOCS_UPDATE_LOCAL - DOCS_UPDATE_PRODUCTION));
if [[ $TIME_DIFFERENCE -le 0 ]]; then
echo "Documentation deployment is skipped: no new content";
exit 0
fi
# ===== BUILD
cd ./docs
yarn build
# ==== DEPLOY TO GH-PAGES
# Configuring the user making the push
git config --global user.email "algobot@users.noreply.github.com"
git config --global user.name "algobot"
# Adding the remote:
# Note: We need to wrap it in a conditional to not re-add a remote that already
# exists (can happen with the way Netlify caches builds). Attempting to add
# a remote that already exists will generate an error.
if ! git config remote.origin.url > /dev/null; then
git remote add origin git@github.com:algolia/docsearch.git
fi
# Configure the ssh private key
# The public key is configured as part of GitHub Deploy keys.
# The private key is stored in an environment variable (with underscore instead
# of newlines as Netlify does not allow for new lines). We convert it and store
# it in a file, then tell git to use it
mkdir -p ~/.ssh
echo -e "${GITHUB_DEPLOY_KEY_PRIVATE//_/\\n}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no"
# We add a file that contains the last updated date, to use on the next deploy
echo "$DOCS_UPDATE_LOCAL" > ./dist/last_update
yarn gh-pages -d dist

8161
yarn.lock Normal file

File diff suppressed because it is too large Load diff