Skip to content

feat(docs): algolia powered search #2952

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Apr 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
aa27914
feat(docs): add algolia search
jacobmllr95 Mar 29, 2019
c9f4890
Update search.vue
tmorehouse Mar 30, 2019
ed34157
Update search.vue
tmorehouse Mar 31, 2019
e1cf0fa
Merge remote-tracking branch 'upstream/dev' into feat-docs-algolia-se…
jacobmllr95 Mar 31, 2019
5a7487e
add algolia API key + search improvemnts
jacobmllr95 Mar 31, 2019
53b09b1
Update styles.scss
tmorehouse Mar 31, 2019
60e2a91
Update styles.scss
tmorehouse Mar 31, 2019
3b53955
Update search.vue
tmorehouse Mar 31, 2019
c0afa95
Update _slug.vue
tmorehouse Mar 31, 2019
081a7c6
Update _slug.vue
tmorehouse Mar 31, 2019
cb5c7fe
Update index.js
tmorehouse Mar 31, 2019
97a343a
Update play.vue
tmorehouse Mar 31, 2019
7244f59
Update index.js
tmorehouse Mar 31, 2019
9c8a9e8
Update styles.scss
tmorehouse Mar 31, 2019
fbda4a5
Update componentdoc.vue
tmorehouse Mar 31, 2019
a2fb748
Update importdoc.vue
tmorehouse Mar 31, 2019
246181f
Update nuxt.config.js
tmorehouse Mar 31, 2019
75cda65
Update importdoc.vue
tmorehouse Mar 31, 2019
88bb8eb
Update importdoc.vue
tmorehouse Mar 31, 2019
335afe9
Update componentdoc.vue
tmorehouse Apr 1, 2019
54a3813
Update nuxt.config.js
tmorehouse Apr 1, 2019
9d189cb
Update styles.scss
tmorehouse Apr 1, 2019
f5686d9
Update importdoc.vue
tmorehouse Apr 1, 2019
01f2236
Update styles.scss
tmorehouse Apr 1, 2019
1240522
Update styles.scss
tmorehouse Apr 1, 2019
c2e429f
Update nuxt.config.js
tmorehouse Apr 1, 2019
985ae55
Update styles.scss
tmorehouse Apr 1, 2019
3e7f494
Update styles.scss
tmorehouse Apr 1, 2019
dec52df
Update componentdoc.vue
tmorehouse Apr 1, 2019
035e340
Update importdoc.vue
tmorehouse Apr 1, 2019
32571d3
Merge branch 'dev' into feat-docs-algolia-search
jacobmllr95 Apr 1, 2019
f6e5657
Update styles.scss
tmorehouse Apr 1, 2019
71bb457
Update styles.scss
tmorehouse Apr 1, 2019
3717be6
Update styles.scss
tmorehouse Apr 1, 2019
9eb3f1c
Update styles.scss
jacobmllr95 Apr 1, 2019
a23872f
Update styles.scss
tmorehouse Apr 1, 2019
be99021
Merge branch 'dev' into feat-docs-algolia-search
jacobmllr95 Apr 1, 2019
75554fa
Update search.vue
jacobmllr95 Apr 1, 2019
de5f004
Merge branch 'feat-docs-algolia-search' of https://github.com/jackmu9…
jacobmllr95 Apr 1, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions docs/assets/scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,46 @@ pre.editable.error:after {
background-color: rgba(255, 0, 0, 0.1);
}

/* Additional styling for (responsive) markdown tables */
.bv-docs-table {
font-size: 90%;

thead > tr > th {
min-width: 80px;
}

code {
white-space: nowrap !important;
}
}

/* CSS for table transition example */
table#table-transition-example {
.flip-list-move {
transition: transform 1s;
}
}

