Formatting + moved search index fetching to top level

This commit is contained in:
squidfunk
2021-02-24 18:02:09 +01:00
parent cb723d4bef
commit d6317dc514
69 changed files with 404 additions and 328 deletions

View File

@@ -61,6 +61,32 @@ export type Component<
ref: U /* Component reference */
}
/* ----------------------------------------------------------------------------
* Helper types
* ------------------------------------------------------------------------- */
/**
* Component type map
*/
interface ComponentTypeMap {
"announce": HTMLElement /* Announcement bar */
"container": HTMLElement /* Container */
"content": HTMLElement /* Content */
"dialog": HTMLElement /* Dialog */
"header": HTMLElement /* Header */
"header-title": HTMLElement /* Header title */
"header-topic": HTMLElement /* Header topic */
"main": HTMLElement /* Main area */
"search": HTMLElement /* Search */
"search-query": HTMLInputElement /* Search input */
"search-result": HTMLElement /* Search results */
"sidebar": HTMLElement /* Sidebar */
"skip": HTMLAnchorElement /* Skip link */
"source": HTMLAnchorElement /* Repository information */
"tabs": HTMLElement /* Navigation tabs */
"toc": HTMLElement /* Table of contents */
}
/* ----------------------------------------------------------------------------
* Functions
* ------------------------------------------------------------------------- */
@@ -68,31 +94,31 @@ export type Component<
/**
* Retrieve the element for a given component or throw a reference error
*
* @template T - Element type
* @template T - Component type
*
* @param type - Component type
* @param node - Node of reference
*
* @returns Element
*/
export function getComponentElement<T extends HTMLElement>(
type: ComponentType, node: ParentNode = document
): T {
export function getComponentElement<T extends ComponentType>(
type: T, node: ParentNode = document
): ComponentTypeMap[T] {
return getElementOrThrow(`[data-md-component=${type}]`, node)
}
/**
* Retrieve all elements for a given component
*
* @template T - Element type
* @template T - Component type
*
* @param type - Component type
* @param node - Node of reference
*
* @returns Elements
*/
export function getComponentElements<T extends HTMLElement>(
type: ComponentType, node: ParentNode = document
): T[] {
export function getComponentElements<T extends ComponentType>(
type: T, node: ParentNode = document
): ComponentTypeMap[T][] {
return getElements(`[data-md-component=${type}]`, node)
}

View File

@@ -95,8 +95,8 @@ let index = 0
/**
* Watch code block
*
* This function will monitor size changes of the viewport, as well as switches
* of content tabs with embedded code blocks, as both may trigger overflow.
* This function monitors size changes of the viewport, as well as switches of
* content tabs with embedded code blocks, as both may trigger overflow.
*
* @param el - Code block element
* @param options - Options
@@ -163,7 +163,7 @@ export function mountCodeBlock(
resetFocusable(el)
})
/* Inject button for Clipboard.js integration */
/* Render button for Clipboard.js integration */
if (ClipboardJS.isSupported()) {
const parent = el.closest("pre")!
parent.id = `__code_${index++}`

View File

@@ -52,8 +52,8 @@ const sentinel = createElement("table")
/**
* Mount data table
*
* This function wraps a data table in another scrollable container, so they
* can be scrolled on smaller screen sizes and won't break the layout.
* This function wraps a data table in another scrollable container, so it can
* be smoothly scrolled on smaller screen sizes and won't break the layout.
*
* @param el - Data table element
*

View File

@@ -105,8 +105,8 @@ export function watchDialog(
/**
* Mount dialog
*
* This function makes the dialog in the right corner appear when a new alert
* is emitted through the subject that is passed as part of the options.
* This function reveals the dialog in the right cornerwhen a new alert is
* emitted through the subject that is passed as part of the options.
*
* @param el - Dialog element
* @param options - Options

View File

@@ -28,7 +28,6 @@ import {
Keyboard,
getActiveElement,
getElements,
requestJSON,
setElementFocus,
setElementSelection,
setToggle
@@ -63,24 +62,10 @@ export type Search =
* Mount options
*/
interface MountOptions {
index$: ObservableInput<SearchIndex> /* Search index observable */
keyboard$: Observable<Keyboard> /* Keyboard observable */
}
/* ----------------------------------------------------------------------------
* Helper functions
* ------------------------------------------------------------------------- */
/**
* Fetch search index
*
* @param url - Search index URL
*
* @returns Promise or observable
*/
function fetchSearchIndex(url: string): ObservableInput<SearchIndex> {
return __search?.index || requestJSON<SearchIndex>(url)
}
/* ----------------------------------------------------------------------------
* Functions
* ------------------------------------------------------------------------- */
@@ -97,16 +82,14 @@ function fetchSearchIndex(url: string): ObservableInput<SearchIndex> {
* @returns Search component observable
*/
export function mountSearch(
el: HTMLElement, { keyboard$ }: MountOptions
el: HTMLElement, { index$, keyboard$ }: MountOptions
): Observable<Component<Search>> {
if (location.protocol === "file:")
return NEVER
/* Set up search worker */
const config = configuration()
const worker = setupSearchWorker(config.search, fetchSearchIndex(
`${config.base}/search/search_index.json`
))
const worker = setupSearchWorker(config.search, index$)
/* Retrieve nested components */
const query = getComponentElement("search-query", el)
@@ -193,7 +176,7 @@ export function mountSearch(
})
/* Create and return component */
const query$ = mountSearchQuery(query as HTMLInputElement, worker)
const query$ = mountSearchQuery(query, worker)
return merge(
query$,
mountSearchResult(result, worker, { query$ })

View File

@@ -33,7 +33,6 @@ import {
distinctUntilKeyChanged,
finalize,
map,
startWith,
takeLast,
takeUntil,
tap
@@ -96,7 +95,6 @@ export function watchSearchQuery(
)
.pipe(
map(() => fn(el.value)),
startWith(fn(el.value)),
distinctUntilChanged()
)

View File

@@ -89,8 +89,8 @@ interface MountOptions {
/**
* Mount search result list
*
* This function will perform a lazy rendering of the search results, depending
* on the vertical offset of the search result container.
* This function performs a lazy rendering of the search results, depending on
* the vertical offset of the search result container.
*
* @param el - Search result list element
* @param worker - Search worker

View File

@@ -32,7 +32,7 @@ import {
import { setSourceFacts, setSourceState } from "~/actions"
import { renderSourceFacts } from "~/templates"
import { hash } from "~/utilities"
import { digest } from "~/utilities"
import { Component } from "../../_"
import { SourceFacts, fetchSourceFacts } from "../facts"
@@ -53,7 +53,7 @@ export interface Source {
* ------------------------------------------------------------------------- */
/**
* Repository facts observable
* Repository information observable
*/
let fetch$: Observable<Source>
@@ -64,8 +64,8 @@ let fetch$: Observable<Source>
/**
* Watch repository information
*
* This function will try to read the repository facts from session storage,
* and if unsuccessful, fetch them from the underlying provider.
* This function tries to read the repository facts from session storage, and
* if unsuccessful, fetches them from the underlying provider.
*
* @param el - Repository information element
*
@@ -74,18 +74,15 @@ let fetch$: Observable<Source>
export function watchSource(
el: HTMLAnchorElement
): Observable<Source> {
const digest = hash(el.href).toString()
/* Fetch repository facts once */
return fetch$ ||= defer(() => {
const data = sessionStorage.getItem(digest)
const data = sessionStorage.getItem(digest("__repo"))
if (data) {
return of(JSON.parse(data))
return of<SourceFacts>(JSON.parse(data))
} else {
const value$ = fetchSourceFacts(el.href)
value$.subscribe(value => {
try {
sessionStorage.setItem(digest, JSON.stringify(value))
sessionStorage.setItem(digest("__repo"), JSON.stringify(value))
} catch (err) {
/* Uncritical, just swallow */
}