initial version of better aligned bibliography

This commit is contained in:
2026-05-03 14:23:02 +02:00
parent 11a105fec7
commit 177eff9ea6
7 changed files with 274 additions and 110 deletions
+209 -23
View File
@@ -1,27 +1,213 @@
#import "@preview/alexandria:0.2.2": *
#import "@preview/alexandria:0.2.2": alexandria, get-bibliography, load-bibliography
= Spis literatury
// Global state
#let used-refs = state("used-refs", ())
== Książki
#bibliographyx(
"Bibliography/Books.bib",
prefix: "book-",
title: none,
style: "ieee",
)
// 1. Analizes and sets up the document
#let bib-setup(body) = {
show: alexandria(prefix: "cite:", read: path => read(path))
== Artykuły
#bibliographyx(
"Bibliography/Articles.bib",
prefix: "article-",
title: none,
style: "ieee",
)
// Searching for references in document
show ref: it => {
let target = str(it.target)
if target.starts-with("cite:") {
let key = target.slice(5)
used-refs.update(arr => if key not in arr { arr + (key,) } else { arr })
context {
let cites = used-refs.final()
let bib = get-bibliography("cite:")
let get-type(k) = {
let e = bib.references.find(x => x.key == k)
if e != none { lower(e.details.at("type", default: "")) } else { "" }
}
let is-book(t) = t == "book"
let is-article(t) = t == "article" or t == "paper-conference" or t == "inproceedings"
let is-other(t) = not is-book(t) and not is-article(t)
== Źródła internetowe i inne
#bibliographyx(
"Bibliography/Others.bib",
prefix: "other-",
title: none,
style: "ieee",
)
let books = cites.filter(k => is-book(get-type(k)))
let articles = cites.filter(k => is-article(get-type(k)))
let others = cites.filter(k => is-other(get-type(k)))
let sorted = books + articles + others
let idx = sorted.position(k => k == key)
if idx != none { link(it.target, [\[#(idx + 1)\]]) } else { [\[?\]] }
}
} else { it }
}
body
}
// 2. Bibliography rendering
#let render-bib() = {
load-bibliography("Bibliography.bib", prefix: "cite:", full: true, style: "ieee")
heading(level: 1)[Spis literatury]
v(1em)
context {
let cites = used-refs.final()
if cites.len() > 0 {
let bib = get-bibliography("cite:")
let get-entry(k) = bib.references.find(e => e.key == k)
// custom implementation adapting the ZUT's formatting
let format-custom(entry) = {
let d = entry.details
let entry-type = lower(d.at("type", default: ""))
let format-author(a) = {
if type(a) == dictionary {
let parts = ()
if "given" in a { parts.push(str(a.given)) }
if "family" in a { parts.push(str(a.family)) }
if parts.len() > 0 { return parts.join(" ") }
if "name" in a { return str(a.name) }
return ""
} else {
let s = str(a)
let parts = s.split(",")
if parts.len() == 2 { return parts.at(1).trim() + " " + parts.at(0).trim() }
return s
}
}
let raw-auth = d.at("author", default: ())
let author-list = if type(raw-auth) == array {
raw-auth.map(format-author)
} else if raw-auth != none and raw-auth != "" {
(format-author(raw-auth),)
} else { () }
let authors = if author-list.len() > 1 {
author-list.slice(0, -1).join(", ") + " i " + author-list.last()
} else if author-list.len() == 1 { author-list.first() } else { "" }
let get-val(..keys) = {
let extract(obj, k) = {
if type(obj) != dictionary { return none }
let v = obj.at(k, default: none)
if v == none { return none }
if type(v) == str { return v }
if type(v) in (int, float) { return str(v) }
if type(v) == array { return v.filter(x => type(x) in (str, int, float)).map(x => str(x)).join(", ") }
if type(v) == dictionary {
if "isbn" in v { return str(v.isbn) }
if "value" in v { return str(v.value) }
if "name" in v { return str(v.name) }
if "text" in v { return str(v.text) }
return ""
}
return ""
}
for k in keys.pos() {
let res = extract(d, k)
if res == none and "parent" in d { res = extract(d.parent, k) }
if res != none and res != "" { return res }
}
return ""
}
let y = ""
let m = ""
let date-val = d.at("date", default: none)
if type(date-val) == dictionary {
y = str(date-val.at("year", default: ""))
m = str(date-val.at("month", default: ""))
} else if date-val != none { y = str(date-val) }
if y == "" { y = get-val("year") }
if m == "" { m = get-val("month") }
if m != "" {
if m.match(regex("^\d+$")) != none {
let idx = int(m)
let months = (
"",
"sty.",
"lut.",
"mar.",
"kwi.",
"maj",
"cze.",
"lip.",
"sie.",
"wrz.",
"paź.",
"lis.",
"gru.",
)
if idx >= 1 and idx <= 12 { m = months.at(idx) }
}
}
let year = if m != "" { m + y } else { y }
let title-txt = get-val("title")
let series = get-val("collection-title", "series")
let pub-place = get-val("location", "address", "publisher-place")
let pub = get-val("publisher")
let edition = get-val("edition")
let volume = get-val("volume")
let pages = get-val("page-range", "pages").replace("--", "").replace("-", "")
let isbn = get-val("isbn", "ISBN", "serial-number", "number")
let issue = get-val("issue", "number")
let url = get-val("url")
if entry-type == "book" [
#authors. #emph(title-txt).
#if edition != "" { if edition.match(regex("^\d+$")) != none [#edition wyd. ] else [#edition. ] }
#if volume != "" [T. #volume. ]
#if series != "" [#series. ]
#if pub-place != "" [#pub-place: ]
#if pub != "" [#pub, ]
#year#if pages != "" [, s. #pages].
#if isbn != "" [ isbn: #isbn.]
] else if entry-type == "article" or entry-type == "paper-conference" [
#authors. #title-txt”. W:#if volume != "" or issue != "" [ #volume#if issue != "" [.#issue]] (#year)#if pages != "" [, s. #pages].
] else [
#authors. #emph(title-txt).
#if url != "" [ URL: #link(url)[#raw(url)].]
]
}
let get-type(k) = {
let e = get-entry(k)
if e != none { lower(e.details.at("type", default: "")) } else { "" }
}
let is-book(t) = t == "book"
let is-article(t) = t == "article" or t == "paper-conference" or t == "inproceedings"
let is-other(t) = not is-book(t) and not is-article(t)
let render-group(title, keys, start-idx) = {
if keys.len() > 0 [
== #title
#grid(
columns: (auto, 1fr),
column-gutter: 0.65em,
row-gutter: 1em,
..keys
.enumerate()
.map(((i, k)) => {
let entry = get-entry(k)
if entry == none { return () }
let num = start-idx + i + 1
// Pamiętaj: musisz użyć format-custom, który wkleiłeś wyżej!
([\[#num\]], [#format-custom(entry)#label("cite:" + k)])
})
.flatten()
)
#v(1em)
]
}
let books = cites.filter(k => is-book(get-type(k)))
let articles = cites.filter(k => is-article(get-type(k)))
let others = cites.filter(k => is-other(get-type(k)))
// last parameter is start idx
render-group("Książki", books, 0)
render-group("Artykuły", articles, books.len())
render-group("Źródła internetowe i inne", others, books.len() + articles.len())
}
}
}