/*
* Docsearch overrides
* See: https://github.com/twbs/bootstrap/blob/master/site/static/docs/4.3/assets/scss/_algolia.scss
*/
.algolia-autocomplete {
.ds-dropdown-menu {
background: #fff !important;
border: 1px solid rgba(0, 0, 0, 0.1) !important;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.175) !important;

.ds-suggestions {
@media (min-width: 768px) {
max-height: calc(100vh - 12rem);
overflow-y: auto;
}

.algolia-docsearch-suggestion--subcategory-inline,
.algolia-docsearch-suggestion--title {
display: inline-block !important;
}
}
}
}
14 changes: 12 additions & 2 deletions docs/components/componentdoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
<b-table
:items="propsItems"
:fields="propsFields"
class="bv-docs-table"
responsive="sm"
small
head-variant="default"
striped
Expand Down Expand Up @@ -60,6 +62,8 @@
<b-table
:items="[componentVModel]"
:fields="['prop', 'event']"
class="bv-docs-table"
responsive="sm"
small
head-variant="default"
striped
Expand All @@ -81,6 +85,8 @@
<b-table
:items="slots"
:fields="slotsFields"
class="bv-docs-table"
responsive="sm"
small
head-variant="default"
striped
Expand All @@ -98,6 +104,8 @@
<b-table
:items="events"
:fields="eventsFields"
class="bv-docs-table"
responsive="sm"
small
head-variant="default"
striped
Expand All @@ -110,7 +118,7 @@
v-for="arg in value"
:key="`event-${item.event}-${arg.arg ? arg.arg : 'none'}`"
>
<template v-if="arg.arg"><code>{{ arg.arg }}</code> - </template>
<template v-if="arg.arg"><code class="text-nowrap">{{ arg.arg }}</code> - </template>
<span>{{ arg.description }}</span>
</div>
</template>
Expand All @@ -128,6 +136,8 @@
<b-table
:items="rootEventListeners"
:fields="rootEventListenersFields"
class="bv-docs-table"
responsive="sm"
small
head-variant="default"
striped
Expand All @@ -141,7 +151,7 @@
:key="`event-${item.event}-${arg.arg ? arg.arg : 'none'}`"
>
<template v-if="arg.arg">
<code>{{ arg.arg }}</code>
<code class="text-nowrap">{{ arg.arg }}</code>
<span v-if="arg.description"> - {{ arg.description }}</span>
</template>
</div>
Expand Down
21 changes: 17 additions & 4 deletions docs/components/importdoc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@
Importing individual {{ pluginTitle }} Components
</anchored-heading>

<b-table :items="componentImports" small head-variant="default" striped>
<b-table
:items="componentImports"
class="bv-docs-table"
small
striped
head-variant="default"
>
<template slot="component" slot-scope="{ value }">
<code class="text-nowrap">{{ value }}</code>
</template>
<template slot="importPath" slot-scope="{ value }">
<code>{{ value }}</code>
<code class="text-nowrap">{{ value }}</code>
</template>
</b-table>

Expand All @@ -30,12 +36,19 @@
Importing individual {{ pluginTitle }} Directives
</anchored-heading>

<b-table :items="directiveImports" small head-variant="default" striped>
<b-table
:items="directiveImports"
class="bv-docs-table"
small
striped
responsive="sm"
head-variant="default"
>
<template slot="directive" slot-scope="{ value }">
<code class="text-nowrap">{{ value }}</code>
</template>
<template slot="importPath" slot-scope="{ value }">
<code>{{ value }}</code>
<code class="text-nowrap">{{ value }}</code>
</template>
</b-table>

Expand Down
163 changes: 62 additions & 101 deletions docs/components/search.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<template>
<div class="bd-search d-flex align-items-center">
<form
class="bd-search d-flex align-items-center"
@submit.stop.prevent
>
<b-form-input
id="bd-search-input"
v-model="search"
autocomplete="off"
type="search"
placeholder="Search keywords..."
aria-label="Search site"
placeholder="Search..."
aria-label="Search docs"
></b-form-input>
<button
v-b-toggle.bd-docs-nav
Expand All @@ -32,119 +34,78 @@
/>
</svg>
</button>
<b-popover target="bd-search-input" placement="bottom" triggers="focus">
<span v-if="search.length && Object.keys(results).length === 0">No results found</span>
<span v-else-if="search.length"></span>
<span v-else>Type something to start search</span>

<div
v-for="(results, section, idx) in results"
:key="section"
:class="idx > 0 ? 'mt-2' : ''"
role="group"
>
<h6 class="bd-text-purple my-1" v-html="section"></h6>
<div v-for="t in results" :key="t.href" class="my-1">
<b-link :to="t.href" @click="search = ''" v-html="t.title"></b-link>
</div>
</div>
</b-popover>
</div>
</form>
</template>

<script>
import groupBy from 'lodash/groupBy'
import intersectionBy from 'lodash/intersectionBy'
import { makeTOC } from '~/utils'
import { components, directives, reference, misc } from '~/content'

const SEARCH = []

const process = (readme, section, page) => {
const baseURL = '/' + ['docs', section, page].filter(v => !!v).join('/')
const { title, toc } = makeTOC(readme)
;[...toc].forEach(({ label, href }) => {
SEARCH.push({
section: title,
title: label,
href: `${baseURL}${href}`.replace('/#', '#')
})
})
}
import { relativeUrl } from '../utils'

