diff --git a/.gitignore b/.gitignore index c4f61d9a..09e622f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .DS_Store .cache docs/dist +docs/search.json dist examples node_modules diff --git a/docs/404.md b/docs/404.md index 3d4de0e7..822aef5f 100644 --- a/docs/404.md +++ b/docs/404.md @@ -1,3 +1,5 @@ # Not Found -Sorry, I couldn't find that page. +Cute monsters hiding behind a tree + +Sorry, I couldn't find that page. Have you tried pressing / to search? diff --git a/docs/assets/images/undraw-not-found.svg b/docs/assets/images/undraw-not-found.svg new file mode 100644 index 00000000..aea1d505 --- /dev/null +++ b/docs/assets/images/undraw-not-found.svg @@ -0,0 +1 @@ +not found \ No newline at end of file diff --git a/docs/assets/plugins/search/lunr.min.js b/docs/assets/plugins/search/lunr.min.js new file mode 100644 index 00000000..d5218778 --- /dev/null +++ b/docs/assets/plugins/search/lunr.min.js @@ -0,0 +1,6 @@ +/** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + */ + !function(){var e=function(t){var r=new e.Builder;return r.pipeline.add(e.trimmer,e.stopWordFilter,e.stemmer),r.searchPipeline.add(e.stemmer),t.call(r,r),r.build()};e.version="2.3.9",e.utils={},e.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),e.utils.asString=function(e){return void 0===e||null===e?"":e.toString()},e.utils.clone=function(e){if(null===e||void 0===e)return e;for(var t=Object.create(null),r=Object.keys(e),i=0;i0){var c=e.utils.clone(r)||{};c.position=[a,l],c.index=s.length,s.push(new e.Token(i.slice(a,o),c))}a=o+1}}return s},e.tokenizer.separator=/[\s\-]+/,e.Pipeline=function(){this._stack=[]},e.Pipeline.registeredFunctions=Object.create(null),e.Pipeline.registerFunction=function(t,r){r in this.registeredFunctions&&e.utils.warn("Overwriting existing registered function: "+r),t.label=r,e.Pipeline.registeredFunctions[t.label]=t},e.Pipeline.warnIfFunctionNotRegistered=function(t){var r=t.label&&t.label in this.registeredFunctions;r||e.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",t)},e.Pipeline.load=function(t){var r=new e.Pipeline;return t.forEach(function(t){var i=e.Pipeline.registeredFunctions[t];if(!i)throw new Error("Cannot load unregistered function: "+t);r.add(i)}),r},e.Pipeline.prototype.add=function(){var t=Array.prototype.slice.call(arguments);t.forEach(function(t){e.Pipeline.warnIfFunctionNotRegistered(t),this._stack.push(t)},this)},e.Pipeline.prototype.after=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,r)},e.Pipeline.prototype.before=function(t,r){e.Pipeline.warnIfFunctionNotRegistered(r);var i=this._stack.indexOf(t);if(i==-1)throw new Error("Cannot find existingFn");this._stack.splice(i,0,r)},e.Pipeline.prototype.remove=function(e){var t=this._stack.indexOf(e);t!=-1&&this._stack.splice(t,1)},e.Pipeline.prototype.run=function(e){for(var t=this._stack.length,r=0;r1&&(se&&(r=n),s!=e);)i=r-t,n=t+Math.floor(i/2),s=this.elements[2*n];return s==e?2*n:s>e?2*n:sa?l+=2:o==a&&(t+=r[u+1]*i[l+1],u+=2,l+=2);return t},e.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},e.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),t=1,r=0;t0){var o,a=s.str.charAt(0);a in s.node.edges?o=s.node.edges[a]:(o=new e.TokenSet,s.node.edges[a]=o),1==s.str.length&&(o["final"]=!0),n.push({node:o,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(0!=s.editsRemaining){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new e.TokenSet;s.node.edges["*"]=u}if(0==s.str.length&&(u["final"]=!0),n.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&n.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),1==s.str.length&&(s.node["final"]=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new e.TokenSet;s.node.edges["*"]=l}1==s.str.length&&(l["final"]=!0),n.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var c,h=s.str.charAt(0),d=s.str.charAt(1);d in s.node.edges?c=s.node.edges[d]:(c=new e.TokenSet,s.node.edges[d]=c),1==s.str.length&&(c["final"]=!0),n.push({node:c,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return i},e.TokenSet.fromString=function(t){for(var r=new e.TokenSet,i=r,n=0,s=t.length;n=e;t--){var r=this.uncheckedNodes[t],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r["char"]]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}},e.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},e.Index.prototype.search=function(t){return this.query(function(r){var i=new e.QueryParser(t,r);i.parse()})},e.Index.prototype.query=function(t){for(var r=new e.Query(this.fields),i=Object.create(null),n=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},e.Builder.prototype.k1=function(e){this._k1=e},e.Builder.prototype.add=function(t,r){var i=t[this._ref],n=Object.keys(this._fields);this._documents[i]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return e.QueryLexer.EOS;var t=this.str.charAt(this.pos);return this.pos+=1,t},e.QueryLexer.prototype.width=function(){return this.pos-this.start},e.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},e.QueryLexer.prototype.backup=function(){this.pos-=1},e.QueryLexer.prototype.acceptDigitRun=function(){var t,r;do t=this.next(),r=t.charCodeAt(0);while(r>47&&r<58);t!=e.QueryLexer.EOS&&this.backup()},e.QueryLexer.prototype.more=function(){return this.pos1&&(t.backup(),t.emit(e.QueryLexer.TERM)),t.ignore(),t.more())return e.QueryLexer.lexText},e.QueryLexer.lexEditDistance=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.EDIT_DISTANCE),e.QueryLexer.lexText},e.QueryLexer.lexBoost=function(t){return t.ignore(),t.acceptDigitRun(),t.emit(e.QueryLexer.BOOST),e.QueryLexer.lexText},e.QueryLexer.lexEOS=function(t){t.width()>0&&t.emit(e.QueryLexer.TERM)},e.QueryLexer.termSeparator=e.tokenizer.separator,e.QueryLexer.lexText=function(t){for(;;){var r=t.next();if(r==e.QueryLexer.EOS)return e.QueryLexer.lexEOS;if(92!=r.charCodeAt(0)){if(":"==r)return e.QueryLexer.lexField;if("~"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexEditDistance;if("^"==r)return t.backup(),t.width()>0&&t.emit(e.QueryLexer.TERM),e.QueryLexer.lexBoost;if("+"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if("-"==r&&1===t.width())return t.emit(e.QueryLexer.PRESENCE),e.QueryLexer.lexText;if(r.match(e.QueryLexer.termSeparator))return e.QueryLexer.lexTerm}else t.escapeCharacter()}},e.QueryParser=function(t,r){this.lexer=new e.QueryLexer(t),this.query=r,this.currentClause={},this.lexemeIdx=0},e.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var t=e.QueryParser.parseClause;t;)t=t(this);return this.query},e.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},e.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},e.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},e.QueryParser.parseClause=function(t){var r=t.peekLexeme();if(void 0!=r)switch(r.type){case e.QueryLexer.PRESENCE:return e.QueryParser.parsePresence;case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(i+=" with value '"+r.str+"'"),new e.QueryParseError(i,r.start,r.end)}},e.QueryParser.parsePresence=function(t){var r=t.consumeLexeme();if(void 0!=r){switch(r.str){case"-":t.currentClause.presence=e.Query.presence.PROHIBITED;break;case"+":t.currentClause.presence=e.Query.presence.REQUIRED;break;default:var i="unrecognised presence operator'"+r.str+"'";throw new e.QueryParseError(i,r.start,r.end)}var n=t.peekLexeme();if(void 0==n){var i="expecting term or field, found nothing";throw new e.QueryParseError(i,r.start,r.end)}switch(n.type){case e.QueryLexer.FIELD:return e.QueryParser.parseField;case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var i="expecting term or field, found '"+n.type+"'";throw new e.QueryParseError(i,n.start,n.end)}}},e.QueryParser.parseField=function(t){var r=t.consumeLexeme();if(void 0!=r){if(t.query.allFields.indexOf(r.str)==-1){var i=t.query.allFields.map(function(e){return"'"+e+"'"}).join(", "),n="unrecognised field '"+r.str+"', possible fields: "+i;throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.fields=[r.str];var s=t.peekLexeme();if(void 0==s){var n="expecting term, found nothing";throw new e.QueryParseError(n,r.start,r.end)}switch(s.type){case e.QueryLexer.TERM:return e.QueryParser.parseTerm;default:var n="expecting term, found '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseTerm=function(t){var r=t.consumeLexeme();if(void 0!=r){t.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(t.currentClause.usePipeline=!1);var i=t.peekLexeme();if(void 0==i)return void t.nextClause();switch(i.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+i.type+"'";throw new e.QueryParseError(n,i.start,i.end)}}},e.QueryParser.parseEditDistance=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="edit distance must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.editDistance=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},e.QueryParser.parseBoost=function(t){var r=t.consumeLexeme();if(void 0!=r){var i=parseInt(r.str,10);if(isNaN(i)){var n="boost must be numeric";throw new e.QueryParseError(n,r.start,r.end)}t.currentClause.boost=i;var s=t.peekLexeme();if(void 0==s)return void t.nextClause();switch(s.type){case e.QueryLexer.TERM:return t.nextClause(),e.QueryParser.parseTerm;case e.QueryLexer.FIELD:return t.nextClause(),e.QueryParser.parseField;case e.QueryLexer.EDIT_DISTANCE:return e.QueryParser.parseEditDistance;case e.QueryLexer.BOOST:return e.QueryParser.parseBoost;case e.QueryLexer.PRESENCE:return t.nextClause(),e.QueryParser.parsePresence;default:var n="Unexpected lexeme type '"+s.type+"'";throw new e.QueryParseError(n,s.start,s.end)}}},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.lunr=t()}(this,function(){return e})}(); diff --git a/docs/assets/plugins/search/search.css b/docs/assets/plugins/search/search.css new file mode 100644 index 00000000..0a0a6b53 --- /dev/null +++ b/docs/assets/plugins/search/search.css @@ -0,0 +1,125 @@ +body.site-search-visible { + overflow: hidden; +} + +.sidebar .search-box { + margin: 1.25rem 26px; +} + +.sidebar .search-box kbd { + margin-top: 2px; +} + +/* Site search */ +.site-search { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1000; +} + +.site-search[hidden] { + display: none; +} + +.site-search__overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgb(var(--sl-overlay-background-color) / var(--sl-overlay-opacity)); + z-index: -1; +} + +.site-search__panel { + display: flex; + flex-direction: column; + max-width: 460px; + max-height: calc(100vh - 20rem); + background-color: rgb(var(--sl-color-neutral-0)); + border-radius: var(--sl-border-radius-large); + box-shadow: var(--sl-shadow-x-large); + margin: 10rem auto; +} + +@media screen and (max-width: 1000px) { + .site-search__panel { + max-width: 100%; + max-height: 92vh; + margin: 4vh var(--sl-spacing-medium); + } +} + +.site-search__input::part(base) { + border: none; +} + +.site-search__input:focus-within::part(base) { + outline: none; + box-shadow: none; +} + +.site-search__body { + flex: 1 1 auto; + overflow: auto; +} + +.site-search--has-results .site-search__body { + border-top: solid 1px rgb(var(--sl-color-neutral-200)); +} + +.site-search__results { + display: none; + line-height: var(--sl-line-height-dense); + list-style: none; + padding: var(--sl-spacing-x-small) 0; + margin: 0; +} + +.site-search--has-results .site-search__results { + display: block; +} + +.site-search__results a { + display: block; + text-decoration: none; + padding: var(--sl-spacing-x-small) var(--sl-spacing-large); +} + +.site-search__results li a:hover, +.site-search__results li a:hover small, +.site-search__results li a[aria-selected], +.site-search__results li a[aria-selected] small { + outline: none; + color: rgb(var(--sl-color-neutral-0)); + background-color: rgb(var(--sl-color-primary-600)); +} + +.site-search__results h3 { + font-weight: var(--sl-font-weight-semibold); + margin: 0; +} + +.site-search__results li { + padding: 0; + margin: 0; +} + +.site-search__results small { + display: block; + color: rgb(var(--sl-color-neutral-600)); +} + +.site-search__empty { + display: none; + border-top: solid 1px rgb(var(--sl-color-neutral-200)); + text-align: center; + padding: var(--sl-spacing-x-large); +} + +.site-search--no-results .site-search__empty { + display: block; +} diff --git a/docs/assets/plugins/search/search.js b/docs/assets/plugins/search/search.js new file mode 100644 index 00000000..42fa8dcb --- /dev/null +++ b/docs/assets/plugins/search/search.js @@ -0,0 +1,266 @@ +(() => { + if (!window.$docsify) { + throw new Error('Docsify must be loaded before installing this plugin.'); + } + + window.$docsify.plugins.push((hook, vm) => { + // Append the search box to the sidebar + hook.mounted(function () { + const appName = document.querySelector('.sidebar .app-name'); + const searchBox = document.createElement('div'); + searchBox.classList.add('search-box'); + searchBox.innerHTML = ` + + + / + + `; + const searchBoxInput = searchBox.querySelector('sl-input'); + + appName.insertAdjacentElement('afterend', searchBox); + + // Show the search panel when the search is clicked + searchBoxInput.addEventListener('mousedown', event => { + event.preventDefault(); + show(); + }); + + // Show the search panel when a key is pressed + searchBoxInput.addEventListener('keydown', event => { + if (event.key === 'Tab') { + return; + } + + // Pass the character that was typed through to the search input + if (event.key.length === 1) { + event.preventDefault(); + input.value = event.key; + show(); + } + }); + }); + + // Append the search panel to the body + const siteSearch = document.createElement('div'); + siteSearch.classList.add('site-search'); + siteSearch.hidden = true; + siteSearch.innerHTML = ` +
+
+
+ +
+
+
    +
    No results found.
    +
    +
    + `; + document.body.append(siteSearch); + + const searchButtons = [...document.querySelectorAll('[data-site-search]')]; + const overlay = siteSearch.querySelector('.site-search__overlay'); + const panel = siteSearch.querySelector('.site-search__panel'); + const input = siteSearch.querySelector('.site-search__input'); + const results = siteSearch.querySelector('.site-search__results'); + const animationDuration = 150; + const searchDebounce = 250; + let isShowing = false; + let searchTimeout; + let searchIndex; + let map; + + // Load search data + const searchData = fetch('../../../search.json') + .then(res => res.json()) + .then(data => { + searchIndex = lunr.Index.load(data.searchIndex); + map = data.map; + }); + + async function show() { + isShowing = true; + document.body.classList.add('site-search-visible'); + siteSearch.hidden = false; + input.focus(); + updateResults(); + + await Promise.all([ + panel.animate( + [ + { opacity: 0, transform: 'scale(.9)' }, + { opacity: 1, transform: 'scale(1)' } + ], + { duration: animationDuration } + ).finished, + overlay.animate([{ opacity: 0 }, { opacity: 1 }], { duration: animationDuration }).finished + ]); + + document.addEventListener('mousedown', handleDocumentMouseDown); + document.addEventListener('keydown', handleDocumentKeyDown); + document.addEventListener('focusin', handleDocumentFocusIn); + } + + async function hide() { + isShowing = false; + document.body.classList.remove('site-search-visible'); + + await Promise.all([ + panel.animate( + [ + { opacity: 1, transform: 'scale(1)' }, + { opacity: 0, transform: 'scale(.9)' } + ], + { duration: animationDuration } + ).finished, + overlay.animate([{ opacity: 1 }, { opacity: 0 }], { duration: animationDuration }).finished + ]); + + siteSearch.hidden = true; + input.value = ''; + updateResults(); + + document.removeEventListener('mousedown', handleDocumentMouseDown); + document.removeEventListener('keydown', handleDocumentKeyDown); + document.removeEventListener('focusin', handleDocumentFocusIn); + } + + function handleInput() { + // Debounce search queries + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => updateResults(input.value), searchDebounce); + } + + function handleDocumentFocusIn(event) { + // Close when focus leaves the panel + if (event.target.closest('.site-search__panel') !== panel) { + hide(); + } + } + + function handleDocumentMouseDown(event) { + // Close when clicking outside of the panel + if (event.target.closest('.site-search__overlay') === overlay) { + hide(); + } + } + + function handleDocumentKeyDown(event) { + // Close when pressing escape + if (event.key === 'Escape') { + event.preventDefault(); + hide(); + return; + } + + // Handle keyboard selections + if (['ArrowDown', 'ArrowUp', 'Home', 'End', 'Enter'].includes(event.key)) { + event.preventDefault(); + + const currentEl = results.querySelector('[aria-selected]'); + const items = [...results.querySelectorAll('a')]; + let nextEl; + + items.map(item => item.removeAttribute('aria-selected')); + + if (items.length === 0) { + return; + } + + const index = items.indexOf(currentEl); + + switch (event.key) { + case 'ArrowUp': + nextEl = items[Math.max(0, index - 1)]; + break; + case 'ArrowDown': + nextEl = items[Math.min(items.length - 1, index + 1)]; + break; + case 'Home': + nextEl = items[items.length > 0 ? 1 : 0]; + break; + case 'End': + nextEl = items[items.length - 1]; + break; + case 'Enter': + (currentEl || items[0]).click(); + break; + } + + if (nextEl) { + nextEl.setAttribute('aria-selected', 'true'); + nextEl.scrollIntoView({ block: 'nearest' }); + } + + return; + } + } + + async function updateResults(query = '') { + try { + await searchIndex; + + const hasQuery = query.length > 0; + const matches = hasQuery ? searchIndex.search(query) : []; + let id = 0; + + let hasResults = hasQuery && matches.length > 0; + siteSearch.classList.toggle('site-search--has-results', hasQuery && hasResults); + siteSearch.classList.toggle('site-search--no-results', hasQuery && !hasResults); + panel.setAttribute('aria-expanded', hasQuery && hasResults ? 'true' : 'false'); + + results.innerHTML = ''; + + matches.map(match => { + const page = map[match.ref]; + const li = document.createElement('li'); + const a = document.createElement('a'); + + a.href = $docsify.routerMode === 'hash' ? `/#/${page.url}` : `/${page.url}`; + a.innerHTML = ` +

    ${page.title}

    + /${page.url} + `; + + li.setAttribute('id', `search-result-${id++}`); + li.appendChild(a); + results.appendChild(li); + }); + } catch { + // Ignore query errors as the user types + } + } + + // Show the search panel slash is pressed outside of a form element + document.addEventListener('keydown', event => { + if ( + !isShowing && + event.key === '/' && + !event.composedPath().some(el => ['input', 'textarea'].includes(el?.tagName?.toLowerCase())) + ) { + event.preventDefault(); + show(); + } + }); + + input.addEventListener('sl-input', handleInput); + + // Close when a result is selected + results.addEventListener('click', event => { + if (event.target.closest('a')) { + hide(); + } + }); + }); +})(); diff --git a/docs/assets/plugins/sidebar/sidebar.js b/docs/assets/plugins/sidebar/sidebar.js deleted file mode 100644 index 1f8c3769..00000000 --- a/docs/assets/plugins/sidebar/sidebar.js +++ /dev/null @@ -1,14 +0,0 @@ -(() => { - if (!window.$docsify) { - throw new Error('Docsify must be loaded before installing this plugin.'); - } - - window.$docsify.plugins.push((hook, vm) => { - hook.mounted(function () { - // Move search below the app name - const appName = document.querySelector('.sidebar .app-name'); - const search = document.querySelector('.sidebar .search'); - appName.insertAdjacentElement('afterend', search); - }); - }); -})(); diff --git a/docs/assets/styles/docs.css b/docs/assets/styles/docs.css index 6b1b4dfb..8cb233b1 100644 --- a/docs/assets/styles/docs.css +++ b/docs/assets/styles/docs.css @@ -249,6 +249,11 @@ strong { max-width: 22rem; } +.markdown-section .splash-start h1:first-of-type { + font-size: var(--sl-font-size-large); + margin: 0 0 0.5rem 0; +} + @media screen and (max-width: 1040px) { .splash { display: block; @@ -375,12 +380,14 @@ strong { padding: 2px 4px; } +kbd, .markdown-section kbd { font-family: var(--sl-font-mono); font-size: 87.5%; border-radius: var(--sl-border-radius-small); border: solid 1px rgb(var(--sl-color-neutral-200)); - padding: 2px 4px; + box-shadow: var(--sl-shadow-small); + padding: 2px 5px; } /* Code blocks */ @@ -706,3 +713,9 @@ body[data-page^='/tokens/'] .table-wrapper td:first-child code { grid-column-start: span 6; } } + +.not-found-image { + display: block; + max-width: 460px; + margin: 2rem 0; +} diff --git a/docs/getting-started/overview.md b/docs/getting-started/overview.md index 3de995cd..4d85d950 100644 --- a/docs/getting-started/overview.md +++ b/docs/getting-started/overview.md @@ -2,12 +2,12 @@
    -**A forward-thinking library of web components.** +# A forward-thinking library of web components. - Works with all frameworks 🧩 - Works with CDNs 🚛 - Fully customizable with CSS 🎨 -- Includes an official dark theme 🌛 +- Includes a dark theme 🌛 - Built with accessibility in mind ♿️ - First-party [React wrappers](/getting-started/usage#react) - Open source 😸 diff --git a/docs/index.html b/docs/index.html index 4c937d72..ac940a5b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -34,6 +34,7 @@ + @@ -71,6 +72,7 @@ maxLevel: 3, subMaxLevel: 2, name: 'Shoelace', + nameLink: '/', notFoundPage: '404.md', pagination: { previousText: 'Previous', @@ -79,28 +81,20 @@ crossChapterText: false }, routerMode: 'history', - search: { - maxAge: 86400000, // Expiration time, the default one day - paths: 'auto', - placeholder: 'Search', - noData: 'No Results', - depth: 3, - namespace: 'shoelace-docs' - }, themeColor: 'rgb(var(--sl-color-primary-500))' }; - - - - + + + + diff --git a/docs/resources/community.md b/docs/resources/community.md index 7a9c0913..1143374d 100644 --- a/docs/resources/community.md +++ b/docs/resources/community.md @@ -1,6 +1,6 @@ # Community -Shoelace has a budding community of designers and developers that are building amazing things with web components. We'd love for you to become a part of it! +Shoelace has a growing community of designers and developers that are building amazing things with web components. We'd love for you to become a part of it! Please be respectful of other users and remember that Shoelace is an open source project. We'll try to help when we can, but there's no guarantee we'll be able solve your problem. Please manage your expectations and don't forget to contribute back to the conversation when you can! diff --git a/package-lock.json b/package-lock.json index a31fe479..9e08ba7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "get-port": "^5.1.1", "globby": "^11.0.4", "husky": "^4.3.8", + "lunr": "^2.3.9", "mkdirp": "^0.5.5", "plop": "^2.7.4", "prettier": "^2.2.1", @@ -6429,6 +6430,12 @@ "node": ">=0.10.0" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", @@ -16394,6 +16401,12 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", diff --git a/package.json b/package.json index da056ab7..34eeb81c 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "get-port": "^5.1.1", "globby": "^11.0.4", "husky": "^4.3.8", + "lunr": "^2.3.9", "mkdirp": "^0.5.5", "plop": "^2.7.4", "prettier": "^2.2.1", diff --git a/scripts/make-search.js b/scripts/make-search.js new file mode 100644 index 00000000..aee1adb1 --- /dev/null +++ b/scripts/make-search.js @@ -0,0 +1,65 @@ +import fs from 'fs'; +import path from 'path'; +import glob from 'globby'; +import lunr from 'lunr'; + +function getHeadings(markdown, maxLevel = 6) { + const headings = []; + const lines = markdown.split('\n'); + + lines.map(line => { + if (line.startsWith('#')) { + const level = line.match(/^(#+)/)[0].length; + const content = line.replace(/^#+/, ''); + + if (level <= maxLevel) { + headings.push({ level, content }); + } + } + }); + + return headings; +} + +console.log('Generating search index for documentation'); + +(async () => { + const files = await glob('./docs/**/*.md'); + + const map = {}; + const searchIndex = lunr(function () { + // The search index uses these field names extensively, so shortening them can save some serious bytes. The initial + // index file went from 468 KB => 401 KB. + this.ref('id'); // id + this.field('t', { boost: 10 }); // title + this.field('h', { boost: 5 }); // headings + this.field('c'); // content + + files.map((file, index) => { + const relativePath = path.relative('./docs', file); + const url = relativePath.replace(/\.md$/, ''); + const filename = path.basename(file); + + // Ignore certain directories and files + if (relativePath.startsWith('assets/') || relativePath.startsWith('dist/') || filename === '_sidebar.md') { + return false; + } + + const content = fs.readFileSync(file, 'utf8'); + const allHeadings = getHeadings(content, 4); + const title = + allHeadings.find(heading => heading.level === 1)?.content || + path.basename(path.basename(filename), path.extname(filename)); + const headings = allHeadings + .filter(heading => heading.level > 1) + .map(heading => heading.content) + .join('\n'); + + this.add({ id: index, t: title, h: headings, c: content }); + + map[index] = { title, url }; + }); + }); + + fs.writeFileSync('./docs/search.json', JSON.stringify({ searchIndex, map }), 'utf8'); +})(); diff --git a/src/themes/dark.styles.ts b/src/themes/dark.styles.ts index dd548c86..2a48688a 100644 --- a/src/themes/dark.styles.ts +++ b/src/themes/dark.styles.ts @@ -531,7 +531,7 @@ export default css` */ --sl-overlay-background-color: 0 0 0; - --sl-overlay-opacity: 42%; + --sl-overlay-opacity: 67%; /* * Panels