mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
load html pages from service worker
This commit is contained in:
13
index.html
13
index.html
@@ -382,19 +382,6 @@
|
|||||||
|
|
||||||
if(new URLSearchParams(window.location.search).get('leporello') == null) {
|
if(new URLSearchParams(window.location.search).get('leporello') == null) {
|
||||||
await import('./src/launch.js');
|
await import('./src/launch.js');
|
||||||
// TODO remove?
|
|
||||||
/*
|
|
||||||
const {init} = await import('./src/index.js');
|
|
||||||
(
|
|
||||||
document.readyState == 'complete'
|
|
||||||
? Promise.resolve()
|
|
||||||
: new Promise(resolve =>
|
|
||||||
window.addEventListener('load', resolve)
|
|
||||||
)
|
|
||||||
).then(() => {
|
|
||||||
init(document.getElementById('app'))
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -29,22 +29,39 @@ self.addEventListener('message', async function(e) {
|
|||||||
e.ports[0].postMessage(reply)
|
e.ports[0].postMessage(reply)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Fake URL base prepended by code responsible for module loading
|
// Fake directory, http requests to this directory intercepted by service_worker
|
||||||
const FAKE_URL_BASE = 'https://leporello.import/'
|
const FILES_ROOT = '__leporello_files'
|
||||||
|
|
||||||
self.addEventListener("fetch", event => {
|
self.addEventListener("fetch", event => {
|
||||||
if(event.request.url.startsWith(FAKE_URL_BASE)) {
|
const url = new URL(event.request.url)
|
||||||
if(dir_handle != null) {
|
if(url.pathname.startsWith('/' + FILES_ROOT)) {
|
||||||
|
const path = url.pathname.replace('/' + FILES_ROOT + '/', '')
|
||||||
|
|
||||||
|
let file
|
||||||
|
|
||||||
|
if(path == '__leporello_blank.html') {
|
||||||
|
file = Promise.resolve('')
|
||||||
|
} else if(dir_handle != null) {
|
||||||
|
file = read_file(dir_handle, path)
|
||||||
|
} else {
|
||||||
|
// Delegate request to browser
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const headers = new Headers([
|
const headers = new Headers([
|
||||||
['Content-Type', 'text/javascript']
|
[
|
||||||
|
'Content-Type',
|
||||||
|
path.endsWith('.js') || path.endsWith('.mjs')
|
||||||
|
? 'text/javascript'
|
||||||
|
: 'text/html'
|
||||||
|
]
|
||||||
])
|
])
|
||||||
const path = event.request.url.replace(FAKE_URL_BASE, '')
|
|
||||||
const response = read_file(dir_handle, path).then(file =>
|
const response = file.then(file =>
|
||||||
new Response(file, {headers})
|
new Response(file, {headers})
|
||||||
)
|
)
|
||||||
event.respondWith(response)
|
event.respondWith(response)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const read_file = async (dir_handle, filename) => {
|
const read_file = async (dir_handle, filename) => {
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ export class UI {
|
|||||||
state.html_file == f
|
state.html_file == f
|
||||||
? { value: f, selected: true }
|
? { value: f, selected: true }
|
||||||
: { value: f},
|
: { value: f},
|
||||||
f == '' ? 'abount:blank' : f
|
f == '' ? 'about:blank' : f
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
9
src/effects.js
vendored
9
src/effects.js
vendored
@@ -6,7 +6,7 @@ import {
|
|||||||
get_async_calls
|
get_async_calls
|
||||||
} from './calltree.js'
|
} from './calltree.js'
|
||||||
import {FLAGS} from './feature_flags.js'
|
import {FLAGS} from './feature_flags.js'
|
||||||
import {exec} from './index.js'
|
import {exec, FILES_ROOT} from './index.js'
|
||||||
|
|
||||||
// Imports in the context of `run_window`, so global variables in loaded
|
// Imports in the context of `run_window`, so global variables in loaded
|
||||||
// modules refer to that window's context
|
// modules refer to that window's context
|
||||||
@@ -27,8 +27,11 @@ const load_external_imports = async state => {
|
|||||||
? // starts with protocol, import as is
|
? // starts with protocol, import as is
|
||||||
u
|
u
|
||||||
: // local path, load using File System Access API, see service_worker.js
|
: // local path, load using File System Access API, see service_worker.js
|
||||||
// Append fake host that will be intercepted in service worker
|
// Append special URL segment that will be intercepted in service worker
|
||||||
'https://leporello.import/' + u
|
// Note that we use the same origin as current page (where Leporello
|
||||||
|
// is hosted), so Leporello can access window object for custom
|
||||||
|
// `html_file`
|
||||||
|
window.location.origin + '/' + FILES_ROOT + '/' + u
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
const modules = Object.fromEntries(
|
const modules = Object.fromEntries(
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ const EXAMPLE = `const fib = n =>
|
|||||||
: fib(n - 1) + fib(n - 2)
|
: fib(n - 1) + fib(n - 2)
|
||||||
fib(6)`
|
fib(6)`
|
||||||
|
|
||||||
|
// Fake directory, http requests to this directory intercepted by service_worker
|
||||||
|
export const FILES_ROOT = '__leporello_files'
|
||||||
|
|
||||||
const set_error_handler = w => {
|
const set_error_handler = w => {
|
||||||
// TODO err.message
|
// TODO err.message
|
||||||
w.onerror = (msg, src, lineNum, colNum, err) => {
|
w.onerror = (msg, src, lineNum, colNum, err) => {
|
||||||
@@ -19,9 +22,10 @@ const set_error_handler = w => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const get_html_url = state => {
|
const get_html_url = state => {
|
||||||
|
const base = window.location.origin + '/' + FILES_ROOT + '/'
|
||||||
return state.html_file == ''
|
return state.html_file == ''
|
||||||
? 'about:blank'
|
? base + '__leporello_blank.html'
|
||||||
: window.location.origin + '/' + state.html_file + '?leporello'
|
: base + state.html_file + '?leporello'
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default run code in hidden iframe, until user explicitly opens visible
|
// By default run code in hidden iframe, until user explicitly opens visible
|
||||||
|
|||||||
Reference in New Issue
Block a user