Improved documentation and fixed search reset

This commit is contained in:
squidfunk 2020-02-17 14:37:12 +01:00
parent fdffefd536
commit 7876148fbd
32 changed files with 106 additions and 68 deletions

2
.env
View File

@ -24,8 +24,6 @@
if [ ! -d venv ]; then if [ ! -d venv ]; then
echo "Setting up virtual environment" echo "Setting up virtual environment"
virtualenv venv virtualenv venv
echo "Installing dependencies"
pip install -r requirements.txt
fi fi
# Activate virtual environment # Activate virtual environment

View File

@ -185,7 +185,7 @@
"selector-class-pattern": "^[a-z0-9]+(-[a-z0-9]+)*(__[a-z]+)?(--[a-z]+)?$", "selector-class-pattern": "^[a-z0-9]+(-[a-z0-9]+)*(__[a-z]+)?(--[a-z]+)?$",
"selector-descendant-combinator-no-non-space": null, "selector-descendant-combinator-no-non-space": null,
"string-quotes": "double", "string-quotes": "double",
"unit-whitelist": ["px", "em", "deg", "s", "%", "mm", "vh", "dppx"], "unit-whitelist": ["px", "em", "deg", "ms", "%", "mm", "vh", "dppx"],
"value-keyword-case": "lower", "value-keyword-case": "lower",
"value-no-vendor-prefix": true "value-no-vendor-prefix": true
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,10 @@
{ {
"assets/javascripts/bundle.js": "assets/javascripts/bundle.af5dd3a5.min.js", "assets/javascripts/bundle.js": "assets/javascripts/bundle.525b1d98.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.af5dd3a5.min.js.map", "assets/javascripts/bundle.js.map": "assets/javascripts/bundle.525b1d98.min.js.map",
"assets/javascripts/worker/packer.js": "assets/javascripts/worker/packer.c14659e8.min.js", "assets/javascripts/worker/packer.js": "assets/javascripts/worker/packer.c14659e8.min.js",
"assets/javascripts/worker/packer.js.map": "assets/javascripts/worker/packer.c14659e8.min.js.map", "assets/javascripts/worker/packer.js.map": "assets/javascripts/worker/packer.c14659e8.min.js.map",
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.3144ce89.min.js", "assets/javascripts/worker/search.js": "assets/javascripts/worker/search.0a5433f7.min.js",
"assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.3144ce89.min.js.map", "assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.0a5433f7.min.js.map",
"assets/stylesheets/app-palette.scss": "assets/stylesheets/app-palette.3f90c815.min.css", "assets/stylesheets/app-palette.scss": "assets/stylesheets/app-palette.3f90c815.min.css",
"assets/stylesheets/app.scss": "assets/stylesheets/app.0ee2cfd0.min.css" "assets/stylesheets/app.scss": "assets/stylesheets/app.83fc891a.min.css"
} }

File diff suppressed because one or more lines are too long

View File

