chore: initial commit
This commit is contained in:
198
src/lib.typ
Normal file
198
src/lib.typ
Normal file
@@ -0,0 +1,198 @@
|
||||
#import "@preview/showybox:2.0.3": showybox
|
||||
|
||||
#let init-registries(regs) = {
|
||||
[#metadata(regs) <fabulous-fedlex-init>]
|
||||
}
|
||||
|
||||
#let get-registries() = {
|
||||
return query(<fabulous-fedlex-init>).last().value
|
||||
}
|
||||
|
||||
#let min-box(min-width: 0pt, min-height: 0pt, body) = grid(
|
||||
columns: 2,
|
||||
align: center + horizon,
|
||||
v(min-height),
|
||||
grid(
|
||||
align: center + horizon,
|
||||
rows: 2,
|
||||
h(min-width),
|
||||
body
|
||||
)
|
||||
)
|
||||
|
||||
#let badge(regs, registry) = box(
|
||||
stroke: black,
|
||||
inset: 0.2em,
|
||||
radius: 0.3em,
|
||||
baseline: 30%,
|
||||
fill: regs.at(registry).color,
|
||||
min-box(
|
||||
strong(registry),
|
||||
min-width: 1.5em,
|
||||
min-height: 1.5em
|
||||
)
|
||||
)
|
||||
|
||||
#let parse-body(body, highlight: none) = {
|
||||
if type(body) == str {
|
||||
return eval("[" + body + "]")
|
||||
}
|
||||
if type(body) == array {
|
||||
let result = []
|
||||
for part in body {
|
||||
result += parse-body(part)
|
||||
}
|
||||
return result
|
||||
}
|
||||
if type(body) == dictionary {
|
||||
if body.type == "sup" {
|
||||
return super(parse-body(body.body))
|
||||
}
|
||||
if body.type == "sub" {
|
||||
return sub(parse-body(body.body))
|
||||
}
|
||||
if body.type == "enum" {
|
||||
let result = parse-body(body.intro) + linebreak()
|
||||
let cells = ()
|
||||
for (i, (num, item)) in body.items.enumerate() {
|
||||
let h = none
|
||||
if highlight != none and i == highlight.at(0, default: none) {
|
||||
h = highlight.slice(1)
|
||||
}
|
||||
let num-b = parse-body(num, highlight: h)
|
||||
let item-b = parse-body(item, highlight: h)
|
||||
|
||||
if h != none and h.len() == 0 {
|
||||
num-b = strong(num-b)
|
||||
item-b = strong(item-b)
|
||||
}
|
||||
cells.push(num-b)
|
||||
cells.push(item-b)
|
||||
}
|
||||
result += grid(
|
||||
columns: (2em, auto),
|
||||
column-gutter: 1em,
|
||||
row-gutter: 1em,
|
||||
..cells
|
||||
)
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Cites an article from the Swiss law
|
||||
/// - registry (str): registry id, must have been registered with `init-registries`
|
||||
/// - article-id (str): article id (e.g. "art_28")
|
||||
/// - par (none, int): optional paragraph to highlight. If not none, indicates the paragraph's number (as written in the law)
|
||||
/// - highlight (none, int, array): optional part to highlight. If not none, indicates the index or path of indices to the part ot highlight
|
||||
#let cite-law(
|
||||
registry,
|
||||
article-id,
|
||||
par: none,
|
||||
highlight: none,
|
||||
whole-path: false
|
||||
) = context {
|
||||
let regs = get-registries()
|
||||
|
||||
let highlight = if type(highlight) == int {
|
||||
(highlight,)
|
||||
} else {
|
||||
highlight
|
||||
}
|
||||
|
||||
assert(
|
||||
registry in regs,
|
||||
message: "Unknown registry '" + registry + "'. Available registries: " + regs.keys().map(r => "'" + r + "'").join(", ")
|
||||
)
|
||||
let reg = regs.at(registry).data
|
||||
|
||||
let article-id = article-id
|
||||
let article-idx = none
|
||||
if type(article-id) == array {
|
||||
(article-id, article-idx) = article-id
|
||||
}
|
||||
assert(
|
||||
article-id in reg.children.article,
|
||||
message: "Could not find article " + article-id + ". Existing ids: " + reg.children.article.keys().map(k => "'" + k + "'").join(", ")
|
||||
)
|
||||
|
||||
let article = reg.children.article.at(article-id)
|
||||
if article-idx != none {
|
||||
if type(article) != array and article-idx != 0 {
|
||||
panic("Provided an article index but there is only one")
|
||||
}
|
||||
article = article.at(article-idx)
|
||||
} else {
|
||||
if type(article) == array {
|
||||
article = article.first()
|
||||
//panic("Multiple articles with id " + article-id + ". Please provide an article index to choose (article-id, article-index)")
|
||||
}
|
||||
}
|
||||
|
||||
let path = ()
|
||||
let elmt = reg
|
||||
for (etype, eid) in article.path {
|
||||
if eid.starts-with("lvl_u") {
|
||||
continue
|
||||
}
|
||||
elmt = elmt.children.at(etype).at(eid)
|
||||
if whole-path {
|
||||
path.push(elmt.num.trim(":"))
|
||||
} else {
|
||||
path.push(elmt.heading.trim("."))
|
||||
}
|
||||
}
|
||||
|
||||
if not whole-path {
|
||||
path = (path.last(),)
|
||||
}
|
||||
path.push(article.num)
|
||||
|
||||
if par != none {
|
||||
path.push("Par. " + str(par))
|
||||
}
|
||||
|
||||
// Don't enum if only one paragraph
|
||||
let par = par
|
||||
if par == none and article.children.len() == 1 {
|
||||
par = 1
|
||||
}
|
||||
let body = if par == none {
|
||||
enum(
|
||||
spacing: 1em,
|
||||
..article.children.enumerate().map(((i, c)) => {
|
||||
let h = if highlight != none {
|
||||
if i == highlight.at(0, default: none) {
|
||||
highlight.slice(1)
|
||||
}
|
||||
}
|
||||
let r = parse-body(c.content, highlight: h)
|
||||
if h != none and h.len() == 0 {
|
||||
r = strong(r)
|
||||
}
|
||||
r
|
||||
})
|
||||
)
|
||||
} else {
|
||||
parse-body(article.children.at(par - 1).content, highlight: highlight)
|
||||
}
|
||||
|
||||
return showybox(
|
||||
title: badge(regs, registry) + h(0.4em) + path.join[ #sym.arrow.r ],
|
||||
frame: (
|
||||
title-color: gray.lighten(50%),
|
||||
body-color: gray.lighten(80%),
|
||||
border-color: gray.darken(30%)
|
||||
),
|
||||
title-style: (
|
||||
color: black,
|
||||
weight: "semibold",
|
||||
boxed-style: (:)
|
||||
),
|
||||
shadow: (
|
||||
offset: (x: 3pt, y: 5pt),
|
||||
color: gray
|
||||
),
|
||||
body
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user