typst-web-template/lib/pyscript.typ
Jean-Marie 'Histausse' Mineau fe4b003971
work on pyscript/typst api
2026-06-06 18:04:47 +02:00

111 lines
3.5 KiB
Typst

#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-interpreters = state("state-pyscript-interpreters", (:))
#let state-pyscript-default-interpreter = state("state-pyscript-default-interpreter", none)
#let get-pep723(script) = {
script.find(regex(
//"(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
"(?m)^# /// script$\s(?P<content>(^#(| .*)$\s)+)^# ///$"
))
}
#let parse-pep723(script) = {
let metadata-section = get-pep723(script)
if metadata-section == none {
return none
}
let metadata-section = metadata-section.trim(
"# /// script\n"
).trim(
"# ///"
).replace(regex("(?m)^#(| )"), "")
toml(bytes(metadata-section))
}
// TODO DOCUMENT THIS!
#let pyscript-show(it) = {
let metadata = parse-pep723(it.text)
if metadata == none {
metadata = (:)
}
state-use-pyscript.update(x => true)
context {
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 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))
}
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
)
}
//raw(block: true, lang: "json", json.encode(metadata))
}