@ -43,7 +43,7 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/app.0ee2cfd0.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/app.83fc891a.min.css' | url }}">
{% if palette.primary or palette.accent %} {% if palette.primary or palette.accent %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/app-palette.3f90c815.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/app-palette.3f90c815.min.css' | url }}">
{% endif %} {% endif %}
@ -190,7 +190,7 @@
{% endblock %} {% endblock %}
</div> </div>
{% block scripts %} {% block scripts %}
<script src="{{ 'assets/javascripts/bundle.af5dd3a5.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/bundle.525b1d98.min.js' | url }}"></script>
<script id="__lang" type="application/json"> <script id="__lang" type="application/json">
{%- set translations = {} -%} {%- set translations = {} -%}
{%- for key in [ {%- for key in [
@ -209,7 +209,7 @@
{%- endfor -%} {%- endfor -%}
{{ translations | tojson }} {{ translations | tojson }}
</script> </script>
<script>app=initialize({base:"{{ base_url }}",worker:{search:"{{ 'assets/javascripts/worker/search.3144ce89.min.js' | url }}",packer:"{{ 'assets/javascripts/worker/packer.c14659e8.min.js' | url }}"}})</script> <script>app=initialize({base:"{{ base_url }}",worker:{search:"{{ 'assets/javascripts/worker/search.0a5433f7.min.js' | url }}",packer:"{{ 'assets/javascripts/worker/packer.c14659e8.min.js' | url }}"}})</script>
{% for path in config["extra_javascript"] %} {% for path in config["extra_javascript"] %}
<script src="{{ path | url }}"></script> <script src="{{ path | url }}"></script>
{% endfor %} {% endfor %}

View File

@ -82,7 +82,7 @@ let components$: Observable<ComponentMap>
* Watch components with given names * Watch components with given names
* *
* This function returns an observable that will maintain bindings to the given * This function returns an observable that will maintain bindings to the given
* components in-between document switches and update the document in-place. * components in-between document switches and update the components in-place.
* *
* @param names - Component names * @param names - Component names
* @param options - Options * @param options - Options

View File

@ -40,14 +40,14 @@ import {
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/** /**
* Navigation below screen breakpoint * Navigation for [screen -]
*/ */
export interface NavigationBelowScreen { export interface NavigationBelowScreen {
layer: NavigationLayer /* Active layer */ layer: NavigationLayer /* Active layer */
} }
/** /**
* Navigation above screen breakpoint * Navigation for [screen +]
*/ */
export interface NavigationAboveScreen { export interface NavigationAboveScreen {
sidebar: Sidebar /* Sidebar */ sidebar: Sidebar /* Sidebar */
@ -94,7 +94,7 @@ export function mountNavigation(
.pipe( .pipe(
switchMap(screen => { switchMap(screen => {
/* Mount navigation above screen breakpoint */ /* [screen +]: Mount navigation in sidebar */
if (screen) { if (screen) {
return watchSidebar(el, { main$, viewport$ }) return watchSidebar(el, { main$, viewport$ })
.pipe( .pipe(
@ -102,7 +102,7 @@ export function mountNavigation(
map(sidebar => ({ sidebar })) map(sidebar => ({ sidebar }))
) )
/* Mount navigation below screen breakpoint */ /* [screen -]: Mount navigation in drawer */
} else { } else {
const els = getElements("nav", el) const els = getElements("nav", el)
return watchNavigationLayer(els) return watchNavigationLayer(els)

View File

@ -79,19 +79,19 @@ export function mountSearch(
return pipe( return pipe(
switchMap(() => { switchMap(() => {
/* Mount search query */
const query$ = useComponent<HTMLInputElement>("search-query")
.pipe(
mountSearchQuery(handler),
shareReplay(1)
)
/* Mount search reset */ /* Mount search reset */
const reset$ = useComponent<HTMLInputElement>("search-reset") const reset$ = useComponent<HTMLInputElement>("search-reset")
.pipe( .pipe(
mountSearchReset() mountSearchReset()
) )
/* Mount search query */
const query$ = useComponent<HTMLInputElement>("search-query")
.pipe(
mountSearchQuery(handler, { reset$ }),
shareReplay(1)
)
/* Mount search result */ /* Mount search result */
const result$ = useComponent("search-result") const result$ = useComponent("search-result")
.pipe( .pipe(

View File

@ -63,7 +63,6 @@ export function mountSearchQuery(
/* Subscribe worker to search query */ /* Subscribe worker to search query */
query$ query$
.pipe( .pipe(
distinctUntilKeyChanged("value"),
map<SearchQuery, SearchQueryMessage>(({ value }) => ({ map<SearchQuery, SearchQueryMessage>(({ value }) => ({
type: SearchMessageType.QUERY, type: SearchMessageType.QUERY,
data: value data: value

View File

@ -47,12 +47,12 @@ import {
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/** /**
* Table of contents below tablet breakpoint * Table of contents for [tablet -]
*/ */
export interface TableOfContentsBelowTablet {} // tslint:disable-line export interface TableOfContentsBelowTablet {} // tslint:disable-line
/** /**
* Table of contents above tablet breakpoint * Table of contents for [tablet +]
*/ */
export interface TableOfContentsAboveTablet { export interface TableOfContentsAboveTablet {
sidebar: Sidebar /* Sidebar */ sidebar: Sidebar /* Sidebar */
@ -101,7 +101,7 @@ export function mountTableOfContents(
.pipe( .pipe(
switchMap(tablet => { switchMap(tablet => {
/* Mount table of contents above tablet breakpoint */ /* [tablet +]: Mount table of contents in sidebar */
if (tablet) { if (tablet) {
const els = getElements<HTMLAnchorElement>(".md-nav__link", el) const els = getElements<HTMLAnchorElement>(".md-nav__link", el)
@ -123,7 +123,7 @@ export function mountTableOfContents(
map(([sidebar, anchors]) => ({ sidebar, anchors })) map(([sidebar, anchors]) => ({ sidebar, anchors }))
) )
/* Mount table of contents below tablet breakpoint */ /* [tablet -]: Unmount table of contents */
} else { } else {
return of({}) return of({})
} }

View File

@ -102,7 +102,7 @@ export class SearchIndex {
* *
* A mapping of URLs (including hash fragments) to the actual articles and * A mapping of URLs (including hash fragments) to the actual articles and
* sections of the documentation. The search document mapping must be created * sections of the documentation. The search document mapping must be created
* regardless of whether the index was prebuilt or not, as lunr itself will * regardless of whether the index was prebuilt or not, as `lunr` itself will
* only store the actual index. * only store the actual index.
*/ */
protected documents: SearchDocumentMap protected documents: SearchDocumentMap
@ -113,7 +113,7 @@ export class SearchIndex {
protected highlight: SearchHighlightFactoryFn protected highlight: SearchHighlightFactoryFn
/** /**
* The lunr search index * The `lunr` search index
*/ */
protected index: lunr.Index protected index: lunr.Index

View File

@ -20,12 +20,14 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
import { Observable, combineLatest, fromEvent } from "rxjs" import { Observable, combineLatest, fromEvent, merge } from "rxjs"
import { import {
delay,
distinctUntilChanged, distinctUntilChanged,
map, map,
shareReplay, shareReplay,
startWith startWith,
tap
} from "rxjs/operators" } from "rxjs/operators"
import { watchElementFocus } from "../../agent" import { watchElementFocus } from "../../agent"
@ -61,7 +63,7 @@ interface WatchOptions {
* Default transformation function * Default transformation function
* *
* Rogue control characters are filtered before handing the query to the * Rogue control characters are filtered before handing the query to the
* search index, as lunr will throw otherwise. * search index, as `lunr` will throw otherwise.
* *
* @param value - Query value * @param value - Query value
* *
@ -81,6 +83,9 @@ function defaultTransform(value: string): string {
/** /**
* Watch search query * Watch search query
* *
* Note that the focus event which triggers re-reading the current query value
* is delayed by `1ms` so the input's empty state is allowed to propagate.
*
* @param el - Search query element * @param el - Search query element
* @param options - Options * @param options - Options
* *
@ -91,7 +96,10 @@ export function watchSearchQuery(
): Observable<SearchQuery> { ): Observable<SearchQuery> {
/* Intercept keyboard events */ /* Intercept keyboard events */
const value$ = fromEvent(el, "keyup") const value$ = merge(
fromEvent(el, "keyup"),
fromEvent(el, "focus").pipe(delay(1))
)
.pipe( .pipe(
map(() => transform(el.value)), map(() => transform(el.value)),
startWith(transform(el.value)), startWith(transform(el.value)),

View File

@ -57,7 +57,7 @@ import { SearchQuery } from "../query"
*/ */
interface PaintOptions { interface PaintOptions {
query$: Observable<SearchQuery> /* Search query observable */ query$: Observable<SearchQuery> /* Search query observable */
fetch$: Observable<boolean> /* Search trigger observable */ fetch$: Observable<boolean> /* Result fetch observable */
} }
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
@ -67,6 +67,10 @@ interface PaintOptions {
/** /**
* Paint search results from source observable * Paint search results from source observable
* *
* This function will perform a lazy rendering of the search results, depending
* on the vertical offset of the search result container. When the scroll offset
* reaches the bottom of the element, more results are fetched and rendered.
*
* @param el - Search result element * @param el - Search result element
* @param options - Options * @param options - Options
* *

View File

@ -50,6 +50,9 @@ interface MountOptions {
/** /**
* Patch all `details` elements * Patch all `details` elements
* *
* This function will ensure that all `details` tags are opened prior to
* printing, so the whole content of the page is included.
*
* @param options - Options * @param options - Options
* *
* @return Details elements observable * @return Details elements observable

View File

@ -44,6 +44,9 @@ interface MountOptions {
/** /**
* Patch all `table` elements * Patch all `table` elements
* *
* This function will re-render all tables by wrapping them to improve overflow
* scrolling on smaller screen sizes.
*
* @param options - Options * @param options - Options
* *
* @return Table elements observable * @return Table elements observable

View File

@ -38,7 +38,7 @@ const css = {
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/** /**
* Render clipboard * Render a 'copy-to-clipboard' button
* *
* @param id - Unique identifier * @param id - Unique identifier
* *

View File

@ -39,7 +39,7 @@ const css = {
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/** /**
* Render a table wrapper * Render a table inside a wrapper to improve scrolling on mobile
* *
* @param table - Table element * @param table - Table element
* *

View File

@ -28,7 +28,7 @@ import { map } from "rxjs/operators"
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/** /**
* Invert boolean value of source observable * Invert the value of a toggle observable
* *
* @param toggle$ - Toggle observable * @param toggle$ - Toggle observable
* *

View File

@ -59,6 +59,11 @@ export function translate(key: string, value?: string): string {
/** /**
* Truncate a string after the given number of characters * Truncate a string after the given number of characters
* *
* This is not a very reasonable approach, since the summaries kind of suck.
* It would be better to create something more intelligent, highlighting the
* search occurrences and making a better summary out of it, but this note was
* written three years ago, so who knows if we'll ever fix it.
*
* @param value - Value to be truncated * @param value - Value to be truncated
* @param n - Number of characters * @param n - Number of characters
* *

View File

@ -33,6 +33,13 @@ import { PackerMessage } from "../message"
/** /**
* Setup packer web worker * Setup packer web worker
* *
* This function will create a web worker that helps in packing and unpacking
* strings using an LZ-based algorithm, namely `lz-string`. Its main purpose is
* to compress the search index before storing it in local storage, so it can
* be retrieved and imported to minimize the time necessary to setup search.
*
* @see https://bit.ly/2Q1ArhU - LZ-String documentation
*
* @param url - Worker url * @param url - Worker url
* *
* @return Worker handler * @return Worker handler

View File

@ -113,7 +113,7 @@ export function setupSearchWorker(
pluck("response") pluck("response")
) )
/* Send index to search worker */ /* Send index to worker */
index$ index$
.pipe<SearchSetupMessage>( .pipe<SearchSetupMessage>(
map(data => ({ map(data => ({

View File

@ -40,6 +40,9 @@ let index: SearchIndex
/** /**
* Setup multi-language support through `lunr-languages` * Setup multi-language support through `lunr-languages`
* *
* This function will automatically import the stemmers necessary to process
* the languages which were given through the search index configuration.
*
* @param config - Search index configuration * @param config - Search index configuration
*/ */
function setupLunrLanguages(config: SearchIndexConfig): void { function setupLunrLanguages(config: SearchIndexConfig): void {
@ -58,7 +61,7 @@ function setupLunrLanguages(config: SearchIndexConfig): void {
/* Load scripts synchronously */ /* Load scripts synchronously */
if (scripts.length) if (scripts.length)
importScripts( self.importScripts(
`${base}/min/lunr.stemmer.support.min.js`, `${base}/min/lunr.stemmer.support.min.js`,
...scripts ...scripts
) )

View File

@ -77,14 +77,7 @@ body {
// Lock body to viewport height (e.g. in search mode) // Lock body to viewport height (e.g. in search mode)
&[data-md-state="lock"] { &[data-md-state="lock"] {
height: 100%; position: fixed;
min-height: auto;
overflow: hidden;
// Hide container on iOS, or the body will not be locked correctly
.ios & .md-container {
display: none;
}
} }
} }
} }

View File

@ -5,7 +5,6 @@
"declaration": false, "declaration": false,
"declarationMap": false, "declarationMap": false,
"downlevelIteration": true, "downlevelIteration": true,
"importHelpers": true,
"jsx": "react", "jsx": "react",
"jsxFactory": "h", "jsxFactory": "h",
"lib": [ "lib": [

View File

@ -61,6 +61,7 @@ function config(args: Configuration): Configuration {
experimentalWatchApi: true, experimentalWatchApi: true,
transpileOnly: true, transpileOnly: true,
compilerOptions: { compilerOptions: {
importHelpers: true,
module: "esnext", module: "esnext",
removeComments: false removeComments: false
} }