import "@ungap/with-resolvers"; import { $ } from "basic-devtools"; import { define } from "../index.js"; import { queryTarget } from "../script-handler.js"; import { defineProperty } from "../utils.js"; import { getText } from "../fetch-utils.js"; // TODO: should this utility be in core instead? import { robustFetch as fetch } from "./pyscript/fetch.js"; // append ASAP CSS to avoid showing content document.head.appendChild(document.createElement("style")).textContent = ` py-script, py-config { display: none; } `; (async () => { // 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); // generic helper to disambiguate between custom element and script const isScript = (element) => element.tagName === "SCRIPT"; // helper for all script[type="py"] out there const before = (script) => { defineProperty(document, "currentScript", { configurable: true, get: () => script, }); }; const after = () => { delete document.currentScript; }; /** * Given a generic DOM Element, tries to fetch the 'src' attribute, if present. * It either throws an error if the 'src' can't be fetched or it returns a fallback * content as source. */ const fetchSource = async (tag) => { if (tag.hasAttribute("src")) { try { const response = await fetch(tag.getAttribute("src")); return response.then(getText); } catch (error) { // TODO _createAlertBanner(err) instead ? alert(error.message); throw error; } } return tag.textContent; }; // common life-cycle handlers for any node const bootstrapNodeAndPlugins = (pyodide, element, callback, hook) => { if (isScript(element)) callback(element); for (const fn of hooks[hook]) fn(pyodide, element); }; const addDisplay = (element) => { const id = isScript(element) ? element.target.id : element.id; return ` # this code is just for demo purpose but the basics work def _display(what, target="${id}", append=True): from js import document element = document.getElementById(target) element.textContent = what display = _display `; }; // define the module as both `