typst-web-template/lib/pyscript.typ
Jean-Marie 'Histausse' Mineau 25cb9c6403
use pep723 to config pyscript
2026-05-31 23:33:50 +02:00

110 lines
2.9 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 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 = if it.lang != "python" {
none
} else {
parse-pep723(it.text)
}
if metadata != none and "pyscript" in metadata.at(
"tool", default: (:)
) and metadata.at(
"tool", default: (:)
).at(
"pyscript", default: (:)
).at(
"run", default: true
) {
state-use-pyscript.update(x => true)
let config = metadata.at("tool", default: (:)).at("pyscript", default: (:))
let pyscript-config = (:)
if "dependencies" in metadata {
pyscript-config.insert("packages", metadata.at("dependencies"))
}
if "files" in config {
pyscript-config.insert("files", config.at("files"))
}
let attrs = (
type: "py"
)
if pyscript-config != (:) {
attrs.insert("config", json.encode(pyscript-config))
}
if true {
attrs.insert("terminal", "")
attrs.insert("worker", "")
}
let script = it.text;
if config.at("repl", default: false) {
script = "import code\n" + script + "\ncode.interact(banner='', local=globals())"
}
if not config.at("hide-code", default: false) { //and not config.at("hide-meta", default: false) {
it
}
/* Don't work, will require some way of unsetting show rule of something
} else if not config.at("hide-code", default: false) and config.at("hide-meta", default: false) {
let meta-lines = get-pep723(it.text).split("\n")
let code-lines = it.text.split("\n")
let meta-line-0 = none
for i in range(code-lines.len()) {
let match = true
for j in range(meta-lines.len()) {
if (i + j) >= code-lines.len() or meta-lines.at(j) != code-lines.at(i + j) {
match = false
break
}
if match {
meta-line-0 = i
}
}
}
show raw.line: it => {
if meta-line-0 == none {
it
} else if it.number > meta-line-0 and it.number <= meta-line-0 + meta-lines.len() {
none
} else {
it
}
}
it
}*/
html.elem(
"script",
attrs: attrs,
script
)
} else {
it
}
//raw(block: true, lang: "json", json.encode(metadata))
}