mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2026-07-24 06:43:50 -04:00
Fixed edge case in scroll restoration
This commit is contained in:
@@ -51,7 +51,8 @@ import {
|
||||
pluck,
|
||||
debounceTime,
|
||||
distinctUntilKeyChanged,
|
||||
distinctUntilChanged
|
||||
distinctUntilChanged,
|
||||
bufferCount
|
||||
} from "rxjs/operators"
|
||||
|
||||
import {
|
||||
@@ -310,7 +311,7 @@ export function initialize(config: unknown) {
|
||||
/**
|
||||
* Location change
|
||||
*/
|
||||
interface LocationChange {
|
||||
interface State {
|
||||
url: URL // TODO: use URL!?
|
||||
data?: ViewportOffset
|
||||
}
|
||||
@@ -323,8 +324,8 @@ export function initialize(config: unknown) {
|
||||
return el.hash.length > 0
|
||||
}
|
||||
|
||||
function compareLocationChange(
|
||||
{ url: a }: LocationChange, { url: b }: LocationChange
|
||||
function compareState(
|
||||
{ url: a }: State, { url: b }: State
|
||||
) {
|
||||
return a.href === b.href
|
||||
}
|
||||
@@ -360,7 +361,7 @@ export function initialize(config: unknown) {
|
||||
return NEVER
|
||||
}),
|
||||
distinctUntilChanged(),
|
||||
map<string, LocationChange>(href => ({ url: new URL(href) })),
|
||||
map<string, State>(href => ({ url: new URL(href) })),
|
||||
share()
|
||||
)
|
||||
|
||||
@@ -374,8 +375,9 @@ export function initialize(config: unknown) {
|
||||
/* Intercept popstate events (history back and forward) */
|
||||
const popstate$ = fromEvent<PopStateEvent>(window, "popstate")
|
||||
.pipe(
|
||||
map<PopStateEvent, LocationChange>(ev => ({
|
||||
url: new URL(getLocation()),
|
||||
filter(ev => ev.state !== null),
|
||||
map<PopStateEvent, State>(ev => ({
|
||||
url: new URL(location.href),
|
||||
data: ev.state
|
||||
})),
|
||||
share()
|
||||
@@ -391,7 +393,8 @@ export function initialize(config: unknown) {
|
||||
/* Add dispatched link to history */
|
||||
internal$
|
||||
.pipe(
|
||||
distinctUntilChanged(compareLocationChange),
|
||||
// TODO: must start with the current location and ignore the first emission
|
||||
distinctUntilChanged(compareState),
|
||||
filter(({ url }) => !isAnchorLink(url))
|
||||
)
|
||||
.subscribe(({ url }) => {
|
||||
@@ -399,6 +402,41 @@ export function initialize(config: unknown) {
|
||||
history.pushState({}, "", url.toString())
|
||||
})
|
||||
|
||||
// special case
|
||||
merge(internal$, popstate$)
|
||||
.pipe(
|
||||
bufferCount(2, 1),
|
||||
// filter(([prev, next]) => {
|
||||
// return prev.url.href.match(next.url.href) !== null
|
||||
// && isAnchorLink(prev.url)
|
||||
// })
|
||||
)
|
||||
.subscribe(([prev, next]) => {
|
||||
console.log(`<- ${prev.url}`)
|
||||
console.log(`-> ${next.url}`)
|
||||
|
||||
if (
|
||||
prev.url.href.match(next.url.href) !== null &&
|
||||
isAnchorLink(prev.url)
|
||||
) {
|
||||
dialog$.next(`Potential Candidate: ${JSON.stringify(next.data)}`, ) // awesome debugging.
|
||||
setViewportOffset(next.data || { y: 0 })
|
||||
}
|
||||
// console.log("Potential Candidate")
|
||||
})
|
||||
// .subscribe((x) => console.log(x[0].url.toString(), x[1].url.toString()))
|
||||
// filter(([prev, next]) => {
|
||||
// return prev.url.href.match(next.url.href) !== null
|
||||
// && isAnchorLink(prev.url)
|
||||
// }),
|
||||
// map(([, next]) => next)
|
||||
// // distinctUntilChanged(compareLocationChange),
|
||||
// // filter(({ url }) => !isAnchorLink(url))
|
||||
// )
|
||||
// .subscribe(({ url }) => {
|
||||
// console.log(`Restore ${url}`)
|
||||
// })
|
||||
|
||||
/* Persist viewport offset in history before hash change */
|
||||
viewport$
|
||||
.pipe(
|
||||
@@ -406,29 +444,18 @@ export function initialize(config: unknown) {
|
||||
distinctUntilKeyChanged("offset"),
|
||||
)
|
||||
.subscribe(({ offset }) => {
|
||||
console.log("Update", offset)
|
||||
// console.log("Update", offset)
|
||||
history.replaceState(offset, "")
|
||||
})
|
||||
|
||||
// /* Edge case: go back from anchor to same
|
||||
// // // TODO: better to just replace the state when this is encountered.
|
||||
// // pop$
|
||||
// // .pipe(
|
||||
// // filter(({ href }) => !/#/.test(href)) // TODO: kind of sucks
|
||||
// // )
|
||||
// // .subscribe(({ data }) => {
|
||||
// // // console.log("Detected", data) // detects too much...
|
||||
// // setViewportOffset(data || { y: 0 }) // TOOD: must wait for document sample!
|
||||
// // })
|
||||
|
||||
/* */
|
||||
merge(dispatch$, popstate$)
|
||||
.pipe(
|
||||
sample(document$),
|
||||
withLatestFrom(document$),
|
||||
)
|
||||
.subscribe(([{ url: href, data }, { title, head }]) => {
|
||||
console.log("Done", href.href, data)
|
||||
.subscribe(([{ url, data }, { title, head }]) => {
|
||||
console.log("Done", url.href, data)
|
||||
|
||||
// setDocumentTitle
|
||||
document.title = title
|
||||
@@ -471,11 +498,11 @@ export function initialize(config: unknown) {
|
||||
// })
|
||||
|
||||
// dispatch$.subscribe(({ url }) => {
|
||||
// console.log(`Push ${url}`)
|
||||
// console.log(`Dispatch ${url}`)
|
||||
// })
|
||||
|
||||
popstate$.subscribe(({ url }) => {
|
||||
console.log(`Pop ${url}`)
|
||||
console.log(`Popstate ${url.href}`, url)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,7 @@ import { NEVER, Observable } from "rxjs"
|
||||
import { ajax } from "rxjs/ajax"
|
||||
import {
|
||||
catchError,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
map,
|
||||
distinctUntilKeyChanged,
|
||||
pluck,
|
||||
share,
|
||||
skip,
|
||||
@@ -54,7 +52,7 @@ interface WatchOptions {
|
||||
/**
|
||||
* Watch document switch
|
||||
*
|
||||
* This function returns an observables that fetches a document if the provided
|
||||
* This function returns an observables that fetches a document if the provided // TODO: update docs
|
||||
* location observable emits a new value (i.e. URL). If the emitted URL points
|
||||
* to the same page, the request is effectively ignored (i.e. when only the
|
||||
* fragment identifier changes).
|
||||
@@ -70,22 +68,20 @@ export function watchDocumentSwitch(
|
||||
): Observable<Document> {
|
||||
return location$
|
||||
.pipe(
|
||||
startWith(location), // TODO: getLocation should return URL or Location
|
||||
filter(url => url.hash.length === 0), // use isAnchorLink
|
||||
map(url => url.href),
|
||||
distinctUntilChanged(),
|
||||
startWith(location), // TODO: getLocation should return URL or Location
|
||||
distinctUntilKeyChanged("pathname"),
|
||||
skip(1),
|
||||
|
||||
/* Fetch document */
|
||||
switchMap(url => ajax({
|
||||
url,
|
||||
url: url.href,
|
||||
responseType: "document",
|
||||
withCredentials: true
|
||||
})
|
||||
.pipe<Document, Document>(
|
||||
pluck("response"),
|
||||
catchError(() => {
|
||||
setLocation(url)
|
||||
setLocation(url.href) // TODO: setLocation should accept URL or location
|
||||
return NEVER
|
||||
})
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user