Fixed bug where a popstate event triggered history.pushState again

This commit is contained in:
squidfunk 2020-03-28 13:25:26 +01:00
parent 0e80ab45b6
commit 63a3481bc2
9 changed files with 48 additions and 21 deletions

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,8 +1,8 @@
{
"assets/javascripts/bundle.js": "assets/javascripts/bundle.864d2fd8.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.864d2fd8.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.cfd486f9.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.cfd486f9.min.js.map",
"assets/javascripts/bundle.js": "assets/javascripts/bundle.e07cb74d.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.e07cb74d.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.c1fcc1cc.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.c1fcc1cc.min.js.map",
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.3bc815f0.min.js",
"assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.3bc815f0.min.js.map",
"assets/stylesheets/main.css": "assets/stylesheets/main.b32d3181.min.css",

View File

@ -174,8 +174,8 @@
{% endblock %}
</div>
{% block scripts %}
<script src="{{ 'assets/javascripts/vendor.cfd486f9.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.864d2fd8.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/vendor.c1fcc1cc.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.e07cb74d.min.js' | url }}"></script>
{%- set translations = {} -%}
{%- for key in [
"clipboard.copy",

View File

@ -80,9 +80,25 @@ interface SetupOptions {
/**
* Set up instant loading
*
* When fetching, theoretically, we could use `responseType: "document"`, but
* since all MkDocs links are relative, we need to make sure that the current
* location matches the document we just loaded. Otherwise any relative links
* in the document could use the old location.
*
* This is the reason why we need to synchronize history events and the process
* of fetching the document for navigation changes (except `popstate` events):
*
* 1. Fetch document via `XMLHTTPRequest`
* 2. Set new location via `history.pushState`
* 3. Parse and emit fetched document
*
* For `popstate` events, we must not use `history.pushState`, or the forward
* history will be irreversibly overwritten. In case the request fails, the
* location change is dispatched regularly.
*
* @param options - Options
*
* @return TODO ?
* @return TODO: return type?
*/
export function setupInstantLoading(
{ document$, viewport$, link$, location$ }: SetupOptions
@ -119,8 +135,9 @@ export function setupInstantLoading(
)
.subscribe(location$)
const dom = new DOMParser()
location$
const ajax$ = location$
.pipe(
distinctUntilKeyChanged("pathname"),
skip(1),
@ -132,18 +149,28 @@ export function setupInstantLoading(
withCredentials: true
})
.pipe(
map(({ response }): Document => {
// TODO: only do this, if
history.pushState({}, "", url.toString()) // TODO: abstract into function
return dom.parseFromString(response, "text/html")
}),
catchError(() => {
setLocation(url)
return NEVER
})
)
),
share()
)
// share()
)
push$
.pipe(
sample(ajax$)
)
.subscribe(({ url }) => {
history.pushState({}, "", url.toString())
})
ajax$
.pipe(
map(({ response }) => {
return dom.parseFromString(response, "text/html")
})
)
.subscribe(document$)