mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
[next] Bootstrap plugins directly (#1698)
This commit is contained in:
committed by
GitHub
parent
7994207c78
commit
3aef5a99dc
@@ -10,7 +10,11 @@ for (const file of readdirSync(join(__dirname, "..", "src", "plugins"))) {
|
||||
? name
|
||||
: `[${JSON.stringify(name)}]`;
|
||||
const value = JSON.stringify(`./plugins/${file}`);
|
||||
plugins.push(` ${key}: () => import(${value}),`);
|
||||
plugins.push(
|
||||
// this comment is needed to avoid bundlers eagerly embedding lazy
|
||||
// dependencies, causing all sort of issues once in production
|
||||
` ${key}: () => import(/* webpackIgnore: true */ ${value}),`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
44
pyscript.core/src/config.js
Normal file
44
pyscript.core/src/config.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* This file parses a generic <py-config> or config attribute
|
||||
* to use as base config for all py-script elements, importing
|
||||
* also a queue of plugins *before* the interpreter (if any) resolves.
|
||||
*/
|
||||
import { $ } from "basic-devtools";
|
||||
|
||||
import allPlugins from "./plugins.js";
|
||||
import { robustFetch as fetch, getText } from "./fetch.js";
|
||||
|
||||
// TODO: this is not strictly polyscript related but handy ... not sure
|
||||
// we should factor this utility out a part but this works anyway.
|
||||
import { parse } from "../node_modules/polyscript/esm/toml.js";
|
||||
|
||||
// find the shared config for all py-script elements
|
||||
let config, plugins, parsed;
|
||||
let pyConfig = $("py-config");
|
||||
if (pyConfig) config = pyConfig.getAttribute("src") || pyConfig.textContent;
|
||||
else {
|
||||
pyConfig = $('script[type="py"][config]');
|
||||
if (pyConfig) config = pyConfig.getAttribute("config");
|
||||
}
|
||||
|
||||
// load its content if remote
|
||||
if (/^https?:\/\//.test(config)) config = await fetch(config).then(getText);
|
||||
|
||||
// parse config only if not empty
|
||||
if (config?.trim()) {
|
||||
try {
|
||||
parsed = JSON.parse(config);
|
||||
} catch (_) {
|
||||
parsed = await parse(config);
|
||||
}
|
||||
}
|
||||
|
||||
// parse all plugins and optionally ignore only
|
||||
// those flagged as "undesired" via `!` prefix
|
||||
const toBeAwaited = [];
|
||||
for (const [key, value] of Object.entries(allPlugins)) {
|
||||
if (!parsed?.plugins?.includes(`!${key}`)) toBeAwaited.push(value());
|
||||
}
|
||||
if (toBeAwaited.length) plugins = Promise.all(toBeAwaited);
|
||||
|
||||
export { config, plugins };
|
||||
@@ -1,12 +1,7 @@
|
||||
/*! (c) PyScript Development Team */
|
||||
|
||||
import "@ungap/with-resolvers";
|
||||
import { $ } from "basic-devtools";
|
||||
import { define, XWorker } from "polyscript";
|
||||
import sync from "./sync.js";
|
||||
|
||||
import stdlib from "./stdlib.js";
|
||||
import plugins from "./plugins.js";
|
||||
|
||||
// TODO: this is not strictly polyscript related but handy ... not sure
|
||||
// we should factor this utility out a part but this works anyway.
|
||||
@@ -14,29 +9,21 @@ import { queryTarget } from "../node_modules/polyscript/esm/script-handler.js";
|
||||
import { dedent, dispatch } from "../node_modules/polyscript/esm/utils.js";
|
||||
import { Hook } from "../node_modules/polyscript/esm/worker/hooks.js";
|
||||
|
||||
import { robustFetch as fetch } from "./fetch.js";
|
||||
import sync from "./sync.js";
|
||||
import stdlib from "./stdlib.js";
|
||||
import { config, plugins } from "./config.js";
|
||||
import { robustFetch as fetch, getText } from "./fetch.js";
|
||||
|
||||
const { assign, defineProperty, entries } = Object;
|
||||
|
||||
const getText = (body) => body.text();
|
||||
const TYPE = "py";
|
||||
|
||||
// allows lazy element features on code evaluation
|
||||
let currentElement;
|
||||
|
||||
// create a unique identifier when/if needed
|
||||
let id = 0;
|
||||
const getID = (prefix = "py") => `${prefix}-${id++}`;
|
||||
|
||||
// find the shared config for all py-script elements
|
||||
let config;
|
||||
let pyConfig = $("py-config");
|
||||
if (pyConfig) config = pyConfig.getAttribute("src") || pyConfig.textContent;
|
||||
else {
|
||||
pyConfig = $('script[type="py"]');
|
||||
config = pyConfig?.getAttribute("config");
|
||||
}
|
||||
|
||||
if (/^https?:\/\//.test(config)) config = await fetch(config).then(getText);
|
||||
const getID = (prefix = TYPE) => `${prefix}-${id++}`;
|
||||
|
||||
// generic helper to disambiguate between custom element and script
|
||||
const isScript = ({ tagName }) => tagName === "SCRIPT";
|
||||
@@ -70,7 +57,7 @@ const fetchSource = async (tag, io, asText) => {
|
||||
if (asText) return dedent(tag.textContent);
|
||||
|
||||
console.warn(
|
||||
'Deprecated: use <script type="py"> for an always safe content parsing:\n',
|
||||
`Deprecated: use <script type="${TYPE}"> for an always safe content parsing:\n`,
|
||||
tag.innerHTML,
|
||||
);
|
||||
|
||||
@@ -140,14 +127,10 @@ const workerHooks = {
|
||||
[...hooks.codeAfterRunWorkerAsync].map(dedent).join("\n"),
|
||||
};
|
||||
|
||||
// avoid running further script if the previous one had
|
||||
// some import that would inevitably delay its execution
|
||||
let queuePlugins;
|
||||
|
||||
// define the module as both `<script type="py">` and `<py-script>`
|
||||
define("py", {
|
||||
define(TYPE, {
|
||||
config,
|
||||
env: "py-script",
|
||||
env: `${TYPE}-script`,
|
||||
interpreter: "pyodide",
|
||||
...workerHooks,
|
||||
onWorkerReady(_, xworker) {
|
||||
@@ -173,21 +156,8 @@ define("py", {
|
||||
registerModule(pyodide);
|
||||
}
|
||||
|
||||
// load plugins unless specified otherwise
|
||||
const toBeAwaited = [];
|
||||
for (const [key, value] of entries(plugins)) {
|
||||
if (!pyodide.config?.plugins?.includes(`!${key}`))
|
||||
toBeAwaited.push(value());
|
||||
}
|
||||
|
||||
// this grants queued results when first script/tag has plugins
|
||||
// and the second one *might* rely on first tag execution
|
||||
if (toBeAwaited.length) {
|
||||
const all = Promise.all(toBeAwaited);
|
||||
queuePlugins = queuePlugins ? queuePlugins.then(() => all) : all;
|
||||
}
|
||||
|
||||
if (queuePlugins) await queuePlugins;
|
||||
// ensure plugins are bootstrapped already
|
||||
if (plugins) await plugins;
|
||||
|
||||
// allows plugins to do whatever they want with the element
|
||||
// before regular stuff happens in here
|
||||
@@ -215,7 +185,7 @@ define("py", {
|
||||
defineProperty(element, "target", { value: show });
|
||||
|
||||
// notify before the code runs
|
||||
dispatch(element, "py");
|
||||
dispatch(element, TYPE);
|
||||
pyodide[`run${isAsync ? "Async" : ""}`](
|
||||
await fetchSource(element, pyodide.io, true),
|
||||
);
|
||||
@@ -249,7 +219,7 @@ class PyScriptElement extends HTMLElement {
|
||||
this.srcCode = await fetchSource(this, io, !this.childElementCount);
|
||||
this.replaceChildren();
|
||||
// notify before the code runs
|
||||
dispatch(this, "py");
|
||||
dispatch(this, TYPE);
|
||||
runner(this.srcCode);
|
||||
this.style.display = "block";
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { FetchError, ErrorCode } from "./exceptions.js";
|
||||
import { getText } from "../node_modules/polyscript/esm/fetch-utils.js";
|
||||
|
||||
export { getText };
|
||||
|
||||
/**
|
||||
* This is a fetch wrapper that handles any non 200 responses and throws a
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// ⚠️ This file is an artifact: DO NOT MODIFY
|
||||
export default {
|
||||
error: () => import("./plugins/error.js"),
|
||||
error: () => import(/* webpackIgnore: true */ "./plugins/error.js"),
|
||||
};
|
||||
|
||||
2
pyscript.core/types/config.d.ts
vendored
Normal file
2
pyscript.core/types/config.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export let config: any;
|
||||
export let plugins: any;
|
||||
3
pyscript.core/types/core.d.ts
vendored
3
pyscript.core/types/core.d.ts
vendored
@@ -21,6 +21,5 @@ export namespace hooks {
|
||||
let codeAfterRunWorker: Set<string>;
|
||||
let codeAfterRunWorkerAsync: Set<string>;
|
||||
}
|
||||
declare let config: any;
|
||||
import { config } from "./config.js";
|
||||
import sync from "./sync.js";
|
||||
export {};
|
||||
|
||||
1
pyscript.core/types/fetch.d.ts
vendored
1
pyscript.core/types/fetch.d.ts
vendored
@@ -8,3 +8,4 @@
|
||||
* @returns {Promise<Response>}
|
||||
*/
|
||||
export function robustFetch(url: string, options?: Request): Promise<Response>;
|
||||
export { getText };
|
||||
|
||||
Reference in New Issue
Block a user