diff --git a/package.json b/package.json index b8ecdaa..039ab26 100644 --- a/package.json +++ b/package.json @@ -76,13 +76,17 @@ "history": "^4.7.2", "html-minifier": "^3.5.16", "js-search": "^1.4.2", + "markdown-toc": "^1.2.0", "minimist": "^1.2.0", "ncp": "^2.0.0", "progress": "^2.0.0", "prop-types": "^15.6.1", "react": "^16.4.0", + "react-click-outside": "^3.0.1", + "react-content-loader": "^3.1.2", "react-dom": "^16.4.0", "react-emotion": "^9.1.3", + "react-feather": "^1.1.0", "react-helmet": "^5.2.0", "react-highlight-words": "^0.11.0", "react-markdown": "^3.3.2", diff --git a/src/core/filesystem.js b/src/core/filesystem.js index 2bcef7d..a6f0a03 100644 --- a/src/core/filesystem.js +++ b/src/core/filesystem.js @@ -1,6 +1,7 @@ const fs = require('fs-extra') const syspath = require('path') const { ncp } = require('ncp') +const toc = require('markdown-toc') const { parseFrontmatter } = require('../utils/frontmatter') const INDEX_FILES = ['index', 'readme'] @@ -154,6 +155,10 @@ async function getContent (path) { return content } +function getTableOfContents (content) { + return toc(content).json +} + /** * because of https://github.com/zeit/pkg/issues/420 */ @@ -171,6 +176,7 @@ module.exports = { checkForConflicts, dirTree, getContent, + getTableOfContents, copyDir, } diff --git a/src/core/output.js b/src/core/output.js index ac5b28a..6c37250 100644 --- a/src/core/output.js +++ b/src/core/output.js @@ -2,7 +2,7 @@ const fs = require('fs-extra') const syspath = require('path') const { generateDatabase } = require('./database') const { templateForProduction } = require('./template') -const { getContent } = require('./filesystem') +const { getContent, getTableOfContents } = require('./filesystem') module.exports = async (entrypoints, props) => { const db = await generateDatabase(props.manifest) @@ -19,7 +19,10 @@ module.exports = async (entrypoints, props) => { const outputJson = syspath.join(item.outputDir, 'index.json') await fs.outputFile(outputHtml, template) - await fs.outputJson(outputJson, { content: item.content }) + await fs.outputJson(outputJson, { + content: item.content, + toc: getTableOfContents(item.content), + }) } if (items) { diff --git a/src/core/socket.js b/src/core/socket.js index 234b6b5..1260481 100644 --- a/src/core/socket.js +++ b/src/core/socket.js @@ -1,6 +1,6 @@ const fs = require('fs') const WebSocket = require('ws') -const { getContent } = require('./filesystem') +const { getContent, getTableOfContents } = require('./filesystem') module.exports = (server) => { const socket = new WebSocket.Server({ @@ -13,7 +13,10 @@ module.exports = (server) => { client.on('message', file => { const send = async () => { const content = await getContent(file) - client.send(content) + client.send(JSON.stringify({ + content, + toc: getTableOfContents(content), + })) } send() diff --git a/src/core/syntax.js b/src/core/syntax.js index fd5e318..86afe9a 100644 --- a/src/core/syntax.js +++ b/src/core/syntax.js @@ -7,17 +7,17 @@ module.exports = async (config) => { const { temp, languages, - theme_custom, + syntax, } = config const rsh = syspath.dirname(require.resolve('react-syntax-highlighter')) const langs = languages - .filter(lang => fs.pathExistsSync(`${rsh}/languages/prism/${lang}`)) - .map(lang => `{ name: '${lang}', func: require('${rsh}/languages/prism/${lang}').default },`) + .filter(lang => fs.pathExistsSync(`${rsh}/languages/${syntax.renderer}/${lang}.js`)) + .map(lang => `{ name: '${lang}', func: require('${rsh}/languages/${syntax.renderer}/${lang}').default },`) .join('\n') const content = `module.exports = { - theme: require('${rsh}/styles/prism/${theme_custom.syntaxTheme}').default, + theme: require('${rsh}/styles/${syntax.renderer}/${syntax.theme}').default, languages: [${langs}] }` diff --git a/src/utils/config.js b/src/utils/config.js index e801522..5fdce4d 100644 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -26,9 +26,12 @@ const DEFAULT_CONFIG = { languages: ['bash', 'json'], header_links: [], theme: 'default', - theme_custom: { - syntaxTheme: 'prism', - syntaxLineNumbers: false, + prefix_titles: true, + table_of_contents: true, + syntax: { + theme: 'atom-one-light', + renderer: 'hljs', + lineNumbers: true, }, } diff --git a/themes/default/application/styles.js b/themes/default/application/styles.js index 5efe4da..405bc66 100644 --- a/themes/default/application/styles.js +++ b/themes/default/application/styles.js @@ -14,9 +14,9 @@ const fontMain = css` ` const fontMono = css` - font-family: 'Menlo', monospace; - line-height: 1; - font-size: 1.1rem; + font-family: "Menlo", "Source Code Pro", "Inconsolata","monospace", serif; + font-size: 13px; + line-height: 21px; ` export const Wrapper = styled('div')` @@ -36,10 +36,22 @@ export const Wrapper = styled('div')` export const WrapperNav = styled('nav')` flex: 1; background: linear-gradient(90deg, #F0F2F4 0%, #F5F7F9 100%); + background: #FAFAFD; border-right: 1px solid #E6E9EB; - min-width: 250px; + box-shadow: inset -4px 0px 2px -2px rgba(202, 209, 226, 0.2); text-align: right; overflow: auto; + + @media (min-width: 850px) { + min-width: 270px; + max-width: 270px; + } + + @media (min-width: 1450px) { + min-width: initial; + max-width: initial; + } + @media (max-width: 850px) { flex: 0 auto; overflow: hidden; diff --git a/themes/default/components/container.js b/themes/default/components/container.js new file mode 100644 index 0000000..cdbb4e1 --- /dev/null +++ b/themes/default/components/container.js @@ -0,0 +1,6 @@ +import styled from 'react-emotion' + +export default styled('div')` + width: 1024px; + margin: 0 auto; +` diff --git a/themes/default/index.js b/themes/default/index.js index ebf28ca..1937ad0 100644 --- a/themes/default/index.js +++ b/themes/default/index.js @@ -2,6 +2,9 @@ import React from 'react' import ReactDOM from 'react-dom' import { Router } from 'react-router-dom' import { hydrate } from 'emotion' +import { registerLanguage as registerHighlight } from 'react-syntax-highlighter/light' +import { registerLanguage as registerPrism } from 'react-syntax-highlighter/prism-light' +import { languages } from '@codegen/loadSyntax' // eslint-disable-line import history from './history' import App from './application' @@ -15,6 +18,17 @@ const render = ReactDOM.render isDev && module.hot && module.hot.accept() _EMOTION_IDS_ && hydrate(_EMOTION_IDS_) +// Ensure required languages are registered +const renderers = { + hljs: registerHighlight, + prism: registerPrism, +} + +if (window) { + const register = renderers[process.env.PROPS.config.syntax.renderer] + languages.forEach(lang => register(lang.name, lang.func)) +} + render( diff --git a/themes/default/loading/index.js b/themes/default/loading/index.js index 08f36c3..bcfa42a 100644 --- a/themes/default/loading/index.js +++ b/themes/default/loading/index.js @@ -1,14 +1,134 @@ import React from 'react' +import ContentLoader from 'react-content-loader' import { Wrapper } from './styles' +// @TODO: Make this a little more responsive by passing in 400 for the height +// on smaller screens export default function (props) { return ( -
-
-
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) } diff --git a/themes/default/loading/styles.js b/themes/default/loading/styles.js index d7bb81c..19d0a8e 100644 --- a/themes/default/loading/styles.js +++ b/themes/default/loading/styles.js @@ -1,40 +1,4 @@ -import styled, { keyframes } from 'react-emotion' - -const stretch = keyframes` - 0%, - 40%, - 100% { - transform: scaleY(0.4); - } - 20% { - transform: scaleY(1.0); - } -` +import styled from 'react-emotion' export const Wrapper = styled('div')` - width: 50px; - height: 40px; - text-align: center; - font-size: 10px; - div { - background: #E6E9EB; - height: 100%; - width: 5px; - display: inline-block; - animation: ${stretch} 1.2s infinite ease-in-out; - margin: 0 1px; - &:nth-child(2) { - animation-delay: -1.1s; - } - &:nth-child(3) { - animation-delay: -1.0s; - } - &:nth-child(4) { - animation-delay: -0.9s; - } - &:nth-child(5) { - animation-delay: -0.8s; - } - } - }), ` diff --git a/themes/default/logo/styles.js b/themes/default/logo/styles.js index 1fd2047..1bdfbb4 100644 --- a/themes/default/logo/styles.js +++ b/themes/default/logo/styles.js @@ -7,11 +7,9 @@ export const Wrapper = styled('div')` ` export const CustomLogo = styled('div')` - padding: 30px; img { display: block; - width: 100%; - height: 100%; + height: 35px; } ` diff --git a/themes/default/markdown/index.js b/themes/default/markdown/index.js index 9234d38..56c7af2 100644 --- a/themes/default/markdown/index.js +++ b/themes/default/markdown/index.js @@ -1,19 +1,14 @@ import React from 'react' import Markdown from 'react-markdown' -import { registerLanguage } from 'react-syntax-highlighter/prism-light' -import { languages } from '@codegen/loadSyntax' // eslint-disable-line import { Wrapper } from './styles' import Code from './overrides/Code' import Header from './overrides/Header' import Link from './overrides/Link' export default function (props) { - languages.forEach(lang => - registerLanguage(lang.name, lang.func)) - const options = { renderers: { - code: Code, + code: p => , link: Link, heading: Header, }, diff --git a/themes/default/markdown/overrides/Code.js b/themes/default/markdown/overrides/Code.js index cf3c960..a462310 100644 --- a/themes/default/markdown/overrides/Code.js +++ b/themes/default/markdown/overrides/Code.js @@ -1,10 +1,11 @@ import React from 'react' -import Syntax from 'react-syntax-highlighter/prism-light' +import Highlight from 'react-syntax-highlighter/light' +import Prism from 'react-syntax-highlighter/prism-light' import { theme, languages } from '@codegen/loadSyntax' // eslint-disable-line export default function (props) { let { language } = props - const { value } = props + const { value, renderer } = props if (language) { language = language // language name aliases @@ -18,12 +19,16 @@ export default function (props) { } } + const Syntax = renderer === 'prism' + ? Prism + : Highlight + return ( {value} diff --git a/themes/default/markdown/overrides/Header.js b/themes/default/markdown/overrides/Header.js index 37802d9..8793759 100644 --- a/themes/default/markdown/overrides/Header.js +++ b/themes/default/markdown/overrides/Header.js @@ -33,15 +33,18 @@ const levels = { export default function (props) { const { - id, level = 1, children, } = props - const itemId = children[0] || id - .toLowerCase() - .split(' ') - .join('-') + // Turn headers into linkable IDs + const text = children[0] + const itemId = typeof text === 'string' + ? text + .toLowerCase() + .split(' ') + .join('-') + : '' return ( diff --git a/themes/default/markdown/styles.js b/themes/default/markdown/styles.js index 6b76c42..6f132a4 100644 --- a/themes/default/markdown/styles.js +++ b/themes/default/markdown/styles.js @@ -2,10 +2,22 @@ import styled from 'react-emotion' export const Wrapper = styled('div')` word-wrap: break-word; + color: #2f3138; + + a { + text-decoration: none; + color: #5944CC; + } + h1, h2, h3, h4 { font-weight: bold; text-decoration: none; margin: 0; + color: #0D0A2B; + } + + a:first-of-type { + margin-top: 0; } p { @@ -29,35 +41,34 @@ export const Wrapper = styled('div')` pre { overflow-x: scroll; + background: #FAFAFD !important; } pre, code { - font-family: monospace; - -webkit-font-smoothing: initial !important; + // -webkit-font-smoothing: initial; } code { border-radius: 4px; - padding: .25rem .5rem; + padding: .15rem .25rem; display: inline; - line-height: 1.5; word-break: break-all; - background: #F4F5F6; + background: #EEEAFE; + color: #5742CA; } pre code { - font-size: 1.1rem; border: none; word-break: break-all; white-space: pre-wrap; display: inline-block !important; background: inherit; - color: rgb(52, 50, 64); + color: #485672; } pre { border-radius: 4px; - font-family: Roboto Mono, monospace; + // font-family: Roboto Mono, monospace; border-radius: 3px; line-height: 19px; } @@ -125,10 +136,6 @@ export const Wrapper = styled('div')` padding-left: 5px !important; } - .react-syntax-highlighter-line-number { - font-size: .85rem; - } - .syntax-shell .react-syntax-highlighter-line-number { opacity: 0.5; visibility: hidden; diff --git a/themes/default/page/index.js b/themes/default/page/index.js index 6c014aa..ead7265 100644 --- a/themes/default/page/index.js +++ b/themes/default/page/index.js @@ -4,7 +4,52 @@ import axios from 'axios' import Markdown from '../markdown' import Loading from '../loading' import { ConfigContext } from '../context' -import { Wrapper } from './styles' +import { Wrapper, ContentWrapper, TOC } from './styles' + +const TableOfContents = ({ toc }) => { + // Don't show this if there aren't enough headers + if (toc.length < 2) return null + + // Create TOC hierarchy and link to headers + const items = toc.map(t => ( +
  • + + {t.content} + +
  • + )) + + return ( + +
      +
      Contents
      + {items} +
    +
    + ) +} + +const Content = ({ content, config, route }) => { + const defaultContent = '##### _You don\'t have any content here yet!_' + + // Prepend route title to content if `prependTitles` is set to true in config + let md = content + if (config.prefix_titles) { + md = `# ${route.title} \n ${content}` + } + + return ( + + + + ) +} export default class Page extends Component { static displayName = 'Page' @@ -14,6 +59,7 @@ export default class Page extends Component { this.state = { loading: !props.route.content, content: props.route.content, + toc: props.route.toc, } } @@ -27,8 +73,10 @@ export default class Page extends Component { }) this._socket.addEventListener('message', evt => { + const { content, toc } = JSON.parse(evt.data) this.setState({ - content: evt.data, + content, + toc, loading: false, }) }) @@ -36,6 +84,7 @@ export default class Page extends Component { const { data } = await axios.get('index.json') this.setState({ // eslint-disable-line content: data.content, + toc: data.toc, loading: false, }) } @@ -55,10 +104,9 @@ export default class Page extends Component { const { loading, content, + toc, } = this.state - const defaultContent = '##### _You don\'t have any content here yet!_' - return ( {config => @@ -66,17 +114,23 @@ export default class Page extends Component { {route.title} - -
    - {loading - ? - : ( - - )} -
    + { + loading && + + } + { + !loading && + + } + { + !loading && + config.table_of_contents && + + } }
    diff --git a/themes/default/page/styles.js b/themes/default/page/styles.js index a487fbb..b28887f 100644 --- a/themes/default/page/styles.js +++ b/themes/default/page/styles.js @@ -1,8 +1,57 @@ import styled from 'react-emotion' export const Wrapper = styled('div')` - padding: 20px 40px; - width: 100%; - max-width: 800px; + padding: 30px 50px; + max-width: 1024px; box-sizing: border-box; + display: flex; + + @media(max-width: 1024px) { + flex-direction: column-reverse; + nav { margin-left: 0 } + } + + @media(min-width: 1450px) { + max-width: 1200px; + } +` + +export const TOC = styled('nav')` + margin-left: 2rem; + width: 150px; + flex-grow: 0; + + ul { + list-style: none; + border-left: 1px solid #E6E9EB; + padding-left: 2rem; + } + + h5 { + color: #848B8E; + margin: 0; + } + + li { + font-size: 13px; + line-height: 30px; + display: block; + } + + a { + text-decoration: none; + color: #626469; + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + &:hover { + color: #5742C7; + } + } +` + +export const ContentWrapper = styled('div')` + padding: 0 50px; ` diff --git a/themes/default/search/index.js b/themes/default/search/index.js index 13224c9..5a0f272 100644 --- a/themes/default/search/index.js +++ b/themes/default/search/index.js @@ -1,27 +1,20 @@ import React, { Component } from 'react' +import enhanceClickOutside from 'react-click-outside' import { Link } from 'react-router-dom' import axios from 'axios' import Highlight from 'react-highlight-words' +import { Search as SearchIcon, ChevronRight } from 'react-feather' import { createDB } from './db' import strip from './strip' import history from '../history' -import { Wrapper, Input, Results, Result } from './styles' +import { ellipsify } from '../utils' +import { Wrapper, Input, Results, Result, Center } from './styles' const UP = 'ArrowUp' const DOWN = 'ArrowDown' const ENTER = 'Enter' const ESCAPE = 'Escape' -function ellipsify (text, limit) { - if (!text) return '' - - if (text.length <= limit) { - return text - } - - return `${text.substring(0, limit)}...` -} - class Search extends Component { constructor (props) { super(props) @@ -38,6 +31,33 @@ class Search extends Component { this.loadResults() } + componentDidUpdate (prevProps, prevState) { + if (this.state.selectedIndex !== prevState.selectedIndex) { + this.ensureActiveItemVisible() + } + } + + ensureActiveItemVisible () { + if (!this.activeItem) return false + + const distanceFromTop = this.activeItem.offsetTop + const height = this.activeItem.offsetHeight + const scrollTop = this.results.scrollTop + const clientHeight = this.results.clientHeight + + if (distanceFromTop === 0) { + return this.results.scrollTop = 0 + } + + if (distanceFromTop < scrollTop) { + return this.results.scrollTop = distanceFromTop + } + + if ((distanceFromTop + height) > (scrollTop + clientHeight)) { + return this.results.scrollTop = distanceFromTop - height + } + } + async loadResults () { // Initialize search instance and set indices const resp = await axios.get('/db.json') @@ -52,7 +72,8 @@ class Search extends Component { const { value } = e.target this.setState({ query: value, - loading: value.length !== 0 + loading: value.length !== 0, + selectedIndex: 0, }, async () => { const results = await this.fetchResults(value) this.setState({ results, loading: false }) @@ -106,6 +127,10 @@ class Search extends Component { this.setState({ selectedIndex: nextIndex }) } + handleClickOutside () { + this.clearSearch() + } + fetchResults (query) { return new Promise((resolve, reject) => { const results = this.db @@ -116,7 +141,36 @@ class Search extends Component { } clearSearch = () => { - this.setState({ loading: false, query: '', results: [] }) + this.setState({ + loading: false, + query: '', + results: [], + selectedIndex: 0, + }) + } + + renderBreadCrumb (result) { + return result + .breadcrumb + .slice(1, result.breadcrumb.length) + .concat(result.title) + .map((b, i) => ( + + { + i !== 0 && + + } + {b} + + )) } renderResults () { @@ -128,16 +182,17 @@ class Search extends Component { i === selectedIndex ? this.activeItem = ref : null} onClick={this.clearSearch} > -

    {r.title}

    +

    {this.renderBreadCrumb(r)}

    3 ? query.split(' ') : []} + searchWords={query.length > 2 ? query.split(' ') : []} autoEscape - textToHighlight={strip(ellipsify(r.content, 400))} + textToHighlight={strip(ellipsify(r.content, 200))} />

    {r.url} @@ -146,9 +201,9 @@ class Search extends Component { ) return ( - + this.results = ref}> {items.length !== 0 && !loading && items} - {items.length === 0 && !loading && No Results...} + {items.length === 0 && !loading &&
    No Results Found matching {`"${query}"`}...
    } {loading && Loading...}
    ) @@ -157,6 +212,7 @@ class Search extends Component { render () { return ( + props.selected ? '#f6f5fb' : '#FFF'}; a { text-decoration: none } &:hover { background: #f6f5fb; - h4 { color: #6457DC; } + h4 { color: #6457DC; text-decoration: underline; } } h4 { font-weight: bold; - text-decoration: underline; + text-decoration: none; margin: 0; color: ${props => props.selected ? '#6457DC' : '#0d2b3e'}; + text-decoration: ${props => props.selected ? 'underline' : 'none'}; } p { - color: rgba(0,0,0,0.85); + color: rgba(0,0,0,0.75); text-decoration: none; margin: 0; + font-size: 1rem; } p .highlight { background: #d1ccec } .url { font-size: 12px; } ` + +export const Center = styled('div')` + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +` diff --git a/themes/default/sidebar/index.js b/themes/default/sidebar/index.js index 1bae472..d917116 100644 --- a/themes/default/sidebar/index.js +++ b/themes/default/sidebar/index.js @@ -1,6 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { withRouter, NavLink } from 'react-router-dom' +import styled from 'react-emotion' import { Reveal } from '@timberio/ui' import Logo from '../logo' import IconHamburger from '../icons/hamburger' @@ -18,6 +19,15 @@ import { Callout, } from './styles' +const Divider = styled('div')` + border-bottom: 1px solid #dfe2e6; + margin: .5rem 1rem .5rem 0; +` + +const componentMap = { + Divider +} + class Sidebar extends Component { static propTypes = { manifest: PropTypes.object, @@ -50,9 +60,7 @@ class Sidebar extends Component { renderTrigger = ({ title, url, component }) => { // @TODO: custom components if (component) { - // return ( - //
    {`<${component} />`}
    - // ) + return React.createElement(componentMap[component]) } if (!url) { @@ -140,15 +148,14 @@ class Sidebar extends Component { - - - Powered by GitDocs - + + Powered by GitDocs +
    } diff --git a/themes/default/sidebar/styles.js b/themes/default/sidebar/styles.js index e5d45e9..0b61091 100644 --- a/themes/default/sidebar/styles.js +++ b/themes/default/sidebar/styles.js @@ -15,8 +15,9 @@ export const Wrapper = styled('div')` display: flex; flex-direction: column; height: 100vh; - max-width: 250px; margin-left: auto; + min-width: 270px; + max-width: 270px; text-align: left; @media (max-width: 850px) { max-width: 100%; @@ -30,19 +31,22 @@ export const Wrapper = styled('div')` export const TopWrapper = styled('div')` flex-shrink: 0; display: flex; - justify-content: center; + justify-content: flex-start; align-items: center; height: 70px; padding: 0 20px; + border-bottom: 1px solid #E6E9EB; @media (max-width: 850px) { justify-content: space-between; } ` export const MenuWrapper = styled('div')` - flex: 1; + flex: 1 1 auto; display: flex; flex-direction: column; + overflow: scroll; + @media (max-width: 850px) { background: #F5F7F9; box-shadow: -2px 0 3px rgba(0, 0, 0, .2); @@ -81,9 +85,7 @@ export const Hamburger = styled('div')` export const Nav = styled('nav')` flex: 1 0 auto; - border-top: 1px solid #E6E9EB; - border-bottom: 1px solid #E6E9EB; - padding: 30px 0 30px 15px; + padding: 20px 0 20px 15px; ` export const NavList = styled(Accordion)` @@ -134,6 +136,7 @@ export const Callout = styled('a')` padding: 20px 0; text-decoration: none; text-align: center; + border-top: 1px solid #E6E9EB; :hover { color: rgba(0, 0, 0, .3); } diff --git a/themes/default/utils/index.js b/themes/default/utils/index.js new file mode 100644 index 0000000..c151084 --- /dev/null +++ b/themes/default/utils/index.js @@ -0,0 +1,9 @@ +export function ellipsify (text, limit) { + if (!text) return '' + + if (text.length <= limit) { + return text + } + + return `${text.substring(0, limit)}...` +} diff --git a/yarn.lock b/yarn.lock index f635b76..d6cf9c2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -360,6 +360,12 @@ ansi-html@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + dependencies: + ansi-wrap "0.1.0" + ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -378,6 +384,10 @@ ansi-styles@^3.1.0, ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + ansi@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/ansi/-/ansi-0.3.1.tgz#0c42d4fb17160d5a9af1e484bace1c66922c1b21" @@ -435,6 +445,13 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@~0.1.15: + version "0.1.16" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c" + dependencies: + underscore "~1.7.0" + underscore.string "~2.4.0" + aria-query@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-0.7.1.tgz#26cbb5aff64144b0a825be1846e0b16cfa00b11e" @@ -567,6 +584,10 @@ atob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" +autolinker@~0.15.0: + version "0.15.3" + resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.15.3.tgz#342417d8f2f3461b14cf09088d5edf8791dc9832" + aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -1741,6 +1762,10 @@ code@^5.2.0: dependencies: hoek "5.x.x" +coffee-script@^1.12.4: + version "1.12.7" + resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.12.7.tgz#c05dae0cb79591d05b3070a8433a98c9a89ccc53" + collapse-white-space@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091" @@ -1804,7 +1829,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.5.0, concat-stream@^1.6.0: +concat-stream@^1.5.0, concat-stream@^1.5.2, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" dependencies: @@ -2222,6 +2247,10 @@ detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" +diacritics-map@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/diacritics-map/-/diacritics-map-0.1.0.tgz#6dfc0ff9d01000a2edf2865371cac316e94977af" + diff@3.5.0, diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -3385,6 +3414,16 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6 version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +gray-matter@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-2.1.1.tgz#3042d9adec2a1ded6a7707a9ed2380f8a17a430e" + dependencies: + ansi-red "^0.1.1" + coffee-script "^1.12.4" + extend-shallow "^2.0.1" + js-yaml "^3.8.1" + toml "^2.3.2" + gray-matter@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.1.tgz#375263c194f0d9755578c277e41b1c1dfdf22c7d" @@ -3574,7 +3613,7 @@ hoek@5.x.x: version "5.0.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-5.0.3.tgz#b71d40d943d0a95da01956b547f83c4a5b4a34ac" -hoist-non-react-statics@^2.3.0, hoist-non-react-statics@^2.3.1: +hoist-non-react-statics@^2.1.1, hoist-non-react-statics@^2.3.0, hoist-non-react-statics@^2.3.1: version "2.5.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" @@ -4118,7 +4157,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.11.0, js-yaml@^3.6.1, js-yaml@^3.9.0, js-yaml@^3.9.1: +js-yaml@^3.11.0, js-yaml@^3.6.1, js-yaml@^3.8.1, js-yaml@^3.9.0, js-yaml@^3.9.1: version "3.11.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" dependencies: @@ -4246,6 +4285,12 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" +lazy-cache@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" + dependencies: + set-getter "^0.1.0" + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -4273,6 +4318,15 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +list-item@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/list-item/-/list-item-1.1.1.tgz#0c65d00e287cb663ccb3cb3849a77e89ec268a56" + dependencies: + expand-range "^1.8.1" + extend-shallow "^2.0.1" + is-number "^2.1.0" + repeat-string "^1.5.2" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -4420,6 +4474,27 @@ markdown-escapes@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.2.tgz#e639cbde7b99c841c0bacc8a07982873b46d2122" +markdown-link@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/markdown-link/-/markdown-link-0.1.1.tgz#32c5c65199a6457316322d1e4229d13407c8c7cf" + +markdown-toc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/markdown-toc/-/markdown-toc-1.2.0.tgz#44a15606844490314afc0444483f9e7b1122c339" + dependencies: + concat-stream "^1.5.2" + diacritics-map "^0.1.0" + gray-matter "^2.1.0" + lazy-cache "^2.0.2" + list-item "^1.1.1" + markdown-link "^0.1.1" + minimist "^1.2.0" + mixin-deep "^1.1.3" + object.pick "^1.2.0" + remarkable "^1.7.1" + repeat-string "^1.6.1" + strip-color "^0.1.0" + math-random@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" @@ -4603,7 +4678,7 @@ mississippi@^2.0.0: stream-each "^1.1.0" through2 "^2.0.0" -mixin-deep@^1.2.0: +mixin-deep@^1.1.3, mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" dependencies: @@ -4985,7 +5060,7 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -object.pick@^1.3.0: +object.pick@^1.2.0, object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" dependencies: @@ -5574,6 +5649,16 @@ rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-click-outside@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/react-click-outside/-/react-click-outside-3.0.1.tgz#6e77e84d2f17afaaac26dbad743cbbf909f5e24c" + dependencies: + hoist-non-react-statics "^2.1.1" + +react-content-loader@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/react-content-loader/-/react-content-loader-3.1.2.tgz#98230b4604b4b744eaa2d3fc88917dd988df6766" + react-dom@^16.3.2, react-dom@^16.4.0: version "16.4.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.0.tgz#099f067dd5827ce36a29eaf9a6cdc7cbf6216b1e" @@ -5590,6 +5675,10 @@ react-emotion@^9.1.3: babel-plugin-emotion "^9.1.2" create-emotion-styled "^9.1.2" +react-feather@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-1.1.0.tgz#f0aa692497de952237ca1f3b118ebcb5427152e1" + react-helmet@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.0.tgz#a81811df21313a6d55c5f058c4aeba5d6f3d97a7" @@ -5859,6 +5948,13 @@ remark-parse@^5.0.0: vfile-location "^2.0.0" xtend "^4.0.1" +remarkable@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.1.tgz#aaca4972100b66a642a63a1021ca4bac1be3bff6" + dependencies: + argparse "~0.1.15" + autolinker "~0.15.0" + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -6137,6 +6233,12 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" +set-getter@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" + dependencies: + to-object-path "^0.3.0" + set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" @@ -6549,6 +6651,10 @@ strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" +strip-color@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b" + strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" @@ -6742,6 +6848,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toml@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.3.tgz#8d683d729577cb286231dfc7a8affe58d31728fb" + touch@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de" @@ -6885,6 +6995,14 @@ unbzip2-stream@^1.0.9: buffer "^3.0.1" through "^2.3.6" +underscore.string@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" + +underscore@~1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" + unherit@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c"