diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..339cbf23 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v5.10.0 diff --git a/lib/Registry.js b/lib/Registry.js index 43241647..5055c9df 100644 --- a/lib/Registry.js +++ b/lib/Registry.js @@ -5,7 +5,8 @@ * is populated during compilation in the "index" phase. */ function Registry() { - this.entries = {}; + this.indices = {}; + this.tokens = []; } /** @@ -30,11 +31,11 @@ function Registry() { * index. Things like doc ID or title or such. */ Registry.prototype.add = function(id, entry) { - this.entries[id] = entry; + this.indices[id] = entry; }; Registry.prototype.get = function(id) { - return this.entries[id]; + return this.indices[id]; }; /** @@ -43,12 +44,19 @@ Registry.prototype.get = function(id) { * is the index data. */ Registry.prototype.toJSON = function() { - return this.entries; + return { + indices: this.indices, + tokens: this.tokens + }; +}; + +Registry.prototype.addSearchToken = function(token) { + this.tokens.push(token); }; Object.defineProperty(Registry.prototype, 'size', { get: function() { - return Object.keys(this.entries).length; + return Object.keys(this.indices).length; } }); diff --git a/lib/plugins/core/config.js b/lib/plugins/core/config.js index 012168b8..4e142107 100644 --- a/lib/plugins/core/config.js +++ b/lib/plugins/core/config.js @@ -225,5 +225,7 @@ module.exports = { * * Only works when using the single page layout. */ - scrollSpying: false + scrollSpying: false, + + spotlight: true, }; diff --git a/lib/plugins/core/write.js b/lib/plugins/core/write.js index def2828a..10b6f140 100644 --- a/lib/plugins/core/write.js +++ b/lib/plugins/core/write.js @@ -114,6 +114,8 @@ function generateRuntimeConfigScript(compiler, config, database) { runtimeConfig.pluginCount += 1; } + runtimeConfig.registry = compiler.registry.toJSON(); + console.log('Registered UI plugins:', compiler.assets.pluginScripts.map(function(filePath) { return path.basename(filePath); diff --git a/package.json b/package.json index f464cf28..ae561b64 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tinydoc", - "version": "4.0.1", + "version": "4.0.2", "description": "Fast and sleek and modular documentation generator.", "main": "lib/index.js", "bin": { @@ -37,8 +37,10 @@ "commander": "^2.8.1", "css-loader": "0.9.1", "deep-get-set": "^0.1.1", + "dom-contains": "^0.2.0", "file-loader": "^0.8.4", "fs-extra": "0.18.0", + "fuse.js": "2.2.0", "git-log-parser": "^1.1.0", "glob": "5.0.3", "htmlparser2": "^3.8.3", diff --git a/ui/css/components/banner.less b/ui/css/components/banner.less index 9b523eca..02bcbef3 100644 --- a/ui/css/components/banner.less +++ b/ui/css/components/banner.less @@ -47,6 +47,7 @@ text-align: center; min-width: 100px; margin-left: -@banner-border-dim; + cursor: pointer; a { display: block; diff --git a/ui/css/components/spotlight.less b/ui/css/components/spotlight.less new file mode 100644 index 00000000..a4369295 --- /dev/null +++ b/ui/css/components/spotlight.less @@ -0,0 +1,85 @@ +.spotlight { + &__wrapper { + background: rgba(0,0,0,.4); + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 2000; + padding-top: 30vh; + font-family: Slack-Lato,appleLogo,sans-serif; + } + + width: 460px; + display: block; + box-shadow: 0 1px 10px rgba(0,0,0,.5); + background: #fff; + border-radius: 8px; + padding: .75rem 1rem; + margin: 0 auto; + + &__input { + width: 100%; + max-width: 100%; + outline: 0; + line-height: normal; + + font-size: 2rem; + font-family: appleLogo,sans-serif; + font-weight: 700; + padding: 1rem; + border: 1px solid #a0a0a2!important; + border-radius: 6px; + box-shadow: none!important; + color: #2c2d30; + } + + &__results { + padding: 0; + margin: 0; + max-height: 30vh; + overflow: auto; + + &:not(:empty) { + margin-top: 0.5rem; + } + } + + &__result a { + display: block; + text-decoration: none; + border-radius: 6px; + padding: 0.1rem 0.5rem; + } + + &__help { + margin: 0 0 .5rem; + color: #8b898f; + font-size: .7rem; + display: block; + + &-entry { + display: inline-block; + margin-left: 0.25rem; + } + } +} + +.schemable({ + .spotlight { + &__highlighted-term { + background-color: @code; + } + + &__result { + list-style: none; + color: @base0; + + &--active a, a:hover, a:focus { + background: @link; + color: @base3; + } + } + } +}); \ No newline at end of file diff --git a/ui/css/index.less b/ui/css/index.less index f9f7357e..1c174ce4 100644 --- a/ui/css/index.less +++ b/ui/css/index.less @@ -73,6 +73,13 @@ ul, ol { font-family: inherit; } +.float--right { + float: right; +} +.float--left { + float: left; +} + .schemable({ background-color: @base3; color: @base0; @@ -152,3 +159,4 @@ ul, ol { @import 'components/hot-item-indicator'; @import 'components/anchorable-heading'; @import 'components/resizable'; +@import 'components/spotlight'; diff --git a/ui/index.js b/ui/index.js index 79488cf0..2493b1c6 100644 --- a/ui/index.js +++ b/ui/index.js @@ -51,6 +51,12 @@ tinydoc.onReady(function(registrar) { {registrar.getRouteMap()} + + + {config.spotlight && ( + + )} + @@ -93,7 +102,7 @@ const Root = React.createClass({ trackLayoutChange() { this.setState({ layoutChanged: true }); - } + }, }); module.exports = Root; \ No newline at end of file diff --git a/ui/screens/Search.js b/ui/screens/Search.js new file mode 100644 index 00000000..bc773862 --- /dev/null +++ b/ui/screens/Search.js @@ -0,0 +1,12 @@ +const React = require('react'); +const Spotlight = require('components/Spotlight'); + +const Search = React.createClass({ + render() { + return ( + + ); + } +}); + +module.exports = Search; diff --git a/ui/shared/components/Banner.js b/ui/shared/components/Banner.js index 42ce8d9d..b64955e1 100644 --- a/ui/shared/components/Banner.js +++ b/ui/shared/components/Banner.js @@ -3,6 +3,7 @@ var Link = require("components/Link"); var Outlet = require("components/Outlet"); var config = require('config'); var Icon = require('components/Icon'); +const AppState = require('core/AppState'); var BannerItem = React.createClass({ propTypes: { @@ -49,7 +50,13 @@ var Banner = React.createClass({