├── cypress.json ├── .gitignore ├── cypress ├── fixtures │ └── example.json ├── plugins │ └── index.js ├── support │ ├── index.js │ └── commands.js └── integration │ ├── github-link.spec.js │ └── search_spec.js ├── docs ├── test-page-02.md └── test-page-01.md ├── scripts ├── node │ ├── validateNodeVersion.js │ └── validateNPMVersion.js └── createVersionValidator.js ├── README.md ├── src ├── pages │ ├── 404.js │ └── index.js ├── components │ ├── NavigationItem.js │ ├── VerticalNavigationList.js │ └── Search.js ├── layouts │ ├── index.js │ └── index.css └── templates │ └── default.js ├── .travis.yml ├── LICENSE.md ├── gatsby-config.js ├── CONTRIBUTING.md ├── gatsby-node.js ├── package.json ├── package-scripts.js └── .gitattributes /cypress.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project dependencies 2 | node_modules 3 | .cache/ 4 | # Build directory 5 | public/ 6 | .DS_Store 7 | cypress/screenshots 8 | -------------------------------------------------------------------------------- /cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } -------------------------------------------------------------------------------- /docs/test-page-02.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Page 2 3 | keywords: 4 | - three 5 | - two 6 | --- 7 | 8 | # Page 2 9 | 10 | Page 2 11 | 12 | # Matching Keywords 13 | 14 | * two 15 | * three 16 | -------------------------------------------------------------------------------- /docs/test-page-01.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Test Page 1 3 | keywords: 4 | - one 5 | - two 6 | --- 7 | 8 | # Page 1 9 | 10 | This is the first test page. 11 | 12 | # Matching Keywords 13 | 14 | * one 15 | * two 16 | -------------------------------------------------------------------------------- /scripts/node/validateNodeVersion.js: -------------------------------------------------------------------------------- 1 | const {engines} = require('../../package.json'); 2 | const createVersionValidator = require('../createVersionValidator'); 3 | 4 | createVersionValidator('node')(engines.node, process.version); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo Site 2 | 3 | Demo site for `gatsby-plugin-elasticlunr-search` 4 | 5 | # Contributing 6 | 7 | See [`CONTRIBUTING.md`](./CONTRIBUTING.md) 8 | 9 | # Other Resources 10 | 11 | * [`LICENSE`](./LICENSE.md) 12 | -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const NotFoundPage = () => ( 4 |
5 |

NOT FOUND

6 |

You just hit a route that doesn't exist...the sadness.

