mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Refactored instant loading setup
This commit is contained in:
parent
9edf4e8068
commit
c7e4063d86
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
24
material/assets/javascripts/bundle.d3f83a35.min.js
vendored
Normal file
24
material/assets/javascripts/bundle.d3f83a35.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
material/assets/javascripts/bundle.d3f83a35.min.js.map
Normal file
1
material/assets/javascripts/bundle.d3f83a35.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
{
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.1defb77e.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.1defb77e.min.js.map",
|
||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.d3f83a35.min.js",
|
||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.d3f83a35.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.1defb77e.min.js' | url }}"></script>
|
||||
<script src="{{ 'assets/javascripts/bundle.d3f83a35.min.js' | url }}"></script>
|
||||
{%- set translations = {} -%}
|
||||
{%- for key in [
|
||||
"clipboard.copy",
|
||||
|
@ -27,8 +27,7 @@ import {
|
||||
map,
|
||||
scan,
|
||||
shareReplay,
|
||||
switchMap,
|
||||
tap
|
||||
switchMap
|
||||
} from "rxjs/operators"
|
||||
|
||||
import { getElement } from "observables"
|
||||
@ -86,20 +85,18 @@ let components$: Observable<ComponentMap>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch components with given names
|
||||
* Setup bindings to elements with given names
|
||||
*
|
||||
* This function returns an observable that will maintain bindings to the given
|
||||
* components in-between document switches and update the components in-place.
|
||||
* This function will maintain bindings to the elements identified by the given
|
||||
* names in-between document switches and update the elements in-place.
|
||||
*
|
||||
* @param names - Component names
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Component map observable
|
||||
*/
|
||||
export function watchComponentMap(
|
||||
export function setupComponents(
|
||||
names: Component[], { document$ }: WatchOptions
|
||||
): Observable<ComponentMap> {
|
||||
return components$ = document$
|
||||
): void {
|
||||
components$ = document$
|
||||
.pipe(
|
||||
|
||||
/* Build component map */
|
||||
@ -141,6 +138,9 @@ export function watchComponentMap(
|
||||
/**
|
||||
* Retrieve a component
|
||||
*
|
||||
* The returned observable will only re-emit if the element changed, i.e. if
|
||||
* it was replaced from a document which was switched to.
|
||||
*
|
||||
* @template T - Element type
|
||||
*
|
||||
* @param name - Component name
|
||||
|
@ -45,7 +45,8 @@ import {
|
||||
take,
|
||||
mapTo,
|
||||
shareReplay,
|
||||
switchMapTo
|
||||
switchMapTo,
|
||||
skip
|
||||
} from "rxjs/operators"
|
||||
|
||||
import {
|
||||
@ -57,10 +58,10 @@ import {
|
||||
watchLocation,
|
||||
watchLocationHash,
|
||||
watchViewport,
|
||||
watchToggleMap,
|
||||
setupToggles,
|
||||
useToggle,
|
||||
getElement,
|
||||
watchDocumentSwitch
|
||||
setViewportOffset
|
||||
} from "./observables"
|
||||
import { setupSearchWorker } from "./workers"
|
||||
|
||||
@ -74,7 +75,7 @@ import {
|
||||
mountTableOfContents,
|
||||
mountTabs,
|
||||
useComponent,
|
||||
watchComponentMap,
|
||||
setupComponents,
|
||||
mountHeaderTitle,
|
||||
mountSearchQuery,
|
||||
mountSearchReset,
|
||||
@ -114,14 +115,9 @@ export function initialize(config: unknown) {
|
||||
throw new SyntaxError(`Invalid configuration: ${JSON.stringify(config)}`)
|
||||
|
||||
const location$ = watchLocation()
|
||||
|
||||
// instant loading
|
||||
const switch$ = config.feature.instant
|
||||
? watchDocumentSwitch({ location$ })
|
||||
: NEVER
|
||||
|
||||
const load$ = watchDocument()
|
||||
const document$ = merge(load$, switch$)
|
||||
const document$ = watchDocument(
|
||||
config.feature.instant ? { location$ } : {}
|
||||
)
|
||||
const hash$ = watchLocationHash()
|
||||
const viewport$ = watchViewport()
|
||||
const tablet$ = watchMedia("(min-width: 960px)")
|
||||
@ -135,12 +131,14 @@ export function initialize(config: unknown) {
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
watchToggleMap([
|
||||
/* Setup toggle bindings */
|
||||
setupToggles([
|
||||
"drawer", /* Toggle for drawer */
|
||||
"search" /* Toggle for search */
|
||||
], { document$ })
|
||||
|
||||
watchComponentMap([
|
||||
/* Setup components bindings */
|
||||
setupComponents([
|
||||
"container", /* Container */
|
||||
"header", /* Header */
|
||||
"header-title", /* Header title */
|
||||
@ -155,6 +153,8 @@ export function initialize(config: unknown) {
|
||||
"toc" /* Table of contents */
|
||||
], { document$ })
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/* Create header observable */
|
||||
const header$ = useComponent("header")
|
||||
.pipe(
|
||||
@ -300,13 +300,11 @@ export function initialize(config: unknown) {
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
// instant loading
|
||||
const instant$ = config.feature.instant ? load$ // TODO: just use document$ and take(1)
|
||||
const instant$ = config.feature.instant ? document$ // TODO: just use document$ and take(1)
|
||||
.pipe(
|
||||
take(1), // only initial load
|
||||
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) {
|
||||
@ -326,19 +324,20 @@ export function initialize(config: unknown) {
|
||||
)
|
||||
: NEVER
|
||||
|
||||
// deploy new location
|
||||
// deploy new location - can be written as instant$.subscribe(location$)
|
||||
instant$.subscribe(url => {
|
||||
console.log(`Load ${url}`)
|
||||
location$.next(url)
|
||||
})
|
||||
|
||||
// scroll to top when document is loaded
|
||||
// if a new url is deployed via instant loading, switch to document observable
|
||||
// to exactly know when the content was loaded. then go to top.
|
||||
instant$
|
||||
.pipe(
|
||||
switchMapTo(switch$), // TODO: just use document$ and skip(1)
|
||||
switchMapTo(document$.pipe(skip(1))), // TODO: just use document$ and skip(1)
|
||||
)
|
||||
.subscribe(() => {
|
||||
window.scrollTo(0, 0) // TODO: or scroll element into view
|
||||
setViewportOffset({ y: 0 })
|
||||
})
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
@ -75,8 +75,11 @@ export function setupClipboard(
|
||||
const clipboard$ = fromEventPattern<ClipboardJS.Event>(next => {
|
||||
new ClipboardJS(".md-clipboard").on("success", next)
|
||||
})
|
||||
.pipe(
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* Display notification upon clipboard copy */
|
||||
/* Display notification for clipboard event */
|
||||
clipboard$
|
||||
.pipe(
|
||||
tap(ev => ev.clearSelection()),
|
||||
@ -84,9 +87,6 @@ export function setupClipboard(
|
||||
)
|
||||
.subscribe(dialog$)
|
||||
|
||||
/* Return clipboard as hot observable */
|
||||
/* Return clipboard */
|
||||
return clipboard$
|
||||
.pipe(
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ export function setupDialog(
|
||||
switchMap(text => useComponent("container")
|
||||
.pipe(
|
||||
map(container => container.appendChild(dialog)),
|
||||
observeOn(animationFrameScheduler),
|
||||
delay(1), // Strangley it doesnt work when we push things to the new animation frame...
|
||||
tap(el => {
|
||||
el.innerHTML = text
|
||||
|
@ -20,9 +20,22 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Observable, fromEvent } from "rxjs"
|
||||
import { NEVER, Observable, fromEvent, merge } from "rxjs"
|
||||
import { mapTo, shareReplay } from "rxjs/operators"
|
||||
|
||||
import { watchDocumentSwitch } from "../switch"
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Helper types
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch options
|
||||
*/
|
||||
interface WatchOptions {
|
||||
location$?: Observable<string> /* Location observable */
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
@ -30,12 +43,24 @@ import { mapTo, shareReplay } from "rxjs/operators"
|
||||
/**
|
||||
* Watch document
|
||||
*
|
||||
* If the location observable is passed, instant loading will be enabled which
|
||||
* means that new values will be emitted every time the location changes.
|
||||
*
|
||||
* @return Document observable
|
||||
*/
|
||||
export function watchDocument(): Observable<Document> {
|
||||
return fromEvent(document, "DOMContentLoaded")
|
||||
export function watchDocument(
|
||||
{ location$ }: WatchOptions = {}
|
||||
): Observable<Document> {
|
||||
return merge(
|
||||
fromEvent(document, "DOMContentLoaded")
|
||||
.pipe(
|
||||
mapTo(document)
|
||||
),
|
||||
typeof location$ !== "undefined"
|
||||
? watchDocumentSwitch({ location$ })
|
||||
: NEVER
|
||||
)
|
||||
.pipe(
|
||||
mapTo(document),
|
||||
shareReplay(1)
|
||||
)
|
||||
}
|
||||
|
@ -75,17 +75,15 @@ let toggles$: Observable<ToggleMap>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Watch toggles with given names
|
||||
* Setup bindings to toggles with given names
|
||||
*
|
||||
* @param names - Toggle names
|
||||
* @param options - Options
|
||||
*
|
||||
* @return Toggle map observable
|
||||
*/
|
||||
export function watchToggleMap(
|
||||
export function setupToggles(
|
||||
names: Toggle[], { document$ }: WatchOptions
|
||||
): Observable<ToggleMap> {
|
||||
return toggles$ = document$
|
||||
): void {
|
||||
toggles$ = document$
|
||||
.pipe(
|
||||
|
||||
/* Ignore document switches */
|
||||
@ -108,7 +106,8 @@ export function watchToggleMap(
|
||||
/**
|
||||
* Retrieve a toggle
|
||||
*
|
||||
* @template T - Element type
|
||||
* The returned observable will only re-emit if the element changed, i.e. if
|
||||
* it was replaced from a document which was switched to.
|
||||
*
|
||||
* @param name - Toggle name
|
||||
*
|
||||
@ -136,7 +135,7 @@ export function useToggle(
|
||||
* Simulating a click event seems to be the most cross-browser compatible way
|
||||
* of changing the value while also emitting a `change` event. Before, Material
|
||||
* used `CustomEvent` to programmatically change the value of a toggle, but this
|
||||
* is a much simpler and cleaner solution.
|
||||
* is a much simpler and cleaner solution which doesn't require a polyfill.
|
||||
*
|
||||
* @param el - Toggle element
|
||||
* @param value - Toggle value
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
import { Subject, from } from "rxjs"
|
||||
import { ajax } from "rxjs/ajax"
|
||||
import { map, pluck } from "rxjs/operators"
|
||||
import { map, pluck, shareReplay } from "rxjs/operators"
|
||||
|
||||
import { SearchIndexOptions } from "integrations/search"
|
||||
import {
|
||||
@ -106,7 +106,8 @@ export function setupSearchWorker(
|
||||
}
|
||||
}
|
||||
return message
|
||||
})
|
||||
}),
|
||||
shareReplay(1)
|
||||
)
|
||||
|
||||
/* Fetch index if it wasn't passed explicitly */
|
||||
|
Loading…
Reference in New Issue
Block a user