You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte/site/static/repl-runner.js

106 lines
2.7 KiB

(function() {
const import_cache = {};
function fetch_import(id) {
return new Promise((fulfil, reject) => {
curl([`https://bundle.run/${id}`]).then(module => {
import_cache[id] = module;
fulfil(module);
}, err => {
console.error(err.stack);
reject(new Error(`Error loading ${id} from bundle.run`));
});
});
}
function fetch_imports(imports, progress_func) {
const missing_imports = imports.filter(x => !import_cache[x]);
let pending_imports = missing_imports.length;
if (missing_imports.length) {
const promise = Promise.all(
missing_imports.map(id => fetch_import(id).then(() => {
pending_imports -= 1;
if (progress_func) progress_func(pending_imports);
}))
);
return promise;
} else {
return Promise.resolve();
}
}
function handle_message(ev) {
const { action, cmd_id } = ev.data;
const send_message = (payload) => parent.postMessage( { ...payload }, ev.origin);
const send_reply = (payload) => send_message({ ...payload, cmd_id });
const send_ok = () => send_reply({ action: 'cmd_ok' });
const send_error = (message, stack) => send_reply({ action: 'cmd_error', message, stack });
if (action === 'eval') {
try {
const { script } = ev.data.args;
eval(script);
send_ok();
} catch (e) {
send_error(e.message, e.stack);
}
}
if (action === 'catch_clicks') {
try {
const top_origin = ev.origin;
document.body.addEventListener('click', event => {
if (event.which !== 1) return;
if (event.metaKey || event.ctrlKey || event.shiftKey) return;
if (event.defaultPrevented) return;
// ensure target is a link
let el = event.target;
while (el && el.nodeName !== 'A') el = el.parentNode;
if (!el || el.nodeName !== 'A') return;
if (el.hasAttribute('download') || el.getAttribute('rel') === 'external' || el.target) return;
event.preventDefault();
if (el.href.startsWith(top_origin)) {
const url = new URL(el.href);
if (url.hash[0] === '#') {
window.location.hash = url.hash;
return;
}
}
window.open(el.href, '_blank');
});
send_ok();
} catch (e) {
send_error(e.message, e.stack);
}
}
if (action === 'fetch_imports') {
const { imports, import_map } = ev.data.args;
fetch_imports(imports, (remaining) => {
send_message({action: 'fetch_progress', args: { remaining }});
})
.then(() => {
imports.forEach(x => {
const module = import_cache[x];
const name = import_map.get(x);
window[name] = module;
});
send_ok();
})
.catch(e => {
send_error(e.message, e.stack);
});
}
}
window.addEventListener('message', handle_message, false);
})();