diff --git a/bridge/README.md b/bridge/README.md index f345f1e3..918f1021 100644 --- a/bridge/README.md +++ b/bridge/README.md @@ -21,6 +21,7 @@ def func_b(): ### Options + * **pyscript**: the release version to automatically import if not already available on the page. If no version is provided the *developers' channel* version will be used instead (for developers' purposes only). * **type**: `py` by default to bootstrap *Pyodide*. * **worker**: `true` by default to bootstrap in a *Web Worker*. * **config**: either a *string* or a PyScript compatible config *JS literal* to make it possible to bootstrap files and whatnot. If specified, the `worker` becomes implicitly `true` to avoid multiple configs conflicting on the main thread. @@ -39,6 +40,7 @@ no config The [test.js](./test/test.js) files uses the following defaults: + * `pyscript` as `"2025.8.1"` * `type` as `"mpy"` * `worker` as `false` * `config` as `undefined` diff --git a/bridge/index.js b/bridge/index.js index a65afb60..70528943 100644 --- a/bridge/index.js +++ b/bridge/index.js @@ -1,7 +1,9 @@ /*! (c) PyScript Development Team */ const { stringify } = JSON; -const { create, entries } = Object; +const { assign, create, entries } = Object; + +const el = (name, props) => assign(document.createElement(name), props); /** * Transform a list of keys into a Python dictionary. @@ -57,6 +59,7 @@ export default (url, { config = null, env = null, serviceWorker = null, + pyscript = null, } = {}) => { const { protocol, host, pathname } = new URL(url); const py = pathname.replace(/\.m?js(?:\/\+\w+)?$/, '.py'); @@ -88,8 +91,17 @@ export default (url, { // create the arguments for the `dispatchEvent` call const eventArgs = `${stringify(name)},${name}to_ts(${detail})`; // bootstrap the script element type and its attributes - const script = document.createElement('script'); - script.type = type; + const script = el('script', { type, textContent: [ + '\n', code, '\n', + // this is to avoid local scope name clashing + `from pyscript import window as ${name}`, + `from pyscript.ffi import to_js as ${name}to_ts`, + `${name}.dispatchEvent(${name}.CustomEvent.new(${eventArgs}))`, + // remove these references even if non-clashing to keep + // the local scope clean from undesired entries + `del ${name}`, + `del ${name}to_ts`, + ].join('\n') }); // if config is provided it needs to be a worker to avoid // conflicting with main config on the main thread (just like always) @@ -102,19 +114,6 @@ export default (url, { if (env) script.setAttribute('env', env); if (serviceWorker) script.setAttribute('service-worker', serviceWorker); - // augment the code with the previously accessed fields at the end - script.textContent = [ - '\n', code, '\n', - // this is to avoid local scope name clashing - `from pyscript import window as ${name}`, - `from pyscript.ffi import to_js as ${name}to_ts`, - `${name}.dispatchEvent(${name}.CustomEvent.new(${eventArgs}))`, - // remove these references even if non-clashing to keep - // the local scope clean from undesired entries - `del ${name}`, - `del ${name}to_ts`, - ].join('\n'); - // let PyScript resolve and execute this script document.body.appendChild(script); @@ -132,19 +131,15 @@ export default (url, { // has been emitted and the interpreter evaluated the code const { promise, resolve } = Promise.withResolvers(); - // ⚠️ This is just a *fallback* !!! - // Please always use an explicit PyScript release !!! if (!(Symbol.for('@pyscript/core') in globalThis)) { - // bring in PyScript via the `npm` developers' channel - const cdn = 'https://cdn.jsdelivr.net/npm/@pyscript/core/dist'; + // bring in PyScript if not available already + const cdn = pyscript ? + `https://pyscript.net/releases/${pyscript}` : + // ⚠️ fallback to developers' channel !!! + 'https://cdn.jsdelivr.net/npm/@pyscript/core/dist' + ; document.head.appendChild( - Object.assign( - document.createElement('link'), - { - rel: 'stylesheet', - href: `${cdn}/core.css`, - } - ) + el('link', { rel: 'stylesheet', href: `${cdn}/core.css` }), ); try { await import(`${cdn}/core.js`) } catch {} diff --git a/bridge/package.json b/bridge/package.json index f3bbaf1b..0fb2a7d9 100644 --- a/bridge/package.json +++ b/bridge/package.json @@ -1,6 +1,6 @@ { "name": "@pyscript/bridge", - "version": "0.2.0", + "version": "0.2.2", "description": "A JS based way to use PyScript modules", "type": "module", "module": "./index.js", @@ -14,6 +14,10 @@ "Python", "bridge" ], + "files": [ + "index.js", + "README.md" + ], "author": "Anaconda Inc.", "license": "APACHE-2.0", "repository": { diff --git a/bridge/test/test.js b/bridge/test/test.js index 4c896e04..5429a39f 100644 --- a/bridge/test/test.js +++ b/bridge/test/test.js @@ -5,6 +5,7 @@ const { searchParams } = new URL(location.href); // the named (or default) export for test.py export const ffi = bridge(import.meta.url, { + pyscript: "2025.8.1", env: searchParams.get("env"), type: searchParams.get("type") || "mpy", worker: searchParams.has("worker"),