// Async build the search database
import('~/markdown/intro/README.md' /* webpackChunkName: "docs/intro" */).then(readme =>
process(readme.default, '', '')
)
Object.keys(components).forEach(page => {
import(`~/../src/components/${page}/README.md` /* webpackChunkName: "docs/components" */).then(
readme => process(readme.default, 'components', page)
)
})
Object.keys(directives).forEach(page => {
import(`~/../src/directives/${page}/README.md` /* webpackChunkName: "docs/directives" */).then(
readme => process(readme.default, 'directives', page)
)
})
Object.keys(reference).forEach(page => {
import(`~/markdown/reference/${page}/README.md` /* webpackChunkName: "docs/reference" */).then(
readme => process(readme.default, 'reference', page)
)
})
Object.keys(misc).forEach(page => {
import(`~/markdown/misc/${page}/README.md` /* webpackChunkName: "docs/misc" */).then(readme =>
process(readme.default, 'misc', page)
)
})
let scriptsInjected = false

export default {
data() {
return {
search: ''
docsearch: null
}
},
computed: {
results() {
if (!this.search.length) {
return {}
mounted() {
this.loadDocsearch().then(this.initDocsearch)
},
methods: {
async loadDocsearch() {
if (scriptsInjected) {
return
}

// Break the searh into individual terms
const terms = this.search
.replace(/\s+/g, ' ')
.split(/\s+/)
.filter(t => t)
if (terms.length === 0) {
return {}
}
// Search indexing config stored at:
// https://github.com/algolia/docsearch-configs/blob/master/configs/bootstrap-vue.json

// Find results for each term
let results = terms.map(term => this.resultsFor(term))
const cdnBaseUrl = '//cdn.jsdelivr.net/docsearch.js/2/'
const $body = document.body

// If no results return emptiness
if (results.length === 0) {
return {}
}
// Load JS
const loadJs = new Promise(resolve => {
let $script = document.createElement('script')
$script.setAttribute('type', 'text/javascript')
$script.setAttribute('src', `${cdnBaseUrl}docsearch.min.js`)
$body.appendChild($script)
$script.onload = resolve
})

// Add our intersectionBy 'iteratee' key as the last array entry
results.push('href')
// Find the intersection (common) of all individual term results (all retults ANDed)
results = intersectionBy(...results)
// Load CSS
const loadCss = new Promise(resolve => {
let $link = document.createElement('link')
$link.setAttribute('rel', 'stylesheet')
$link.setAttribute('type', 'text/css')
$link.setAttribute('href', `${cdnBaseUrl}docsearch.min.css`)
$body.appendChild($link)
$link.onload = resolve
})

// Return the first 6 results or an empty array
return groupBy(results.slice(0, 6), 'section')
}
},
methods: {
resultsFor(term) {
// Return the search entries for a particular search term
const regex = new RegExp(`\\b${term}`, 'i')
return SEARCH.reduce((results, item) => {
if (regex.test(item.title) || regex.test(item.section)) {
results.push(item)
}
return results
}, [])
await Promise.all([loadJs, loadCss])

scriptsInjected = true
},
initDocsearch() {
if (this.docsearch) {
return
}
// Initialize docsearch
this.docsearch = window.docsearch({
apiKey: 'c816d3054b015320f0cfb40042f7e2bc',
indexName: 'bootstrap-vue',
inputSelector: '#bd-search-input',
transformData(hits) {
return hits.map(function(hit) {
// Transform URL to a relative URL
hit.url = relativeUrl(hit.url)

return hit
})
},
// Set debug to `true` if you want to inspect the dropdown
debug: false
})
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions docs/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ renderer.heading = function(text, level, raw, slugger) {
// BS4 table support for markdown renderer
const originalTable = renderer.table
renderer.table = function(header, body) {
let r = originalTable.apply(this, arguments)
return r
.replace('<table>', '<table class="table b-table table-striped">')
let table = originalTable.apply(this, arguments)
table = table
.replace('<table>', '<table class="table b-table table-striped table-sm bv-docs-table">')
.replace('<thead>', '<thead class="thead-default">')
return `<div class="table-responsive-sm">${table}</div>`
}

module.exports = {
Expand Down
3 changes: 2 additions & 1 deletion docs/pages/docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
defaultConfig
}
},
template: `<div class="container bd-content">${readme}</div>`,
// We use a string template here so that the docs README can do interpolation
template: `<main class="container"><div class="bd-content">${readme}</div></main>`,
layout: 'docs'
}
4 changes: 2 additions & 2 deletions docs/pages/docs/misc/_slug.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="container">
<main class="container">
<div class="bd-content" v-html="readme"></div>
</div>
</main>
</template>

<script>
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/docs/reference/_slug.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="container">
<main class="container">
<div v-play class="bd-content" v-html="readme"></div>
</div>
</main>
</template>

<script>
Expand Down
Loading