mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Implemented instant loading
This commit is contained in:
parent
3aa251fb03
commit
ae1ed3d924
24
material/assets/javascripts/bundle.1defb77e.min.js
vendored
Normal file
24
material/assets/javascripts/bundle.1defb77e.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
material/assets/javascripts/bundle.1defb77e.min.js.map
Normal file
1
material/assets/javascripts/bundle.1defb77e.min.js.map
Normal file
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
@ -1,6 +1,6 @@
|
||||
{
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.4cda9c77.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.4cda9c77.min.js.map",
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.1defb77e.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.1defb77e.min.js.map",
|
||||
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.926ffd9e.min.js",
|
||||
"assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.926ffd9e.min.js.map",
|
||||
"assets/stylesheets/app-palette.scss": "assets/stylesheets/app-palette.3f90c815.min.css",
|
||||
|
@ -190,7 +190,7 @@
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% block scripts %}
|
||||
<script src="{{ 'assets/javascripts/bundle.4cda9c77.min.js' | url }}"></script>
|
||||
<script src="{{ 'assets/javascripts/bundle.1defb77e.min.js' | url }}"></script>
|
||||
<script id="__lang" type="application/json">
|
||||
{%- set translations = {} -%}
|
||||
{%- for key in [
|
||||
@ -209,7 +209,17 @@
|
||||
{%- endfor -%}
|
||||
{{ translations | tojson }}
|
||||
</script>
|
||||
<script>app=initialize({base:"{{ base_url }}",worker:{search:"{{ 'assets/javascripts/worker/search.926ffd9e.min.js' | url }}"}})</script>
|
||||
<script>
|
||||
app = initialize({
|
||||
base: "{{ base_url }}",
|
||||
worker: {
|
||||
search: "{{ 'assets/javascripts/worker/search.926ffd9e.min.js' | url }}"
|
||||
},
|
||||
feature: {
|
||||
instant: {{ feature.instant | tojson }}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% for path in config["extra_javascript"] %}
|
||||
<script src="{{ path | url }}"></script>
|
||||
{% endfor %}
|
||||
|
@ -32,6 +32,10 @@ feature:
|
||||
# of tabs, especially useful for larger documentation projects
|
||||
tabs: false
|
||||
|
||||
# Instant loading will instruct the application to intercept all internal
|
||||
# links, load and inject the HTML into the page and rebind all handlers
|
||||
instant: false
|
||||
|
||||
# Sets the primary and accent color palettes as defined in the Material Design
|
||||
# documentation - possible values can be looked up in the getting started guide
|
||||
palette:
|
||||
|
@ -22,4 +22,4 @@
|
||||
mkdocs>=1.0
|
||||
Pygments>=2.4
|
||||
markdown>=3.2
|
||||
pymdown-extensions>=7.0b1
|
||||
pymdown-extensions>=7.0b2
|
||||
|
@ -22,7 +22,14 @@
|
||||
|
||||
import { keys } from "ramda"
|
||||
import { NEVER, Observable, of } from "rxjs"
|
||||
import { map, scan, shareReplay, switchMap } from "rxjs/operators"
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
scan,
|
||||
shareReplay,
|
||||
switchMap,
|
||||
tap
|
||||
} from "rxjs/operators"
|
||||
|
||||
import { getElement } from "observables"
|
||||
|
||||
@ -92,7 +99,7 @@ let components$: Observable<ComponentMap>
|
||||
export function watchComponentMap(
|
||||
names: Component[], { document$ }: WatchOptions
|
||||
): Observable<ComponentMap> {
|
||||
components$ = document$
|
||||
return components$ = document$
|
||||
.pipe(
|
||||
|
||||
/* Build component map */
|
||||
@ -124,12 +131,9 @@ export function watchComponentMap(
|
||||
}
|
||||
}
|
||||
return prev
|
||||
})
|
||||
)
|
||||
}),
|
||||
|
||||
/* Return component map as hot observable */
|
||||
return components$
|
||||
.pipe(
|
||||
/* Convert to hot observable */
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
@ -152,6 +156,7 @@ export function useComponent<T extends HTMLElement>(
|
||||
typeof components[name] !== "undefined"
|
||||
? of(components[name] as T)
|
||||
: NEVER
|
||||
))
|
||||
)),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, pipe } from "rxjs"
|
||||
import { shareReplay, switchMap } from "rxjs/operators"
|
||||
import { switchMap } from "rxjs/operators"
|
||||
|
||||
import { Header, Viewport, watchHeader } from "observables"
|
||||
|
||||
@ -51,7 +51,6 @@ export function mountHeader(
|
||||
{ viewport$ }: MountOptions
|
||||
): OperatorFunction<HTMLElement, Header> {
|
||||
return pipe(
|
||||
switchMap(el => watchHeader(el, { viewport$ })),
|
||||
shareReplay(1)
|
||||
switchMap(el => watchHeader(el, { viewport$ }))
|
||||
)
|
||||
}
|
||||
|
@ -21,12 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, pipe } from "rxjs"
|
||||
import {
|
||||
filter,
|
||||
map,
|
||||
shareReplay,
|
||||
switchMap
|
||||
} from "rxjs/operators"
|
||||
import { filter, map, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
Header,
|
||||
@ -74,8 +69,7 @@ export function mountHeaderTitle(
|
||||
map(({ offset: { y } }) => y >= hx.offsetHeight),
|
||||
paintHeaderTitle(el)
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, pipe } from "rxjs"
|
||||
import { map, shareReplay, switchMap } from "rxjs/operators"
|
||||
import { map, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
Header,
|
||||
@ -73,7 +73,6 @@ export function mountHero(
|
||||
paintHideable(el, 20),
|
||||
map(hidden => ({ hidden }))
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -21,11 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, pipe } from "rxjs"
|
||||
import {
|
||||
distinctUntilKeyChanged,
|
||||
shareReplay,
|
||||
switchMap
|
||||
} from "rxjs/operators"
|
||||
import { distinctUntilKeyChanged, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
Header,
|
||||
@ -81,7 +77,6 @@ export function mountMain(
|
||||
return main$
|
||||
})
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, pipe } from "rxjs"
|
||||
import { map, shareReplay, switchMap } from "rxjs/operators"
|
||||
import { map, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
Header,
|
||||
@ -115,7 +115,6 @@ export function mountNavigation(
|
||||
}
|
||||
})
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, combineLatest, pipe } from "rxjs"
|
||||
import { map, shareReplay, switchMap } from "rxjs/operators"
|
||||
import { map, switchMap } from "rxjs/operators"
|
||||
|
||||
import { SearchResult } from "integrations/search"
|
||||
import { SearchQuery } from "observables"
|
||||
@ -68,8 +68,7 @@ export function mountSearch(
|
||||
return pipe(
|
||||
switchMap(() => combineLatest([query$, result$, reset$])
|
||||
.pipe(
|
||||
map(([query, result]) => ({ query, result })),
|
||||
shareReplay(1)
|
||||
map(([query, result]) => ({ query, result }))
|
||||
))
|
||||
)
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import {
|
||||
filter,
|
||||
map,
|
||||
pluck,
|
||||
shareReplay,
|
||||
switchMap
|
||||
} from "rxjs/operators"
|
||||
|
||||
@ -90,7 +89,6 @@ export function mountSearchResult(
|
||||
pluck("data"),
|
||||
paintSearchResult(el, { query$, fetch$ })
|
||||
)
|
||||
}),
|
||||
shareReplay(1)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, OperatorFunction, of, pipe } from "rxjs"
|
||||
import { map, shareReplay, switchMap } from "rxjs/operators"
|
||||
import { map, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
Header,
|
||||
@ -87,7 +87,6 @@ export function mountTabs(
|
||||
}
|
||||
})
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
of,
|
||||
pipe
|
||||
} from "rxjs"
|
||||
import { map, shareReplay, switchMap } from "rxjs/operators"
|
||||
import { map, switchMap } from "rxjs/operators"
|
||||
|
||||
import {
|
||||
AnchorList,
|
||||
@ -129,7 +129,6 @@ export function mountTableOfContents(
|
||||
}
|
||||
})
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -30,7 +30,10 @@ import { values } from "ramda"
|
||||
import {
|
||||
merge,
|
||||
combineLatest,
|
||||
animationFrameScheduler
|
||||
animationFrameScheduler,
|
||||
fromEvent,
|
||||
of,
|
||||
NEVER
|
||||
} from "rxjs"
|
||||
import {
|
||||
delay,
|
||||
@ -41,7 +44,8 @@ import {
|
||||
observeOn,
|
||||
take,
|
||||
mapTo,
|
||||
shareReplay
|
||||
shareReplay,
|
||||
switchMapTo
|
||||
} from "rxjs/operators"
|
||||
|
||||
import {
|
||||
@ -55,7 +59,8 @@ import {
|
||||
watchViewport,
|
||||
watchToggleMap,
|
||||
useToggle,
|
||||
getElement
|
||||
getElement,
|
||||
watchDocumentSwitch
|
||||
} from "./observables"
|
||||
import { setupSearchWorker } from "./workers"
|
||||
|
||||
@ -108,9 +113,15 @@ export function initialize(config: unknown) {
|
||||
if (!isConfig(config))
|
||||
throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)
|
||||
|
||||
// pass config here!?
|
||||
const document$ = watchDocument()
|
||||
const location$ = watchLocation()
|
||||
|
||||
// instant loading
|
||||
const switch$ = config.feature.instant
|
||||
? watchDocumentSwitch({ location$ })
|
||||
: NEVER
|
||||
|
||||
const load$ = watchDocument()
|
||||
const document$ = merge(load$, switch$)
|
||||
const hash$ = watchLocationHash()
|
||||
const viewport$ = watchViewport()
|
||||
const tablet$ = watchMedia("(min-width: 960px)")
|
||||
@ -147,12 +158,14 @@ export function initialize(config: unknown) {
|
||||
/* Create header observable */
|
||||
const header$ = useComponent("header")
|
||||
.pipe(
|
||||
mountHeader({ viewport$ })
|
||||
mountHeader({ viewport$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
const main$ = useComponent("main")
|
||||
.pipe(
|
||||
mountMain({ header$, viewport$ })
|
||||
mountMain({ header$, viewport$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@ -167,47 +180,55 @@ export function initialize(config: unknown) {
|
||||
/* Mount search reset */
|
||||
const reset$ = useComponent("search-reset")
|
||||
.pipe(
|
||||
mountSearchReset()
|
||||
mountSearchReset(),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* Mount search result */
|
||||
const result$ = useComponent("search-result")
|
||||
.pipe(
|
||||
mountSearchResult(worker, { query$ })
|
||||
mountSearchResult(worker, { query$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
const search$ = useComponent("search")
|
||||
.pipe(
|
||||
mountSearch({ query$, reset$, result$ })
|
||||
mountSearch({ query$, reset$, result$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
const navigation$ = useComponent("navigation")
|
||||
.pipe(
|
||||
mountNavigation({ header$, main$, viewport$, screen$ })
|
||||
mountNavigation({ header$, main$, viewport$, screen$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
const toc$ = useComponent("toc")
|
||||
.pipe(
|
||||
mountTableOfContents({ header$, main$, viewport$, tablet$ })
|
||||
mountTableOfContents({ header$, main$, viewport$, tablet$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
const tabs$ = useComponent("tabs")
|
||||
.pipe(
|
||||
mountTabs({ header$, viewport$, screen$ })
|
||||
mountTabs({ header$, viewport$, screen$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
const hero$ = useComponent("hero")
|
||||
.pipe(
|
||||
mountHero({ header$, viewport$ })
|
||||
mountHero({ header$, viewport$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
const title$ = useComponent("header-title")
|
||||
.pipe(
|
||||
mountHeaderTitle({ header$, viewport$ })
|
||||
mountHeaderTitle({ header$, viewport$ }),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
@ -278,6 +299,50 @@ export function initialize(config: unknown) {
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
// instant loading
|
||||
const instant$ = config.feature.instant ? load$ // TODO: just use document$ and take(1)
|
||||
.pipe(
|
||||
switchMap(({ body }) => fromEvent(body, "click")),
|
||||
switchMap(ev => {
|
||||
|
||||
// two cases: search results which should always load from same domain
|
||||
// and/or
|
||||
if (ev.target && ev.target instanceof HTMLElement) {
|
||||
const anchor = ev.target.closest("a")
|
||||
if (anchor) {
|
||||
if (/(:\/\/|^#)/.test(anchor.getAttribute("href")!) === false) {
|
||||
ev.preventDefault()
|
||||
|
||||
// we must copy the value, or weird stuff will happen
|
||||
const href = anchor.href
|
||||
history.pushState(true, "", href)
|
||||
return of(href)
|
||||
}
|
||||
}
|
||||
}
|
||||
return NEVER
|
||||
}),
|
||||
shareReplay(1)
|
||||
)
|
||||
: NEVER
|
||||
|
||||
// deploy new location
|
||||
instant$.subscribe(url => {
|
||||
console.log(`Load ${url}`)
|
||||
location$.next(url)
|
||||
})
|
||||
|
||||
// scroll to top when document is loaded
|
||||
instant$
|
||||
.pipe(
|
||||
switchMapTo(switch$), // TODO: just use document$ and skip(1)
|
||||
)
|
||||
.subscribe(() => {
|
||||
window.scrollTo(0, 0) // TODO: or scroll element into view
|
||||
})
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
// if we use a single tab outside of search, unhide all permalinks.
|
||||
// TODO: experimental. necessary!?
|
||||
keyboard$
|
||||
|
@ -26,7 +26,7 @@ import {
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
pluck,
|
||||
shareReplay,
|
||||
share,
|
||||
skip,
|
||||
startWith,
|
||||
switchMap
|
||||
@ -67,7 +67,7 @@ export function watchDocumentSwitch(
|
||||
return location$
|
||||
.pipe(
|
||||
startWith(getLocation()),
|
||||
map(url => url.replace(/#[^#]+$/, "")),
|
||||
map(url => url.replace(/#[^#]*$/, "")),
|
||||
distinctUntilChanged(),
|
||||
skip(1),
|
||||
|
||||
@ -81,6 +81,6 @@ export function watchDocumentSwitch(
|
||||
pluck("response")
|
||||
)
|
||||
),
|
||||
shareReplay(1)
|
||||
share()
|
||||
)
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ import {
|
||||
map,
|
||||
observeOn,
|
||||
scan,
|
||||
shareReplay,
|
||||
switchMap,
|
||||
tap
|
||||
} from "rxjs/operators"
|
||||
@ -184,8 +183,8 @@ export function watchAnchorList(
|
||||
)
|
||||
)
|
||||
|
||||
/* Compute anchor list migrations */
|
||||
const migration$ = partition$
|
||||
/* Compute and return anchor list migrations */
|
||||
return partition$
|
||||
.pipe(
|
||||
map(([prev, next]) => ({
|
||||
prev: prev.map(([path]) => path),
|
||||
@ -202,12 +201,6 @@ export function watchAnchorList(
|
||||
}
|
||||
}, { prev: [], next: [] })
|
||||
)
|
||||
|
||||
/* Return anchor list migrations as hot observable */
|
||||
return migration$
|
||||
.pipe(
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -21,12 +21,7 @@
|
||||
*/
|
||||
|
||||
import { Observable, combineLatest } from "rxjs"
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
pluck,
|
||||
shareReplay
|
||||
} from "rxjs/operators"
|
||||
import { distinctUntilChanged, map, pluck } from "rxjs/operators"
|
||||
|
||||
import { Viewport } from "../../agent"
|
||||
import { Header } from "../../header"
|
||||
@ -103,14 +98,13 @@ export function watchMain(
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Combine into a single hot observable */
|
||||
/* Combine into a single observable */
|
||||
return combineLatest([adjust$, height$, active$])
|
||||
.pipe(
|
||||
map(([adjust, height, active]) => ({
|
||||
offset: el.offsetTop - adjust,
|
||||
height,
|
||||
active
|
||||
})),
|
||||
shareReplay(1)
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ import {
|
||||
finalize,
|
||||
map,
|
||||
observeOn,
|
||||
shareReplay,
|
||||
tap,
|
||||
withLatestFrom
|
||||
} from "rxjs/operators"
|
||||
@ -136,11 +135,10 @@ export function watchSidebar(
|
||||
distinctUntilChanged()
|
||||
)
|
||||
|
||||
/* Combine into single hot observable */
|
||||
/* Combine into single observable */
|
||||
return combineLatest([height$, lock$])
|
||||
.pipe(
|
||||
map(([height, lock]) => ({ height, lock })),
|
||||
shareReplay(1)
|
||||
map(([height, lock]) => ({ height, lock }))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@ import {
|
||||
map,
|
||||
observeOn,
|
||||
scan,
|
||||
shareReplay,
|
||||
tap
|
||||
} from "rxjs/operators"
|
||||
|
||||
@ -99,12 +98,11 @@ export function watchNavigationLayer(
|
||||
)))
|
||||
)
|
||||
|
||||
/* Return previous and next layer as hot observable */
|
||||
/* Return previous and next layer */
|
||||
return layer$
|
||||
.pipe(
|
||||
map(next => ({ next })),
|
||||
scan(({ next: prev }, { next }) => ({ prev, next })),
|
||||
shareReplay(1)
|
||||
scan(({ next: prev }, { next }) => ({ prev, next }))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@ import {
|
||||
delay,
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
shareReplay,
|
||||
startWith
|
||||
} from "rxjs/operators"
|
||||
|
||||
@ -109,10 +108,9 @@ export function watchSearchQuery(
|
||||
/* Intercept focus events */
|
||||
const focus$ = watchElementFocus(el)
|
||||
|
||||
/* Combine into a single hot observable */
|
||||
/* Combine into a single observable */
|
||||
return combineLatest([value$, focus$])
|
||||
.pipe(
|
||||
map(([value, focus]) => ({ value, focus })),
|
||||
shareReplay(1)
|
||||
map(([value, focus]) => ({ value, focus }))
|
||||
)
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
import { NEVER, Observable, fromEvent, of } from "rxjs"
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
map,
|
||||
shareReplay,
|
||||
startWith,
|
||||
@ -84,7 +85,7 @@ let toggles$: Observable<ToggleMap>
|
||||
export function watchToggleMap(
|
||||
names: Toggle[], { document$ }: WatchOptions
|
||||
): Observable<ToggleMap> {
|
||||
toggles$ = document$
|
||||
return toggles$ = document$
|
||||
.pipe(
|
||||
|
||||
/* Ignore document switches */
|
||||
@ -97,12 +98,9 @@ export function watchToggleMap(
|
||||
...toggles,
|
||||
...typeof el !== "undefined" ? { [name]: el } : {}
|
||||
}
|
||||
}, {}))
|
||||
)
|
||||
}, {})),
|
||||
|
||||
/* Return toggle map as hot observable */
|
||||
return toggles$
|
||||
.pipe(
|
||||
/* Convert to hot observable */
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
@ -125,7 +123,8 @@ export function useToggle(
|
||||
typeof toggles[name] !== "undefined"
|
||||
? of(toggles[name]!)
|
||||
: NEVER
|
||||
))
|
||||
)),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ export function patchDetails(
|
||||
/* Open parent details and fix anchor jump */
|
||||
hash$
|
||||
.pipe(
|
||||
map(hash => getElement(hash)!),
|
||||
map(id => getElement(`[id="${id}"]`)!),
|
||||
filter(el => typeof el !== "undefined"),
|
||||
tap(el => {
|
||||
const details = el.closest("details")
|
||||
|
@ -32,6 +32,9 @@ export interface Config {
|
||||
worker: {
|
||||
search: string /* Search worker URL */
|
||||
}
|
||||
feature: {
|
||||
instant: true /* Instant loading */
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
@ -56,14 +56,18 @@ interface SetupOptions {
|
||||
|
||||
/**
|
||||
* Resolve URL
|
||||
* * TODO: document what's going on here + cache results
|
||||
*
|
||||
* @param base - Base URL
|
||||
* @param origin - Base URL
|
||||
* @param paths - Further URL paths
|
||||
*
|
||||
* @return Absolute URL
|
||||
* @return Relative URL
|
||||
*/
|
||||
function resolve(base: URL | string, ...paths: string[]) {
|
||||
return [base, ...paths].join("")
|
||||
function resolve(origin: URL, ...paths: string[]) {
|
||||
const path = location.pathname
|
||||
.replace(origin.pathname, "")
|
||||
.replace(/[^\/]+/g, "..")
|
||||
return [path, ...paths].join("")
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
@ -87,7 +91,7 @@ export function setupSearchWorker(
|
||||
url: string, { base, index }: SetupOptions
|
||||
): WorkerHandler<SearchMessage> {
|
||||
const worker = new Worker(url)
|
||||
const prefix = new URL(base, getLocation())
|
||||
const origin = new URL(base, getLocation())
|
||||
|
||||
/* Create communication channels and resolve relative links */
|
||||
const tx$ = new Subject<SearchMessage>()
|
||||
@ -96,9 +100,9 @@ export function setupSearchWorker(
|
||||
map(message => {
|
||||
if (isSearchResultMessage(message)) {
|
||||
for (const { article, sections } of message.data) {
|
||||
article.location = resolve(prefix, article.location)
|
||||
article.location = resolve(origin, article.location)
|
||||
for (const section of sections)
|
||||
section.location = resolve(prefix, section.location)
|
||||
section.location = resolve(origin, section.location)
|
||||
}
|
||||
}
|
||||
return message
|
||||
@ -109,7 +113,7 @@ export function setupSearchWorker(
|
||||
const index$ = typeof index !== "undefined"
|
||||
? from(index)
|
||||
: ajax({
|
||||
url: resolve(prefix, "search/search_index.json"),
|
||||
url: resolve(origin, "search/search_index.json"),
|
||||
responseType: "json",
|
||||
withCredentials: true
|
||||
})
|
||||
|
@ -400,6 +400,9 @@
|
||||
base: "{{ base_url }}",
|
||||
worker: {
|
||||
search: "{{ 'assets/javascripts/worker/search.js' | url }}"
|
||||
},
|
||||
feature: {
|
||||
instant: {{ feature.instant | tojson }}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -32,6 +32,10 @@ feature:
|
||||
# of tabs, especially useful for larger documentation projects
|
||||
tabs: false
|
||||
|
||||
# Instant loading will instruct the application to intercept all internal
|
||||
# links, load and inject the HTML into the page and rebind all handlers
|
||||
instant: false
|
||||
|
||||
# Sets the primary and accent color palettes as defined in the Material Design
|
||||
# documentation - possible values can be looked up in the getting started guide
|
||||
palette:
|
||||
|
Loading…
Reference in New Issue
Block a user