Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pyscript/core",
"version": "0.7.18",
"version": "0.7.24",
"type": "module",
"description": "PyScript",
"module": "./index.js",
Expand Down
60 changes: 43 additions & 17 deletions core/src/plugins/py-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const getRelatedScript = (target, type) => {
return editor?.parentNode?.previousElementSibling;
};

async function execute({ currentTarget, script }) {
async function execute({ currentTarget, script }, onBeforeRun = "") {
const { env, pySrc, outDiv } = this;
const hasRunButton = !!currentTarget;

Expand Down Expand Up @@ -152,7 +152,8 @@ async function execute({ currentTarget, script }) {
console.error(str);
}
};
sync.runAsync(pySrc).then(enable, enable);
if (onBeforeRun) onBeforeRun += ";";
sync.runAsync(onBeforeRun + pySrc).then(enable, enable);
});
}

Expand All @@ -176,11 +177,11 @@ const makeRunButton = (handler, type) => {
runButton.innerHTML = RUN_BUTTON;
runButton.setAttribute("aria-label", "Python Script Run Button");
runButton.addEventListener("click", async (event) => {
const script = getRelatedScript(runButton, type);
if (
runButton.classList.contains("running") &&
confirm("Stop evaluating this code?")
) {
const script = getRelatedScript(runButton, type);
if (script) {
const env = script.getAttribute("env");
// remove the bootstrapped env which could be one or shared
Expand All @@ -205,7 +206,10 @@ const makeRunButton = (handler, type) => {
return;
}
runButton.blur();
await handler.handleEvent(event);
await handler.handleEvent(
event,
script?.getAttribute("onbeforerun") || "",
);
});
return runButton;
};
Expand Down Expand Up @@ -235,12 +239,13 @@ const makeOutDiv = (type) => {
return outDiv;
};

const makeBoxDiv = (handler, type) => {
const makeBoxDiv = (handler, type, output) => {
const boxDiv = document.createElement("div");
boxDiv.className = `${type}-editor-box`;

const editorDiv = makeEditorDiv(handler, type);
const outDiv = makeOutDiv(type);
const outDiv = output ? document.getElementById(output) : makeOutDiv(type);
if (output) outDiv.classList.add(`${type}-editor-output`);
boxDiv.append(editorDiv, outDiv);

return [boxDiv, outDiv, editorDiv.querySelector("button")];
Expand Down Expand Up @@ -276,12 +281,20 @@ const init = async (script, type, interpreter) => {
}).onmessage = ({ target }) => target.terminate();
}

// allow bootstrap with same env for repeated editor creation
// only if `env-override` is explicitly set as attribute
if (hasConfig && configs.has(env)) {
throw new SyntaxError(
configs.get(env)
? `duplicated config for env: ${env}`
: `unable to add a config to the env: ${env}`,
);
if (script.hasAttribute("env-override")) {
// in this case we need to bootstrap the env again
// because otherwise each env would leak
envs.delete(env);
} else {
throw new SyntaxError(
configs.get(env)
? `duplicated config for env: ${env}`
: `unable to add a config to the env: ${env}`,
);
}
}

configs.set(env, hasConfig);
Expand Down Expand Up @@ -328,7 +341,7 @@ const init = async (script, type, interpreter) => {
// in every other case be sure that if the listener override returned
// `false` nothing happens, otherwise keep doing what it always did
else {
context.handleEvent = async (event) => {
context.handleEvent = async (event, onBeforeRun) => {
// trap the currentTarget ASAP (if any)
// otherwise it gets lost asynchronously
const { currentTarget } = event;
Expand All @@ -338,7 +351,11 @@ const init = async (script, type, interpreter) => {
});
// avoid executing the default handler if the override returned `false`
if ((await callback(event)) !== false)
await execute.call(context, { currentTarget });
await execute.call(
context,
{ currentTarget },
onBeforeRun,
);
};
}
},
Expand Down Expand Up @@ -388,8 +405,7 @@ const init = async (script, type, interpreter) => {
};

if (isSetup) {
await context.handleEvent({ currentTarget: null, script });
notifyEditor();
context.handleEvent({ currentTarget: null, script }).then(notifyEditor);
return;
}

Expand All @@ -411,13 +427,23 @@ const init = async (script, type, interpreter) => {
if (!target.hasAttribute("root")) target.setAttribute("root", target.id);

// @see https://github.com/JeffersGlass/mkdocs-pyscript/blob/main/mkdocs_pyscript/js/makeblocks.js
const [boxDiv, outDiv, runButton] = makeBoxDiv(context, type);
const [boxDiv, outDiv, runButton] = makeBoxDiv(
context,
type,
script.getAttribute("output"),
);
boxDiv.dataset.env = script.hasAttribute("env") ? env : interpreter;

const inputChild = boxDiv.querySelector(`.${type}-editor-input > div`);
const parent = inputChild.attachShadow({ mode: "open" });
// avoid inheriting styles from the outer component
parent.innerHTML = `<style> :host { all: initial; }</style>`;
const styles = [":host { all: initial; }"];
const rows = script.getAttribute("rows");
if (rows) {
const maxHeight = Math.floor(parseInt(rows) * 18.5) + "px";
styles.push(`.cm-editor { height: auto; max-height: ${maxHeight}; }`);
}
parent.innerHTML = `<style>${styles.join("\n")}</style>`;

target.appendChild(boxDiv);

Expand Down
Loading