mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Evaluate script elements upon load when using instant loading
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
material/assets/javascripts/bundle.4de2b008.min.js.map
Normal file
1
material/assets/javascripts/bundle.4de2b008.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"assets/javascripts/bundle.js": "assets/javascripts/bundle.2f004b84.min.js",
|
"assets/javascripts/bundle.js": "assets/javascripts/bundle.4de2b008.min.js",
|
||||||
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.2f004b84.min.js.map",
|
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.4de2b008.min.js.map",
|
||||||
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.926ffd9e.min.js",
|
"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/javascripts/worker/search.js.map": "assets/javascripts/worker/search.926ffd9e.min.js.map",
|
||||||
"assets/stylesheets/main.scss": "assets/stylesheets/main.1e07d700.min.css",
|
"assets/stylesheets/main.css": "assets/stylesheets/main.1e07d700.min.css",
|
||||||
"assets/stylesheets/palette.scss": "assets/stylesheets/palette.f5f04e6f.min.css"
|
"assets/stylesheets/palette.css": "assets/stylesheets/palette.f5f04e6f.min.css"
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="{{ 'assets/javascripts/bundle.2f004b84.min.js' | url }}"></script>
|
<script src="{{ 'assets/javascripts/bundle.4de2b008.min.js' | url }}"></script>
|
||||||
{%- set translations = {} -%}
|
{%- set translations = {} -%}
|
||||||
{%- for key in [
|
{%- for key in [
|
||||||
"clipboard.copy",
|
"clipboard.copy",
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ import {
|
|||||||
debounceTime,
|
debounceTime,
|
||||||
distinctUntilKeyChanged,
|
distinctUntilKeyChanged,
|
||||||
distinctUntilChanged,
|
distinctUntilChanged,
|
||||||
bufferCount,
|
bufferCount
|
||||||
startWith
|
|
||||||
} from "rxjs/operators"
|
} from "rxjs/operators"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -96,7 +95,8 @@ import {
|
|||||||
patchTables,
|
patchTables,
|
||||||
patchDetails,
|
patchDetails,
|
||||||
patchScrollfix,
|
patchScrollfix,
|
||||||
patchSource
|
patchSource,
|
||||||
|
patchScripts
|
||||||
} from "patches"
|
} from "patches"
|
||||||
import { isConfig } from "utilities"
|
import { isConfig } from "utilities"
|
||||||
import { setupDialog } from "integrations/dialog"
|
import { setupDialog } from "integrations/dialog"
|
||||||
@@ -245,13 +245,13 @@ export function initialize(config: unknown) {
|
|||||||
|
|
||||||
const keyboard$ = setupKeyboard()
|
const keyboard$ = setupKeyboard()
|
||||||
|
|
||||||
patchTables({ document$ })
|
|
||||||
patchDetails({ document$, hash$ })
|
patchDetails({ document$, hash$ })
|
||||||
|
patchScripts({ document$ })
|
||||||
patchSource({ document$ })
|
patchSource({ document$ })
|
||||||
|
patchTables({ document$ })
|
||||||
|
|
||||||
/* Force 1px scroll offset to trigger overflow scrolling */
|
/* Force 1px scroll offset to trigger overflow scrolling */
|
||||||
if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g))
|
patchScrollfix({ document$ })
|
||||||
patchScrollfix({ document$ })
|
|
||||||
|
|
||||||
/* Setup clipboard and dialog */
|
/* Setup clipboard and dialog */
|
||||||
const dialog$ = setupDialog()
|
const dialog$ = setupDialog()
|
||||||
|
|||||||
@@ -61,15 +61,14 @@ export function setupClipboard(
|
|||||||
return NEVER
|
return NEVER
|
||||||
|
|
||||||
/* Inject 'copy-to-clipboard' buttons */
|
/* Inject 'copy-to-clipboard' buttons */
|
||||||
document$
|
document$.subscribe(() => {
|
||||||
.subscribe(() => {
|
const blocks = getElements("pre > code")
|
||||||
const blocks = getElements("pre > code")
|
for (const [index, block] of blocks.entries()) {
|
||||||
for (const [index, block] of blocks.entries()) {
|
const parent = block.parentElement!
|
||||||
const parent = block.parentElement!
|
parent.id = `__code_${index}`
|
||||||
parent.id = `__code_${index}`
|
parent.insertBefore(renderClipboard(parent.id), block)
|
||||||
parent.insertBefore(renderClipboard(parent.id), block)
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
/* Initialize and setup clipboard */
|
/* Initialize and setup clipboard */
|
||||||
const clipboard$ = fromEventPattern<ClipboardJS.Event>(next => {
|
const clipboard$ = fromEventPattern<ClipboardJS.Event>(next => {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from "./details"
|
export * from "./details"
|
||||||
|
export * from "./script"
|
||||||
export * from "./scrollfix"
|
export * from "./scrollfix"
|
||||||
export * from "./source"
|
export * from "./source"
|
||||||
export * from "./table"
|
export * from "./table"
|
||||||
|
|||||||
91
src/assets/javascripts/patches/script/index.ts
Normal file
91
src/assets/javascripts/patches/script/index.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2020 Martin Donath <martin.donath@squidfunk.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { identity } from "ramda"
|
||||||
|
import { Observable, fromEvent, merge } from "rxjs"
|
||||||
|
import {
|
||||||
|
filter,
|
||||||
|
map,
|
||||||
|
skip,
|
||||||
|
switchMapTo,
|
||||||
|
tap,
|
||||||
|
withLatestFrom
|
||||||
|
} from "rxjs/operators"
|
||||||
|
|
||||||
|
import { useComponent } from "components"
|
||||||
|
import {
|
||||||
|
getElement,
|
||||||
|
getElements,
|
||||||
|
watchMedia
|
||||||
|
} from "observables"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Helper types
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mount options
|
||||||
|
*/
|
||||||
|
interface MountOptions {
|
||||||
|
document$: Observable<Document> /* Document observable */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patch all `script` elements
|
||||||
|
*
|
||||||
|
* This function must be run after a document switch, which means the first
|
||||||
|
* emission must be ignored.
|
||||||
|
*
|
||||||
|
* @param options - Options
|
||||||
|
*/
|
||||||
|
export function patchScripts(
|
||||||
|
{ document$ }: MountOptions
|
||||||
|
): void {
|
||||||
|
const els$ = document$
|
||||||
|
.pipe(
|
||||||
|
skip(1),
|
||||||
|
withLatestFrom(useComponent("container")),
|
||||||
|
map(([, el]) => getElements<HTMLScriptElement>("script", el))
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Evaluate all scripts via replacement */
|
||||||
|
els$.subscribe(els => {
|
||||||
|
for (const el of els) {
|
||||||
|
if (
|
||||||
|
el.src || !el.type ||
|
||||||
|
/^(application|text)\/javascript$/i.test(el.type)
|
||||||
|
) {
|
||||||
|
const script = document.createElement("script")
|
||||||
|
if (el.src) {
|
||||||
|
script.src = el.src
|
||||||
|
} else {
|
||||||
|
script.innerText = el.innerText
|
||||||
|
}
|
||||||
|
el.replaceWith(script)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Observable, fromEvent, merge } from "rxjs"
|
import { NEVER, Observable, fromEvent, iif, merge } from "rxjs"
|
||||||
import { map, mapTo, shareReplay, switchMap } from "rxjs/operators"
|
import { map, mapTo, shareReplay, switchMap } from "rxjs/operators"
|
||||||
|
|
||||||
import { getElements } from "observables"
|
import { getElements } from "observables"
|
||||||
@@ -36,6 +36,19 @@ interface MountOptions {
|
|||||||
document$: Observable<Document> /* Document observable */
|
document$: Observable<Document> /* Document observable */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Helper functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whetehr the given device is an Apple device
|
||||||
|
*
|
||||||
|
* @return Test result
|
||||||
|
*/
|
||||||
|
function isAppleDevice(): boolean {
|
||||||
|
return /(iPad|iPhone|iPod)/.test(navigator.userAgent)
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Functions
|
* Functions
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
@@ -67,7 +80,7 @@ export function patchScrollfix(
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* Patch overflow scrolling on touch start */
|
/* Patch overflow scrolling on touch start */
|
||||||
els$
|
iif(isAppleDevice, els$, NEVER)
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(els => merge(...els.map(el => (
|
switchMap(els => merge(...els.map(el => (
|
||||||
fromEvent(el, "touchstart")
|
fromEvent(el, "touchstart")
|
||||||
|
|||||||
@@ -52,14 +52,13 @@ export function cache<T>(
|
|||||||
/* Retrieve value from observable factory and write to storage */
|
/* Retrieve value from observable factory and write to storage */
|
||||||
} else {
|
} else {
|
||||||
const value$ = factory()
|
const value$ = factory()
|
||||||
value$
|
value$.subscribe(value => {
|
||||||
.subscribe(value => {
|
try {
|
||||||
try {
|
sessionStorage.setItem(key, JSON.stringify(value))
|
||||||
sessionStorage.setItem(key, JSON.stringify(value))
|
} catch (err) {
|
||||||
} catch (err) {
|
/* Uncritical, just swallow */
|
||||||
/* Uncritical, just swallow */
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
|
|
||||||
/* Return value */
|
/* Return value */
|
||||||
return value$
|
return value$
|
||||||
|
|||||||
@@ -94,13 +94,13 @@
|
|||||||
|
|
||||||
<!-- Theme-related stylesheets -->
|
<!-- Theme-related stylesheets -->
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.scss' | url }}" />
|
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.css' | url }}" />
|
||||||
|
|
||||||
<!-- Extra color palette -->
|
<!-- Extra color palette -->
|
||||||
{% if palette.primary or palette.accent %}
|
{% if palette.primary or palette.accent %}
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="{{ 'assets/stylesheets/palette.scss' | url }}"
|
href="{{ 'assets/stylesheets/palette.css' | url }}"
|
||||||
/>
|
/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,13 @@ function config(args: Configuration): Configuration {
|
|||||||
plugins: [
|
plugins: [
|
||||||
new AssetsManifestPlugin({
|
new AssetsManifestPlugin({
|
||||||
output: "assets/manifest.json",
|
output: "assets/manifest.json",
|
||||||
assets
|
assets,
|
||||||
|
customize({ key, value }) {
|
||||||
|
return {
|
||||||
|
key: key.replace(/\.scss$/, ".css"),
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
|
|
||||||
@@ -286,17 +292,21 @@ export default (_env: never, args: Configuration): Configuration[] => {
|
|||||||
context: "src"
|
context: "src"
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/* Replace assets in base template */
|
/* Hooks */
|
||||||
new EventHooksPlugin({
|
new EventHooksPlugin({
|
||||||
afterEmit: () => {
|
afterEmit: () => {
|
||||||
const manifest = require("./material/assets/manifest.json")
|
|
||||||
const template = toPairs<string>(manifest)
|
|
||||||
.reduce((content, [from, to]) => {
|
|
||||||
return content.replace(from, to)
|
|
||||||
}, fs.readFileSync("material/base.html", "utf8"))
|
|
||||||
|
|
||||||
/* Save template with replaced assets */
|
/* Replace asset URLs in base template */
|
||||||
fs.writeFileSync("material/base.html", template, "utf8")
|
if (args.mode === "production") {
|
||||||
|
const manifest = require("./material/assets/manifest.json")
|
||||||
|
const template = toPairs<string>(manifest)
|
||||||
|
.reduce((content, [from, to]) => {
|
||||||
|
return content.replace(from, to)
|
||||||
|
}, fs.readFileSync("material/base.html", "utf8"))
|
||||||
|
|
||||||
|
/* Save template with replaced assets */
|
||||||
|
fs.writeFileSync("material/base.html", template, "utf8")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user