7 |
8 | ); 9 | 10 | export default NotFoundPage; 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | 4 | dist: trusty 5 | 6 | language: node_js 7 | node_js: 8 8 | 9 | cache: 10 | directories: 11 | - ~/.npm 12 | - node_modules 13 | 14 | install: 15 | - npm install 16 | 17 | before_script: 18 | - npm start & 19 | 20 | script: 21 | - npm start test/integration 22 | -------------------------------------------------------------------------------- /src/components/NavigationItem.js: -------------------------------------------------------------------------------- 1 | import Link from 'gatsby-link'; 2 | import React from 'react'; 3 | 4 | const NavigationItem = ({ depth, href, value }) => ( 5 |
6 | {value} 7 |
8 | ); 9 | 10 | NavigationItem.defaultProps = { 11 | depth: 0, 12 | }; 13 | 14 | export default NavigationItem; 15 | -------------------------------------------------------------------------------- /scripts/node/validateNPMVersion.js: -------------------------------------------------------------------------------- 1 | const {execSync} = require(`child_process`); 2 | const createVersionValidator = require('../createVersionValidator'); 3 | const {engines} = require('../../package.json'); 4 | 5 | let npmVersion; 6 | try { 7 | npmVersion = execSync(`npm --version`) 8 | .toString() 9 | .trim(); 10 | } 11 | catch (error) { 12 | throw new Error('NPM not found.'); 13 | } 14 | 15 | createVersionValidator('node')(engines.npm, npmVersion); -------------------------------------------------------------------------------- /scripts/createVersionValidator.js: -------------------------------------------------------------------------------- 1 | const semver = require('semver'); 2 | 3 | module.exports = subject => (desiredVersion, actualVersion) => { 4 | if (!actualVersion) { 5 | throw new Error(`No actual version value provided; looking for ${subject}@${desiredVersion}.`); 6 | } 7 | if (!semver.satisfies(actualVersion, desiredVersion)) { 8 | throw new Error(`Your version of ${subject} does not satisfy the requirements; looking for ${subject}@${desiredVersion} and provided version was ${actualVersion}.`); 9 | } 10 | return `👍 ${subject} version satisfied: ${actualVersion}`; 11 | }; -------------------------------------------------------------------------------- /cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | module.exports = (on, config) => { 15 | // `on` is used to hook into various events Cypress emits 16 | // `config` is the resolved Cypress config 17 | } 18 | -------------------------------------------------------------------------------- /cypress/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /cypress/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`); 2 | 3 | module.exports = { 4 | siteMetadata: { 5 | title: `Gastby Plugin Elastic Lunr Search Demo`, 6 | description: `demo site for gastby-plugin-elasticlunr-search`, 7 | }, 8 | plugins: [ 9 | { 10 | resolve: `@andrew-codes/gatsby-plugin-elasticlunr-search`, 11 | options: { 12 | // Fields to index 13 | fields: ['title', 'keywords'], 14 | // How to resolve each field's value for a supported node type 15 | resolvers: { 16 | // For any node of type MarkdownRemark, list how to resolve the fields' values 17 | MarkdownRemark: { 18 | title: node => node.frontmatter.title, 19 | keywords: node => node.frontmatter.keywords, 20 | }, 21 | }, 22 | }, 23 | }, 24 | `gatsby-plugin-react-helmet`, 25 | { 26 | resolve: `gatsby-source-filesystem`, 27 | options: { 28 | name: `pages`, 29 | path: path.resolve(__dirname, `docs`), 30 | }, 31 | }, 32 | { 33 | resolve: `gatsby-transformer-remark`, 34 | options: { 35 | plugins: [`gatsby-remark-prismjs`, `gatsby-remark-autolink-headers`], 36 | }, 37 | }, 38 | ], 39 | }; 40 | -------------------------------------------------------------------------------- /cypress/integration/github-link.spec.js: -------------------------------------------------------------------------------- 1 | describe('repo ribbon link', () => { 2 | const urls = [ 3 | 'http://localhost:8000', 4 | 'http://localhost:8000/test-page-01', 5 | 'http://localhost:8000/non-existant-page', 6 | ]; 7 | urls.forEach(createTestForRibbonRepoLinkOnPage(describe, it)); 8 | }); 9 | function createTestForRibbonRepoLinkOnPage(describe, it) { 10 | return url => { 11 | describe(`when viewing a page (${url})`, () => { 12 | it('contains a ribbon that links to the plugin repo', () => { 13 | cy.visit(url); 14 | const repoLink = 15 | 'a[href="https://github.com/andrew-codes/gatsby-plugin-elasticlunr-search"]'; 16 | const ribbonImage = 17 | 'img[alt="Fork me on GitHub"][src="https://camo.githubusercontent.com/e7bbb0521b397edbd5fe43e7f760759336b5e05f/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677265656e5f3030373230302e706e67"]'; 18 | cy 19 | .get(repoLink) 20 | .children(ribbonImage) 21 | .should('be.visible'); 22 | cy 23 | .get(ribbonImage) 24 | .should('have.css', 'borderWidth', '0px') 25 | .should('have.css', 'position', 'absolute') 26 | .should('have.css', 'top', '0px') 27 | .should('have.css', 'right', '0px'); 28 | }); 29 | }); 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | # Requirements 4 | 5 | You must have [node](https://nodejs.org/en/) v8 or greater and [npm](https://www.npmjs.com/) v5 or greater. You will also need [git](https://git-scm.com/) installed in order to clone the repo. 6 | 7 | ## Setup 8 | 9 | 1. Fork and clone repo 10 | 1. Run `npm install` to install project dependencies 11 | 1. Run `npm start validate` to validate your environment meets the above section requirements 12 | 1. Create a branch for your pull request 13 | 14 | # Getting Started 15 | 16 | You can run `npm start help` to get a list of available commands. However, if you are developing the site locally, then simply run `npm start` and navigate to [http://localhost:8000](http://localhost:8000) in your browser. 17 | 18 | ## Running Integration Tests 19 | 20 | Run the site via `npm start` then, in a separate CLI window, run `npm start test/integration`. 21 | 22 | # Publishing 23 | 24 | Only the **latest version** of the site is published to [Github Pages](https://pages.github.com/). Because we do not allow publishing different docs to the same version, the act of publishing also implicitly includes bumping the version. Therefore, depending on what type of version bump, you are able to publish to gh-pages via `npm start publish/major`, `npm start publish/minor`, and `npm publish/patch`. To learn more about which type of version increment to use, see the [semantic version docs](http://semver.org/). 25 | -------------------------------------------------------------------------------- /src/components/VerticalNavigationList.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import NavigationItem from './NavigationItem'; 3 | import Search from '../components/Search'; 4 | 5 | class VerticalNavigationList extends Component { 6 | constructor(...rest) { 7 | super(...rest); 8 | this.state = { 9 | hits: null, 10 | }; 11 | } 12 | render() { 13 | const { currentSlug, edges, searchData } = this.props; 14 | const { hits } = this.state; 15 | 16 | return ( 17 |
18 | 21 | this.setState({ 22 | hits: text !== '' ? hits : null, 23 | }) 24 | } 25 | /> 26 | 45 |
46 | ); 47 | } 48 | } 49 | 50 | export default VerticalNavigationList; 51 | -------------------------------------------------------------------------------- /src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import graphql from 'graphql-tag'; 2 | import Helmet from 'react-helmet'; 3 | import Link from 'gatsby-link'; 4 | import PropTypes from 'prop-types'; 5 | import React from 'react'; 6 | 7 | import './index.css'; 8 | 9 | const Header = () => ( 10 |
11 |
12 |

13 | Home 14 |

15 |
16 | 17 | Fork me on GitHub 28 | 29 |
30 | ); 31 | 32 | const TemplateWrapper = ({ children, data: { site } }) => ( 33 |
34 | 38 |
39 |
{children()}
40 |
41 | ); 42 | 43 | TemplateWrapper.propTypes = { 44 | children: PropTypes.func, 45 | }; 46 | 47 | export default TemplateWrapper; 48 | export const query = graphql` 49 | query TemplateQuery { 50 | site { 51 | siteMetadata { 52 | description 53 | title 54 | } 55 | } 56 | } 57 | `; 58 | -------------------------------------------------------------------------------- /src/templates/default.js: -------------------------------------------------------------------------------- 1 | import graphql from 'graphql-tag'; 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | import renderHTML from 'react-render-html'; 5 | import VerticalNavigationList from '../components/VerticalNavigationList'; 6 | 7 | export default ({ 8 | data: { allMarkdownRemark, markdownRemark, site, siteSearchIndex }, 9 | }) => { 10 | return ( 11 |
12 | 17 |
18 | 23 |
24 |
{renderHTML(markdownRemark.html)}
25 |
26 | ); 27 | }; 28 | 29 | export const query = graphql` 30 | query DefaultTemplateQuery($slug: String!) { 31 | markdownRemark(fields: { slug: { eq: $slug } }) { 32 | html 33 | fields { 34 | slug 35 | } 36 | frontmatter { 37 | title 38 | } 39 | } 40 | site { 41 | siteMetadata { 42 | title 43 | } 44 | } 45 | siteSearchIndex { 46 | index 47 | } 48 | allMarkdownRemark { 49 | edges { 50 | node { 51 | id 52 | fields { 53 | slug 54 | } 55 | frontmatter { 56 | title 57 | } 58 | headings { 59 | depth 60 | value 61 | } 62 | } 63 | } 64 | } 65 | } 66 | `; 67 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const { createFilePath } = require(`gatsby-source-filesystem`); 4 | 5 | const rootDir = path.resolve(__dirname); 6 | 7 | exports.onCreateNode = ({ node, getNode, boundActionCreators }) => { 8 | const { createNodeField } = boundActionCreators; 9 | if (node.internal.type === `MarkdownRemark`) { 10 | const slug = node.frontmatter.slug 11 | ? node.frontmatter.slug 12 | : createFilePath({ node, getNode, basePath: `docs` }); 13 | createNodeField({ 14 | node, 15 | name: `slug`, 16 | value: slug, 17 | }); 18 | 19 | const template = node.frontmatter.template 20 | ? node.frontmatter.template 21 | : `default`; 22 | createNodeField({ 23 | node, 24 | name: `template`, 25 | value: template, 26 | }); 27 | } 28 | }; 29 | 30 | exports.createPages = ({ graphql, boundActionCreators }) => { 31 | const { createPage } = boundActionCreators; 32 | return new Promise(resolve => { 33 | graphql(` 34 | { 35 | allMarkdownRemark { 36 | edges { 37 | node { 38 | fields { 39 | slug 40 | template 41 | } 42 | } 43 | } 44 | } 45 | } 46 | `).then(result => { 47 | result.data.allMarkdownRemark.edges.map(({ node }) => { 48 | createPage({ 49 | path: node.fields.slug, 50 | component: path.join( 51 | rootDir, 52 | `src`, 53 | `templates`, 54 | `${node.fields.template}.js`, 55 | ), 56 | context: { 57 | slug: node.fields.slug, 58 | }, 59 | }); 60 | }); 61 | resolve(); 62 | }); 63 | }); 64 | }; 65 | -------------------------------------------------------------------------------- /cypress/integration/search_spec.js: -------------------------------------------------------------------------------- 1 | describe('search', () => { 2 | const urls = ['http://localhost:8000', 'http://localhost:8000/test-page-01']; 3 | urls.forEach(createTestForSearch(describe, it)); 4 | }); 5 | 6 | function createTestForSearch(describe, it) { 7 | return url => { 8 | describe(`searching on page (${url})`, () => { 9 | const searchInput = '[role="search"] input[type="search"]'; 10 | beforeEach(() => { 11 | cy.visit(url); 12 | }); 13 | 14 | it('contains a field indicating that it is for searching', () => { 15 | cy.get(`${searchInput}[placeholder="search"]`); 16 | }); 17 | 18 | describe('when searching and then deleting search criteria', () => { 19 | it('it show no navigation items', () => { 20 | cy.get('nav dd').should('have.length', 2); 21 | cy 22 | .get(searchInput) 23 | .type('one') 24 | .clear(); 25 | cy.get('nav dd').should('have.length', 2); 26 | }); 27 | }); 28 | 29 | describe('when searching that yields results', () => { 30 | it('it filters the navigation to show only pages with keywords matching search criteria', () => { 31 | cy.get('nav dd').should('have.length', 2); 32 | 33 | cy.get(searchInput).type('one'); 34 | cy.get('nav dd').should('have.length', 1); 35 | cy.get('nav dd').contains('Test Page 1'); 36 | }); 37 | }); 38 | 39 | describe('when searching with criteria that yields no results', () => { 40 | it('it show no navigation items', () => { 41 | cy.get('nav dd').should('have.length', 2); 42 | 43 | cy.get(searchInput).type('no results'); 44 | cy.get('nav dd').should('have.length', 0); 45 | }); 46 | }); 47 | }); 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@andrew-codes/gatsby-plugin-elasticlunr-search-demo", 4 | "version": "1.0.0", 5 | "description": "", 6 | "author": "", 7 | "contributors": [ 8 | "Andrew Smith " 9 | ], 10 | "license": "MIT", 11 | "engines": { 12 | "node": "8.0.0 - 9.0.0", 13 | "npm": ">=5.0.0" 14 | }, 15 | "homepage": "https://github.com/andrew-codes/gatsby-plugin-elasticlunr-search-demo#readme", 16 | "bugs": { 17 | "url": "https://github.com/andrew-codes/gatsby-plugin-elasticlunr-search-demo/issues" 18 | }, 19 | "keywords": [ 20 | "gatsby", 21 | "gatsby plugin", 22 | "elastic search", 23 | "demo" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/andrew-codes/gatsby-plugin-elasticlunr-search-demo.git" 28 | }, 29 | "dependencies": { 30 | "@andrew-codes/gatsby-plugin-elasticlunr-search": "^1.0.3", 31 | "elasticlunr": "^0.9.5", 32 | "graphql": "0.11.7", 33 | "lodash.debounce": "^4.0.8", 34 | "prop-types": "^15.6.0", 35 | "qs": "^6.5.1", 36 | "react": "^15.6.2", 37 | "react-helmet": "^5.2.0", 38 | "react-render-html": "^0.5.2" 39 | }, 40 | "devDependencies": { 41 | "cypress": "^1.4.1", 42 | "gatsby": "^1.9.102", 43 | "gatsby-link": "^1.6.22", 44 | "gatsby-plugin-react-helmet": "^1.0.8", 45 | "gatsby-remark-autolink-headers": "^1.4.7", 46 | "gatsby-remark-prismjs": "^1.2.9", 47 | "gatsby-source-filesystem": "^1.5.7", 48 | "gatsby-transformer-remark": "^1.7.19", 49 | "gh-pages": "^1.0.0", 50 | "graphql-tag": "^2.5.0", 51 | "nps": "^5.7.1", 52 | "nps-utils": "^1.5.0", 53 | "prettier": "^1.7.4", 54 | "semver": "^5.4.1" 55 | }, 56 | "scripts": { 57 | "start": "nps", 58 | "test": "nps test" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/components/Search.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import qs from 'qs'; 3 | import React, { Component } from 'react'; 4 | import { Index } from 'elasticlunr'; 5 | 6 | const getSearch = ({ location }) => { 7 | if (!location) return ''; 8 | if (!location.search) return ''; 9 | 10 | const query = location.search.substring(1); 11 | const parsed = qs.parse(query); 12 | if (!parsed.q) return ''; 13 | return parsed.q; 14 | }; 15 | 16 | export default class Search extends Component { 17 | constructor(props, context) { 18 | super(props, context); 19 | 20 | this.updateQuery = evt => { 21 | const text = evt.target.value; 22 | const newQuery = qs.stringify({ q: text }, { format: 'RFC1738' }); 23 | const hits = this.getHits(text); 24 | this.props.onSearch(text, hits); 25 | this.setState(s => { 26 | return { 27 | ...s, 28 | hits, 29 | query: text, 30 | }; 31 | }); 32 | }; 33 | 34 | const query = getSearch(props); 35 | this.state = { 36 | query, 37 | hits: this.getHits(query), 38 | }; 39 | } 40 | 41 | createIndex() { 42 | this.index = Index.load(this.props.data.index); 43 | } 44 | 45 | getHits(query) { 46 | if (!query) return []; 47 | 48 | if (!this.index) this.createIndex(); 49 | const hits = this.index.search(query); 50 | return hits.map(({ ref }) => this.index.documentStore.getDoc(ref)); 51 | } 52 | 53 | render() { 54 | const { query, hits } = this.state; 55 | 56 | return ( 57 |
58 | 67 |
68 | ); 69 | } 70 | } 71 | 72 | Search.propTypes = { 73 | data: PropTypes.shape({ 74 | index: PropTypes.object.isRequired, 75 | }).isRequired, 76 | onSearch: PropTypes.func.isRequired, 77 | }; 78 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import graphql from 'graphql-tag'; 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | import VerticalNavigationList from '../components/VerticalNavigationList'; 5 | 6 | const App = ({ data: { allMarkdownRemark, site, siteSearchIndex } }) => ( 7 |
8 | 9 |
10 | 15 |
16 |
17 |

Demo Site for Gatsby Search Plugin

18 |

19 | Welcome to demo site for the 20 | 21 | gatsby-plugin-elasticlunr-search plugin 22 | . 23 |

24 |

25 | Test page 1 and Page 2 are indexed by title, as seen in 26 | the nav menu to the left, and by keyword. Try searching 27 | for "one", "two" or " 28 | three 29 | ". The words "one" and "two" are keywords associated with Test 30 | page 1 and "two" and "three" are associated with Page 2. 31 |

32 |

Of course you can also try searching by words matching the title.

33 |
34 |
35 | ); 36 | export default App; 37 | 38 | export const query = graphql` 39 | query IndexPageQuery { 40 | site { 41 | siteMetadata { 42 | title 43 | } 44 | } 45 | siteSearchIndex { 46 | index 47 | } 48 | allMarkdownRemark { 49 | edges { 50 | node { 51 | id 52 | fields { 53 | slug 54 | } 55 | frontmatter { 56 | title 57 | } 58 | headings { 59 | depth 60 | value 61 | } 62 | } 63 | } 64 | } 65 | } 66 | `; 67 | -------------------------------------------------------------------------------- /package-scripts.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { concurrent, crossEnv, rimraf, series } = require(`nps-utils`); 3 | 4 | const hiddenFromHelp = true; 5 | const rootDir = path.resolve(__dirname); 6 | 7 | module.exports = { 8 | scripts: { 9 | build: { 10 | description: `Build a static site for use in production.`, 11 | script: crossEnv(`NODE_ENV=production gatsby build`), 12 | }, 13 | clean: { 14 | description: `Remove all build artifacts.`, 15 | script: concurrent.nps(`clean/cache`, `clean/public`, `clean/gh-pages`), 16 | }, 17 | 'clean/cache': { 18 | hiddenFromHelp, 19 | script: rimraf(path.join(rootDir, '.cache')), 20 | }, 21 | 'clean/gh-pages': { 22 | hiddenFromHelp, 23 | script: `rm -rf node_modules/gh-pages/.cache`, 24 | }, 25 | 'clean/public': { 26 | hiddenFromHelp, 27 | script: rimraf(path.join(rootDir, 'public')), 28 | }, 29 | cypress: { 30 | description: `Open cypress`, 31 | script: 'cypress open', 32 | }, 33 | default: series.nps(`clean/cache`, `dev`), 34 | dev: { 35 | description: `Run site on a dev server for local site development.`, 36 | script: crossEnv(`NODE_ENV=development gatsby develop`), 37 | }, 38 | 'publish/major': { 39 | description: `Publish a new major version.`, 40 | script: series( 41 | `nps validate`, 42 | `npm version major`, 43 | `nps publish/gh-pages`, 44 | ), 45 | }, 46 | 'publish/minor': { 47 | description: `Publish a new minor version.`, 48 | script: series( 49 | `nps validate`, 50 | `npm version minor`, 51 | `nps publish/gh-pages`, 52 | ), 53 | }, 54 | 'publish/patch': { 55 | description: `Publish a new patch version.`, 56 | script: series( 57 | `nps validate`, 58 | `npm version patch`, 59 | `nps publish/gh-pages`, 60 | ), 61 | }, 62 | 'publish/gh-pages': { 63 | hiddenFromHelp, 64 | script: series( 65 | `nps clean`, 66 | `nps build`, 67 | `gh-pages --version --dir public --silent --no-push`, 68 | `nps clean/public`, 69 | ), 70 | }, 71 | test: { 72 | description: `Run integration tests via cypress.`, 73 | script: series('nps dev', 'nps cypress'), 74 | }, 75 | 'test/integration': { 76 | description: `Run integration tests via cypress.`, 77 | script: `cypress run --headed`, 78 | }, 79 | validate: { 80 | description: `Ensure your environment is correctly configured before developing locally.`, 81 | script: concurrent.nps(`validate/node`, `validate/npm`), 82 | }, 83 | 'validate/node': { 84 | hiddenFromHelp, 85 | script: `node scripts/node/validateNodeVersion.js`, 86 | }, 87 | 'validate/npm': { 88 | hiddenFromHelp, 89 | script: `node scripts/node/validateNPMVersion.js`, 90 | }, 91 | }, 92 | }; 93 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | ## SOURCE CODE 4 | *.bat text eol=crlf 5 | *.coffee text 6 | *.css text 7 | *.htm text 8 | *.html text 9 | *.inc text 10 | *.ini text 11 | *.js text 12 | *.json text 13 | *.jsx text 14 | *.less text 15 | *.od text 16 | *.onlydata text 17 | *.php text 18 | *.pl text 19 | *.py text 20 | *.rb text 21 | *.sass text 22 | *.scm text 23 | *.scss text 24 | *.sh text eol=lf 25 | *.sql text 26 | *.styl text 27 | *.tag text 28 | *.ts text 29 | *.tsx text 30 | *.xml text 31 | *.xhtml text 32 | 33 | ## DOCKER 34 | *.dockerignore text 35 | Dockerfile text 36 | 37 | ## DOCUMENTATION 38 | *.markdown text 39 | *.md text 40 | *.mdwn text 41 | *.mdown text 42 | *.mkd text 43 | *.mkdn text 44 | *.mdtxt text 45 | *.mdtext text 46 | *.txt text 47 | AUTHORS text 48 | CHANGELOG text 49 | CHANGES text 50 | CONTRIBUTING text 51 | COPYING text 52 | copyright text 53 | *COPYRIGHT* text 54 | INSTALL text 55 | license text 56 | LICENSE text 57 | NEWS text 58 | readme text 59 | *README* text 60 | TODO text 61 | 62 | ## TEMPLATES 63 | *.dot text 64 | *.ejs text 65 | *.haml text 66 | *.handlebars text 67 | *.hbs text 68 | *.hbt text 69 | *.jade text 70 | *.latte text 71 | *.mustache text 72 | *.njk text 73 | *.phtml text 74 | *.tmpl text 75 | *.tpl text 76 | *.twig text 77 | 78 | ## LINTERS 79 | .csslintrc text 80 | .eslintrc text 81 | .htmlhintrc text 82 | .jscsrc text 83 | .jshintrc text 84 | .jshintignore text 85 | .stylelintrc text 86 | 87 | ## CONFIGS 88 | *.bowerrc text 89 | *.cnf text 90 | *.conf text 91 | *.config text 92 | .browserslistrc text 93 | .editorconfig text 94 | .gitattributes text 95 | .gitconfig text 96 | .gitignore text 97 | .htaccess text 98 | *.npmignore text 99 | *.yaml text 100 | *.yml text 101 | browserslist text 102 | Makefile text 103 | makefile text 104 | 105 | ## HEROKU 106 | Procfile text 107 | .slugignore text 108 | 109 | ## GRAPHICS 110 | *.ai binary 111 | *.bmp binary 112 | *.eps binary 113 | *.gif binary 114 | *.ico binary 115 | *.jng binary 116 | *.jp2 binary 117 | *.jpg binary 118 | *.jpeg binary 119 | *.jpx binary 120 | *.jxr binary 121 | *.pdf binary 122 | *.png binary 123 | *.psb binary 124 | *.psd binary 125 | *.svg text 126 | *.svgz binary 127 | *.tif binary 128 | *.tiff binary 129 | *.wbmp binary 130 | *.webp binary 131 | 132 | ## AUDIO 133 | *.kar binary 134 | *.m4a binary 135 | *.mid binary 136 | *.midi binary 137 | *.mp3 binary 138 | *.ogg binary 139 | *.ra binary 140 | 141 | ## VIDEO 142 | *.3gpp binary 143 | *.3gp binary 144 | *.as binary 145 | *.asf binary 146 | *.asx binary 147 | *.fla binary 148 | *.flv binary 149 | *.m4v binary 150 | *.mng binary 151 | *.mov binary 152 | *.mp4 binary 153 | *.mpeg binary 154 | *.mpg binary 155 | *.ogv binary 156 | *.swc binary 157 | *.swf binary 158 | *.webm binary 159 | 160 | ## ARCHIVES 161 | *.7z binary 162 | *.gz binary 163 | *.jar binary 164 | *.rar binary 165 | *.tar binary 166 | *.zip binary 167 | 168 | ## FONTS 169 | *.ttf binary 170 | *.eot binary 171 | *.otf binary 172 | *.woff binary 173 | *.woff2 binary 174 | 175 | ## EXECUTABLES 176 | *.exe binary 177 | *.pyc binary 178 | -------------------------------------------------------------------------------- /src/layouts/index.css: -------------------------------------------------------------------------------- 1 | html { 2 | -webkit-font-smoothing: antialiased; 3 | -ms-text-size-adjust: 100%; 4 | -webkit-text-size-adjust: 100%; 5 | color: #272c34; /*midnight*/ 6 | font-family: Arial, sans-serif; 7 | } 8 | body { 9 | margin: 0; 10 | } 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | main, 19 | menu, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | audio, 26 | canvas, 27 | progress, 28 | video { 29 | display: inline-block; 30 | } 31 | audio:not([controls]) { 32 | display: none; 33 | height: 0; 34 | } 35 | progress { 36 | vertical-align: baseline; 37 | } 38 | [hidden], 39 | template { 40 | display: none; 41 | } 42 | a { 43 | background-color: transparent; 44 | -webkit-text-decoration-skip: objects; 45 | transition: all 0.3s ease; 46 | } 47 | a:active, 48 | a:hover { 49 | outline-width: 0; 50 | } 51 | abbr[title] { 52 | border-bottom: none; 53 | text-decoration: underline; 54 | text-decoration: underline dotted; 55 | } 56 | b, 57 | strong { 58 | font-weight: inherit; 59 | font-weight: bolder; 60 | } 61 | dfn { 62 | font-style: italic; 63 | } 64 | h1, 65 | h2, 66 | h3, 67 | h4, 68 | h5, 69 | h6 { 70 | padding: 0; 71 | margin: 0; 72 | } 73 | mark { 74 | background-color: #ff0; 75 | color: #000; 76 | } 77 | small { 78 | font-size: 80%; 79 | } 80 | sub, 81 | sup { 82 | font-size: 75%; 83 | line-height: 0; 84 | position: relative; 85 | vertical-align: baseline; 86 | } 87 | sub { 88 | bottom: -0.25em; 89 | } 90 | sup { 91 | top: -0.5em; 92 | } 93 | img { 94 | border-style: none; 95 | } 96 | svg:not(:root) { 97 | overflow: hidden; 98 | } 99 | code, 100 | kbd, 101 | pre, 102 | samp { 103 | font-family: monospace, monospace; 104 | font-size: 1em; 105 | } 106 | figure { 107 | margin: 1em 40px; 108 | } 109 | hr { 110 | box-sizing: content-box; 111 | height: 0; 112 | overflow: visible; 113 | } 114 | button, 115 | input, 116 | optgroup, 117 | select, 118 | textarea { 119 | font: inherit; 120 | margin: 0; 121 | } 122 | optgroup { 123 | font-weight: 700; 124 | } 125 | button, 126 | input { 127 | overflow: visible; 128 | } 129 | button, 130 | select { 131 | text-transform: none; 132 | } 133 | [type='reset'], 134 | [type='submit'], 135 | button, 136 | html [type='button'] { 137 | -webkit-appearance: button; 138 | } 139 | [type='button']::-moz-focus-inner, 140 | [type='reset']::-moz-focus-inner, 141 | [type='submit']::-moz-focus-inner, 142 | button::-moz-focus-inner { 143 | border-style: none; 144 | padding: 0; 145 | } 146 | [type='button']:-moz-focusring, 147 | [type='reset']:-moz-focusring, 148 | [type='submit']:-moz-focusring, 149 | button:-moz-focusring { 150 | outline: 1px dotted ButtonText; 151 | } 152 | fieldset { 153 | border: 1px solid silver; 154 | margin: 0 2px; 155 | padding: 0.35em 0.625em 0.75em; 156 | } 157 | legend { 158 | box-sizing: border-box; 159 | color: inherit; 160 | display: table; 161 | max-width: 100%; 162 | padding: 0; 163 | white-space: normal; 164 | } 165 | textarea { 166 | overflow: auto; 167 | } 168 | [type='checkbox'], 169 | [type='radio'] { 170 | box-sizing: border-box; 171 | padding: 0; 172 | } 173 | [type='number']::-webkit-inner-spin-button, 174 | [type='number']::-webkit-outer-spin-button { 175 | height: auto; 176 | } 177 | [type='search'] { 178 | -webkit-appearance: textfield; 179 | outline-offset: -2px; 180 | } 181 | [type='search']::-webkit-search-cancel-button, 182 | [type='search']::-webkit-search-decoration { 183 | -webkit-appearance: none; 184 | } 185 | ::-webkit-input-placeholder { 186 | color: inherit; 187 | opacity: 0.54; 188 | } 189 | ::-webkit-file-upload-button { 190 | -webkit-appearance: button; 191 | font: inherit; 192 | } 193 | html { 194 | box-sizing: border-box; 195 | overflow-y: scroll; 196 | } 197 | * { 198 | box-sizing: inherit; 199 | } 200 | *:before { 201 | box-sizing: inherit; 202 | } 203 | *:after { 204 | box-sizing: inherit; 205 | } 206 | body { 207 | color: hsla(0, 0%, 0%, 0.8); 208 | font-weight: normal; 209 | word-wrap: break-word; 210 | font-kerning: normal; 211 | -moz-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; 212 | -ms-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; 213 | -webkit-font-feature-settings: 'kern', 'liga', 'clig', 'calt'; 214 | font-feature-settings: 'kern', 'liga', 'clig', 'calt'; 215 | } 216 | img { 217 | max-width: 100%; 218 | margin-left: 0; 219 | margin-right: 0; 220 | margin-top: 0; 221 | padding-bottom: 0; 222 | padding-left: 0; 223 | padding-right: 0; 224 | padding-top: 0; 225 | margin-bottom: 1.45rem; 226 | } 227 | hgroup { 228 | margin-left: 0; 229 | margin-right: 0; 230 | margin-top: 0; 231 | padding-bottom: 0; 232 | padding-left: 0; 233 | padding-right: 0; 234 | padding-top: 0; 235 | margin-bottom: 1.45rem; 236 | } 237 | ul { 238 | margin-left: 1.45rem; 239 | margin-right: 0; 240 | margin-top: 0; 241 | padding-bottom: 0; 242 | padding-left: 0; 243 | padding-right: 0; 244 | padding-top: 0; 245 | margin-bottom: 1.45rem; 246 | list-style-position: outside; 247 | list-style-image: none; 248 | } 249 | ol { 250 | margin-left: 1.45rem; 251 | margin-right: 0; 252 | margin-top: 0; 253 | padding-bottom: 0; 254 | padding-left: 0; 255 | padding-right: 0; 256 | padding-top: 0; 257 | margin-bottom: 1.45rem; 258 | list-style-position: outside; 259 | list-style-image: none; 260 | } 261 | dl { 262 | margin-left: 0; 263 | margin-right: 0; 264 | margin-top: 0; 265 | padding-bottom: 0; 266 | padding-left: 0; 267 | padding-right: 0; 268 | padding-top: 0; 269 | margin-bottom: 1.45rem; 270 | } 271 | dd { 272 | margin-left: 0; 273 | margin-right: 0; 274 | margin-top: 0; 275 | padding-bottom: 0; 276 | padding-left: 0; 277 | padding-right: 0; 278 | padding-top: 0; 279 | } 280 | p { 281 | margin-left: 0; 282 | margin-right: 0; 283 | margin-top: 0; 284 | padding-bottom: 0; 285 | padding-left: 0; 286 | padding-right: 0; 287 | padding-top: 0; 288 | margin-bottom: 1.45rem; 289 | } 290 | figure { 291 | margin-left: 0; 292 | margin-right: 0; 293 | margin-top: 0; 294 | padding-bottom: 0; 295 | padding-left: 0; 296 | padding-right: 0; 297 | padding-top: 0; 298 | margin-bottom: 1.45rem; 299 | } 300 | pre { 301 | margin-left: 0; 302 | margin-right: 0; 303 | margin-top: 0; 304 | padding-bottom: 0; 305 | padding-left: 0; 306 | padding-right: 0; 307 | padding-top: 0; 308 | margin-bottom: 1.45rem; 309 | font-size: 0.85rem; 310 | line-height: 1.42; 311 | background: hsla(0, 0%, 0%, 0.04); 312 | border-radius: 3px; 313 | overflow: auto; 314 | word-wrap: normal; 315 | padding: 1.45rem; 316 | } 317 | table { 318 | margin-left: 0; 319 | margin-right: 0; 320 | margin-top: 0; 321 | padding-bottom: 0; 322 | padding-left: 0; 323 | padding-right: 0; 324 | padding-top: 0; 325 | margin-bottom: 1.45rem; 326 | font-size: 1rem; 327 | line-height: 1.45rem; 328 | border-collapse: collapse; 329 | width: 100%; 330 | } 331 | fieldset { 332 | margin-left: 0; 333 | margin-right: 0; 334 | margin-top: 0; 335 | padding-bottom: 0; 336 | padding-left: 0; 337 | padding-right: 0; 338 | padding-top: 0; 339 | margin-bottom: 1.45rem; 340 | } 341 | blockquote { 342 | margin-left: 1.45rem; 343 | margin-right: 1.45rem; 344 | margin-top: 0; 345 | padding-bottom: 0; 346 | padding-left: 0; 347 | padding-right: 0; 348 | padding-top: 0; 349 | margin-bottom: 1.45rem; 350 | } 351 | form { 352 | margin-left: 0; 353 | margin-right: 0; 354 | margin-top: 0; 355 | padding-bottom: 0; 356 | padding-left: 0; 357 | padding-right: 0; 358 | padding-top: 0; 359 | margin-bottom: 1.45rem; 360 | } 361 | noscript { 362 | margin-left: 0; 363 | margin-right: 0; 364 | margin-top: 0; 365 | padding-bottom: 0; 366 | padding-left: 0; 367 | padding-right: 0; 368 | padding-top: 0; 369 | margin-bottom: 1.45rem; 370 | } 371 | iframe { 372 | margin-left: 0; 373 | margin-right: 0; 374 | margin-top: 0; 375 | padding-bottom: 0; 376 | padding-left: 0; 377 | padding-right: 0; 378 | padding-top: 0; 379 | margin-bottom: 1.45rem; 380 | } 381 | hr { 382 | margin-left: 0; 383 | margin-right: 0; 384 | margin-top: 0; 385 | padding-bottom: 0; 386 | padding-left: 0; 387 | padding-right: 0; 388 | padding-top: 0; 389 | margin-bottom: calc(1.45rem - 1px); 390 | background: hsla(0, 0%, 0%, 0.2); 391 | border: none; 392 | height: 1px; 393 | } 394 | address { 395 | margin-left: 0; 396 | margin-right: 0; 397 | margin-top: 0; 398 | padding-bottom: 0; 399 | padding-left: 0; 400 | padding-right: 0; 401 | padding-top: 0; 402 | margin-bottom: 1.45rem; 403 | } 404 | b { 405 | font-weight: bold; 406 | } 407 | strong { 408 | font-weight: bold; 409 | } 410 | dt { 411 | font-weight: bold; 412 | } 413 | th { 414 | font-weight: bold; 415 | } 416 | li { 417 | margin-bottom: calc(1.45rem / 2); 418 | } 419 | ol li { 420 | padding-left: 0; 421 | } 422 | ul li { 423 | padding-left: 0; 424 | } 425 | li > ol { 426 | margin-left: 1.45rem; 427 | margin-bottom: calc(1.45rem / 2); 428 | margin-top: calc(1.45rem / 2); 429 | } 430 | li > ul { 431 | margin-left: 1.45rem; 432 | margin-bottom: calc(1.45rem / 2); 433 | margin-top: calc(1.45rem / 2); 434 | } 435 | blockquote *:last-child { 436 | margin-bottom: 0; 437 | } 438 | li *:last-child { 439 | margin-bottom: 0; 440 | } 441 | p *:last-child { 442 | margin-bottom: 0; 443 | } 444 | li > p { 445 | margin-bottom: calc(1.45rem / 2); 446 | } 447 | code { 448 | font-size: 0.85rem; 449 | line-height: 1.45rem; 450 | } 451 | kbd { 452 | font-size: 0.85rem; 453 | line-height: 1.45rem; 454 | } 455 | samp { 456 | font-size: 0.85rem; 457 | line-height: 1.45rem; 458 | } 459 | abbr { 460 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 461 | cursor: help; 462 | } 463 | acronym { 464 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 465 | cursor: help; 466 | } 467 | abbr[title] { 468 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 469 | cursor: help; 470 | text-decoration: none; 471 | } 472 | thead { 473 | text-align: left; 474 | } 475 | td, 476 | th { 477 | text-align: left; 478 | border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); 479 | font-feature-settings: 'tnum'; 480 | -moz-font-feature-settings: 'tnum'; 481 | -ms-font-feature-settings: 'tnum'; 482 | -webkit-font-feature-settings: 'tnum'; 483 | padding-left: 0.96667rem; 484 | padding-right: 0.96667rem; 485 | padding-top: 0.725rem; 486 | padding-bottom: calc(0.725rem - 1px); 487 | } 488 | th:first-child, 489 | td:first-child { 490 | padding-left: 0; 491 | } 492 | th:last-child, 493 | td:last-child { 494 | padding-right: 0; 495 | } 496 | tt, 497 | code { 498 | background-color: hsla(0, 0%, 0%, 0.04); 499 | border-radius: 3px; 500 | font-family: 'SFMono-Regular', Consolas, 'Roboto Mono', 'Droid Sans Mono', 501 | 'Liberation Mono', Menlo, Courier, monospace; 502 | padding: 0; 503 | padding-top: 0.2em; 504 | padding-bottom: 0.2em; 505 | } 506 | pre code { 507 | background: none; 508 | line-height: 1.42; 509 | } 510 | code:before, 511 | code:after, 512 | tt:before, 513 | tt:after { 514 | letter-spacing: -0.2em; 515 | content: ' '; 516 | } 517 | pre code:before, 518 | pre code:after, 519 | pre tt:before, 520 | pre tt:after { 521 | content: ''; 522 | } 523 | @media only screen and (max-width: 480px) { 524 | html { 525 | font-size: 100%; 526 | } 527 | } 528 | 529 | div.master-detail-container { 530 | display: flex; 531 | } 532 | div.detail-pane { 533 | padding: 16px; 534 | } 535 | 536 | div.master-pane { 537 | padding: 16px 0; 538 | border-right: 1px solid #edf2f9; /* ghost */ 539 | } 540 | 541 | div.master-pane [role='search'] { 542 | padding: 0 16px; 543 | } 544 | 545 | div.master-pane nav { 546 | width: 250px; 547 | } 548 | 549 | div.master-pane dd a { 550 | display: block; 551 | width: 100%; 552 | padding: 12px 16px; 553 | text-decoration: none; 554 | color: #31363e; /*gunmetal*/ 555 | } 556 | 557 | div.master-pane dd a:visited { 558 | color: #61666e; /*shuttle*/ 559 | } 560 | 561 | div.master-pane dd a:hover, 562 | div.master-pane dd a:focus, 563 | div.master-pane dd a:active { 564 | color: #00a9e0; 565 | background-color: #cceef9; /* lightest cerulean */ 566 | } 567 | 568 | div.master-pane dd.depth-1 a { 569 | font-size: 1em; 570 | font-weight: 600; 571 | } 572 | 573 | div.master-pane dd.depth-2 a { 574 | font-size: 0.9em; 575 | font-weight: 400; 576 | padding-left: 48px; 577 | } 578 | 579 | div.master-pane dd.depth-3 a { 580 | font-size: 0.8em; 581 | font-weight: 100; 582 | padding-left: 64px; 583 | } 584 | dd.depth-4 { 585 | font-size: 0.8em; 586 | font-weight: 100; 587 | padding-left: 80px; 588 | } 589 | dd.depth-5 { 590 | } 591 | dd.depth-6 { 592 | } 593 | 594 | .top-header { 595 | background-color: #edf2f9; /* ghost */ 596 | padding: 16px; 597 | } 598 | 599 | .top-header div { 600 | width: 50%; 601 | display: inline-block; 602 | } 603 | 604 | .top-header div.github-link { 605 | text-align: right; 606 | } 607 | 608 | .top-header div.github-link img { 609 | margin: 0 5px; 610 | } 611 | 612 | .top-header h1 a { 613 | color: #878c94; /* heather */ 614 | text-decoration: none; 615 | font-weight: 300; 616 | width: fit-content; 617 | } 618 | 619 | .top-header h1 a:hover { 620 | color: #61666e; /* shuttle */ 621 | } 622 | --------------------------------------------------------------------------------