use pep723 to config pyscript

This commit is contained in:
Jean-Marie 'Histausse' Mineau 2026-05-31 23:33:50 +02:00
parent 7e8ee9d17e
commit 25cb9c6403
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
6 changed files with 149 additions and 54 deletions

View file

@ -4,7 +4,7 @@
#import "./nav_menu.typ": nav-menu, nav-menu-toggle
/// Make the body of the webpage
#let html_body(
#let html-body(
/// The visible header of the page
header: none,
/// The footer of the page

View file

@ -3,7 +3,7 @@
#import "./pyscript.typ": state-use-pyscript, state-pyscript-headers, state-pyscript-version
/// Generate the html <head> element for the page.
#let html_head(
#let html-head(
/// Page url,
url,
/// Title of the page

View file

@ -24,7 +24,7 @@
js-list.final().join("\n\n")
}
#let html_show(body) = {
#let html-show(body) = {
show raw: it => {
if it.lang == "raw-css" {
// remove code and add it to css style

View file

@ -1,8 +1,8 @@
#import "./html_head.typ": html_head
#import "./html_body.typ": html_body
#import "./html_utils.typ": html_show
#import "./html_head.typ": html-head
#import "./html_body.typ": html-body
#import "./html_utils.typ": html-show
#import "./summary.typ": summary, card-list
#import "./pyscript.typ": state-use-pyscript, state-pyscript-headers, state-pyscript-version, pyscript
#import "./pyscript.typ": state-use-pyscript, state-pyscript-headers, state-pyscript-version, pyscript-show
#import "./rss.typ": rss
#import "./icons.typ"
@ -56,9 +56,10 @@
state-pyscript-headers.update(x => pyscript-headers)
state-pyscript-version.update(x => pyscript-version)
}
show: html_show
show: html-show
show raw.where(block: true, lang: "python"): pyscript-show
html.html(lang: lang, {
html_head(
html-head(
url,
title,
icon: icon,
@ -70,7 +71,7 @@
stylesheets: stylesheets,
me-links: me-links
)
html_body(
html-body(
logo: logo,
header: header,
footer: footer,

View file

@ -2,26 +2,109 @@
#let state-pyscript-version = state("state-pyscript-version", none)
#let state-pyscript-headers = state("state-pyscript-headers", (:))
#let pyscript(
repl: false,
body
) = {
show raw.where(block: true, lang: "python"): it => {
#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)
it
let script = it.text;
if repl {
script = "import code\n" + script + "\ncode.interact(local=globals())"
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: (
type: "py",
terminal: "",
worker: "",
),
attrs: attrs,
script
)
} else {
it
}
body
//raw(block: true, lang: "json", json.encode(metadata))
}

View file

@ -74,35 +74,46 @@
#lorem(400)
#pyscript[
```python
for i in range(1, 16):
if i % 3 == 0 and i % 5 == 0:
print("plopliplop")
elif i % 3 == 0:
print("plop")
elif i % 5 == 0:
print("plip")
else:
print(i)
```
]
#pyscript(repl: true)[
```python
ret = []
for i in range(16, 31):
if i % 3 == 0 and i % 5 == 0:
ret.append("plopliplop")
elif i % 3 == 0:
ret.append("plop")
elif i % 5 == 0:
ret.append("plip")
else:
ret.append(i)
# >>> print(ret)
# [16, 17, 'plop', 19, 'plip', 'plop', 22, 23, 'plop', 'plip', 26, 'plop', 28, 29, 'plopliplop']
```
]
```python
# /// script
# [tool.pyscript]
# ///
n = ""
while not n.isnumeric():
n = input("enter a valid number: ")
for i in range(1, int(n) + 1):
if i % 3 == 0 and i % 5 == 0:
print("plopliplop")
elif i % 3 == 0:
print("plop")
elif i % 5 == 0:
print("plip")
else:
print(i)
```
```python
# /// script
# # requires-python = ">=3.11" # not supported yet
# dependencies = [
# "rich",
# ]
#
# [tool.pyscript]
# repl = true
# [tool.pyscript.files]
# "https://peps.python.org/api/peps.json" = "./peps.json"
# ///
import json
from rich.pretty import pprint
with open("./peps.json") as fd:
data = json.load(fd)
pprint([(k, v["title"]) for k, v in data.items()][:10])
# >>> print(data["723"]["title"])
# Inline script metadata
```
#summ.card