add support for pygame scripts
This commit is contained in:
parent
fe4b003971
commit
3be22c5654
6 changed files with 180 additions and 89 deletions
206
lib/pyscript.typ
206
lib/pyscript.typ
|
|
@ -1,8 +1,22 @@
|
|||
#import "./html_utils.typ": add-tag-in-head
|
||||
|
||||
#let state-use-pyscript = state("state-use-pyscript", false)
|
||||
#let state-pyscript-version = state("state-pyscript-version", none)
|
||||
#let state-pyscript-headers = state("state-pyscript-headers", (:))
|
||||
#let state-pyscript-data-list = state("state-pyscript-data-list", (:))
|
||||
#let state-pyscript-interpreters = state("state-pyscript-interpreters", (:))
|
||||
#let state-pyscript-default-interpreter = state("state-pyscript-default-interpreter", none)
|
||||
#let state-pyscript-canvas-ids = state("state-pyscript-canvas-ids", ())
|
||||
|
||||
/// Define data needed to load a version of pyscript
|
||||
#let pyscript-data(
|
||||
/// Url to `core.js`
|
||||
core-js-url,
|
||||
/// Additionnal tags to add to <head>, like mini-coi of core.css
|
||||
additionnal-head-tags: {},
|
||||
) = (
|
||||
core-js-url: core-js-url,
|
||||
additionnal-head-tags: additionnal-head-tags
|
||||
)
|
||||
|
||||
#let get-pep723(script) = {
|
||||
script.find(regex(
|
||||
|
|
@ -31,81 +45,131 @@
|
|||
metadata = (:)
|
||||
}
|
||||
state-use-pyscript.update(x => true)
|
||||
context {
|
||||
let config = metadata.at("tool", default: (:)).at("pyscript", default: (:))
|
||||
let config = metadata.at("tool", default: (:)).at("pyscript", default: (:))
|
||||
|
||||
let pyscript-config = (:)
|
||||
// Package dependencies
|
||||
if "dependencies" in metadata {
|
||||
pyscript-config.insert("packages", metadata.at("dependencies"))
|
||||
}
|
||||
// Files stetup
|
||||
if "files" in config {
|
||||
pyscript-config.insert("files", config.at("files"))
|
||||
}
|
||||
// Interpreteur selection
|
||||
if "interpreter" in config {
|
||||
pyscript-config.insert("interpreter", config.at("interpreter"))
|
||||
} else if state-pyscript-default-interpreter.final() != none {
|
||||
assert(
|
||||
state-pyscript-default-interpreter.final() in state-pyscript-interpreters.final(),
|
||||
message: state-pyscript-default-interpreter.final() + " is not in pyscript-interpreters",
|
||||
)
|
||||
pyscript-config.insert("interpreter", state-pyscript-interpreters.final().at(state-pyscript-default-interpreter.final()))
|
||||
}
|
||||
|
||||
let attrs = (
|
||||
type: "py"
|
||||
let pyscript-config = (:)
|
||||
// Package dependencies
|
||||
if "dependencies" in metadata {
|
||||
pyscript-config.insert("packages", metadata.at("dependencies"))
|
||||
}
|
||||
// Files stetup
|
||||
if "files" in config {
|
||||
pyscript-config.insert("files", config.at("files"))
|
||||
}
|
||||
// Interpreteur selection
|
||||
if "interpreter" in config {
|
||||
pyscript-config.insert("interpreter", config.at("interpreter"))
|
||||
} else if state-pyscript-default-interpreter.final() != none {
|
||||
assert(
|
||||
state-pyscript-default-interpreter.final() in state-pyscript-interpreters.final(),
|
||||
message: state-pyscript-default-interpreter.final() + " is not in pyscript-interpreters",
|
||||
)
|
||||
let default_val_terminal = true
|
||||
let default_val_worker = true
|
||||
let default_val_canvas = none
|
||||
// TODO: canvas: can only be used once by page, need inserting canvas html tag and pyscript hook to link it to pyodide
|
||||
if config.at("pygame", default: false) {
|
||||
default_val_terminal = false
|
||||
default_val_worker = false
|
||||
default_val_canvas = "canvas"
|
||||
}
|
||||
if config.at("terminal", default: true) {
|
||||
attrs.insert("terminal", "")
|
||||
}
|
||||
if config.at("worker", default: true) {
|
||||
attrs.insert("worker", "")
|
||||
}
|
||||
if config.at("canvas", default: default_val_canvas) not in (none, false) {
|
||||
attrs.insert("canvas", config.at("canvas", default: default_val_canvas))
|
||||
}
|
||||
pyscript-config.insert("interpreter", state-pyscript-interpreters.final().at(state-pyscript-default-interpreter.final()))
|
||||
}
|
||||
|
||||
if pyscript-config != (:) {
|
||||
attrs.insert("config", json.encode(pyscript-config))
|
||||
}
|
||||
|
||||
let script = it.text;
|
||||
if config.at("repl", default: false) {
|
||||
script = "import code\n" + script + "\ncode.interact(banner='', local=globals())"
|
||||
}
|
||||
let displayed-code = it.text;
|
||||
if config.at("hide-meta", default: false) {
|
||||
displayed-code = displayed-code.replace(get-pep723(displayed-code), "").trim("\n")
|
||||
}
|
||||
let attrs = (
|
||||
type: "py"
|
||||
)
|
||||
let default-val-terminal = true
|
||||
let default-val-worker = true
|
||||
let default-val-canvas = none
|
||||
if config.at("pygame", default: false) {
|
||||
default-val-terminal = false
|
||||
default-val-worker = false
|
||||
default-val-canvas = "canvas"
|
||||
}
|
||||
if config.at("terminal", default: default-val-terminal) {
|
||||
attrs.insert("terminal", "")
|
||||
}
|
||||
if config.at("worker", default: default-val-worker) {
|
||||
attrs.insert("worker", "")
|
||||
}
|
||||
let canvas-attr = config.at("canvas", default: default-val-canvas)
|
||||
if canvas-attr == false {
|
||||
canvas-attr = none
|
||||
}
|
||||
if canvas-attr == true {
|
||||
canvas-attr = "canvas"
|
||||
}
|
||||
if canvas-attr != none {
|
||||
attrs.insert("canvas", canvas-attr)
|
||||
|
||||
if not config.at("hide-code", default: false) {
|
||||
raw(
|
||||
displayed-code,
|
||||
block: true,
|
||||
lang: "python",
|
||||
align: it.align,
|
||||
syntaxes: it.syntaxes,
|
||||
theme: it.theme,
|
||||
tab-size: it.tab-size,
|
||||
)
|
||||
}
|
||||
assert(
|
||||
canvas-attr not in state-pyscript-canvas-ids.at(here()),
|
||||
message: (
|
||||
"Can not have multiple canvas with the same name. Note that SDL2 has issues working with canvas",
|
||||
"with an id different than 'canvas', meaning that it is unadvised to have more than one script",
|
||||
"using SDL2 by page.",
|
||||
"(tool.pyscript.pygame = true set the default value for the SDL2 canvas to 'canvas' instead of none)"
|
||||
).join(" ")
|
||||
)
|
||||
state-pyscript-canvas-ids.update(canvas-ids => canvas-ids + (canvas-attr,))
|
||||
}
|
||||
|
||||
html.elem(
|
||||
"script",
|
||||
attrs: attrs,
|
||||
script
|
||||
if pyscript-config != (:) {
|
||||
attrs.insert("config", json.encode(pyscript-config))
|
||||
}
|
||||
|
||||
let script = it.text;
|
||||
if config.at("repl", default: false) {
|
||||
script = "import code\n" + script + "\ncode.interact(banner='', local=globals())"
|
||||
}
|
||||
let displayed-code = it.text;
|
||||
if config.at("hide-meta", default: false) {
|
||||
displayed-code = displayed-code.replace(get-pep723(displayed-code), "").trim("\n")
|
||||
}
|
||||
|
||||
if not config.at("hide-code", default: false) {
|
||||
raw(
|
||||
displayed-code,
|
||||
block: true,
|
||||
lang: "python",
|
||||
align: it.align,
|
||||
syntaxes: it.syntaxes,
|
||||
theme: it.theme,
|
||||
tab-size: it.tab-size,
|
||||
)
|
||||
}
|
||||
|
||||
html.elem(
|
||||
"script",
|
||||
attrs: attrs,
|
||||
script
|
||||
)
|
||||
if canvas-attr != none {
|
||||
html.elem("canvas", attrs: ("id": canvas-attr))
|
||||
|
||||
let core-js-url = state-pyscript-data-list.final().at(state-pyscript-version.final()).core-js-url
|
||||
add-tag-in-head(
|
||||
html.script(
|
||||
type: "module",
|
||||
```
|
||||
import { hooks } from "<CORE-JS-URL>";
|
||||
hooks.main.onReady.add((wrap, script) => {
|
||||
if (script.hasAttribute("canvas")) {
|
||||
const target = script.getAttribute("canvas");
|
||||
const canvas = document.getElementById(target);
|
||||
wrap.interpreter.canvas.setCanvas2D(canvas);
|
||||
}
|
||||
});
|
||||
```.text.replace("<CORE-JS-URL>", core-js-url)
|
||||
)
|
||||
)
|
||||
}
|
||||
//raw(block: true, lang: "json", json.encode(metadata))
|
||||
}
|
||||
// also need pyscript hook to link canvas to pyodide:
|
||||
//
|
||||
// <script type="module">
|
||||
// // Pyscrypt has a py-game type that handle this, but it forces the interpreter to be
|
||||
// // from the cdn, which is quite meh.
|
||||
// // So I do the setup manually (https://docs.pyscript.net/2026.3.1/user-guide/pygame-ce/)
|
||||
// import { hooks } from "./pyscript/core.js";
|
||||
// hooks.main.onReady.add((wrap, script) => {
|
||||
// if (script.hasAttribute("canvas")) {
|
||||
// const target = script.getAttribute("canvas");
|
||||
// const canvas = document.getElementById(target);
|
||||
// wrap.interpreter.canvas.setCanvas2D(canvas);
|
||||
// }
|
||||
// });
|
||||
// </script>
|
||||
//raw(block: true, lang: "json", json.encode(metadata))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue