-
-
Notifications
You must be signed in to change notification settings - Fork 992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple bibliographies #1097
Comments
we need it for PhD too |
I too have discovered that there can be only one |
Something like that (in latex) would be nice indeed:
|
One more vote for this! I got 80% of the way through rebuilding my CV in typst, which is a dream compared to LaTeX, but this might kill the effort :-/. I'm looking into manually building building bibliographies from the yaml, but I am not quite confident enough in the syntax to have high hopes there. An interim solution (though I'm not sure if it's actually easier to implement) would be to enable the
Maybe one could do something like
To get Some header[1] M. C. Woodruff, K. S. Bonham, et al., “Chronic inflammation, neutrophil activity, and [2] A. A. Schoenborn, S. M. Yannarell, et al., “Microclimate is a strong predictor of the native and Other Header[3] L. Tso, K. S. Bonham, A. Fishbein, S. Rowland, and V. Klepac-Ceraj, “Targeted high-resolution |
Is there a way to call hayagriva within typst? Something like my workaround is already possible with the hayagriva CLI:
|
I just hacked this together using the
gives |
OK, last one - this allows you to pass an array of citation keys, and pass a tag to include:
So you can do eg It also has some logic to add a star at the beginning if you have the tag "cofirst", or a dagger if you have the tag "corresponding" |
Just wanted to confirm. I am trying to reproduce my PhD thesis LaTex template in typst, but it was a necessity to have bibliographies for each chapter and numbering of references needed to start from 1 again. Would be really nice feature to have. |
Multiple bibliographies could meaning:
so what's means |
@ayoubelmhamdi I think you can already use multiple bibliography files by passing an array to |
I currently do this using the lua filters for multiple bibliographies in Quarto v1.3.
|
I wanted to add a page just with personal publications using the |
Is this being considered by the development team? Multiple bibliographies are a basic feature of any academic work. |
@bcdavasconcelos It will be supported in the future, but I can't yet say when. |
Hey all, Seeing as I want to also be able to write my PhD dissertation in Typst, I figured I might come up with a way to allow multiple bibliographies in Typst, by using a Typst library. With multiple bibliographies, I intend to mean that every chapter has their own set of references and citations throughout the manuscript can correctly link to the desired bibliography. https://github.com/jrihon/multi-bibs Hopefully this can be of use to someone else too, until the real deal comes along! |
It's great to have a bibliography on every chapter, but it seems that you control the user on how to organize our project,
|
As stated as a disclaimer and in the But hey, it's open source, feel free to change it yourself if you don't like it. I only figured out a relatively viable solution to a problem I have, and replying with a |
If you use IEEE reference format (or something similar that goes by number), this will work. The only downside is it won't merge adjacent references, but you can accommodate this by using #show bibliography: none
#bibliography("refs.bib")
// Keep track of all references, clearing every time a new heading is shown
#let section-refs = state("section-refs", ())
// Add bibliography references to the current section's state
#show ref: it => {
if it.element != none {
// Citing a document element like a figure, not a bib key
// So don't update refs
it
return
}
section-refs.update(old => {
if it.target not in old {
old.push(it.target)
}
old
})
locate(loc => {
let idx = section-refs.at(loc).position(el => el == it.target)
"[" + str(idx + 1) + "]"
})
}
// Print the "per-section" bibliography
#let section-bib() = locate(loc => {
let ref-counter = counter("section-refs")
ref-counter.update(1)
show regex("^\[(\d+)\]\s"): it => [
[#ref-counter.display()]
]
for target in section-refs.at(loc) {
block(cite(target, form: "full"))
ref-counter.step()
}
})
// Clear the previously stored references every time a level 1 heading
// is created.
#show heading.where(level: 1): it => {
section-refs.update(())
it
}
= First Section
My reference @plucked-string and another @plot
#section-bib()
= Second Section
Another reference @plucked-string-extensions @plot @plucked-string-extensions @plucked-string
#section-bib() |
One of the big utilities is being able to link the citation to the references, by making hyperlinks between them (link, label etc.) . What I am wondering here is the following : what if you are citing a specific reference, sourced from a single bibliography, and using that citation in multiple chapters, thereby creating the multiple instances of the same label. Wouldn't that create ambiguous hyperlinks? Typst will not compile if that is the case .. |
basically we need to reproduce the biblatex behaviour here https://www.overleaf.com/learn/latex/Questions/Creating_multiple_bibliographies_in_the_same_document |
we need 1 new concept refsection. Then a In more advanced version, the refsection should be able to nested. So at the end we can also have a global ref list. But I think it is ok to not support this option. Usually it is quite redundant. |
There could be some improvements:
I made some modification as //modified based on
//https://github.com/typst/typst/issues/1097#issuecomment-1928525350
#show bibliography: none
#bibliography("ref.bib")
// Keep track of all references, clearing every time a new heading is shown
#let section-refs = state("section-refs", ())
// Add bibliography references to the current section's state
#show ref: it => {
if it.element != none {
// Citing a document element like a figure, not a bib key
// So don't update refs
it
return
}
section-refs.update(old => {
if it.target not in old {
old.push(it.target)
}
old
})
//I think the following is how the reference index should be obtained correctly.
let get_ref_id(loc)={
//str(section-refs.at(loc).len())
str(section-refs.at(loc).position(x=>(x==it.target))+1)
}
locate(loc => {
"[" + get_ref_id(loc) + "]"
})
}
// Print the "per-section" bibliography
#let section-bib() = locate(loc => {
//https://github.com/typst/typst/issues/1097
let ref-counter = counter("section-refs")
ref-counter.update(1)
show regex("^\[(\d+)\]\s"): it => [
[#ref-counter.display()]
]
for target in section-refs.at(loc) {
block(cite(target, form: "full"))
ref-counter.step()
}
section-refs.update(())
}) |
I thought of this too; the reason it is separated is because people often see the code and ask "how can I modify it so that references are per-section", or "how can I incorporate a call to
You're absolutely right! I've updated my answer above to include these adjustments and verified with a new screenshot. Would you consider surrounding your code block inside a |
Sure, I have modified the code block. |
Just type https://docs.github.com/en/issues/tracking-your-work-with-issues/about-slash-commands |
(I fixed the formatting of the |
For the peace of mind, I add the newline above and below the code block. (The |
Does anyone know how to modify it for apa references and adding page numbers? I tried adjusting it but I can't figure out a way to make page numbers work. I currently cite works like this: #show bibliography: none
#bibliography("bibliography.yml", title: "Referenser", style: "apa")
// Keep track of all references, clearing every time a new heading is shown
#let section-refs = state("section-refs", ())
// Add bibliography references to the current section's state
#show ref: it => {
if it.element != none {
// Citing a document element like a figure, not a bib key
// So don't update refs
it
return
}
section-refs.update(old => {
if it.target not in old {
old.push(it.target)
}
old
})
locate(loc => {
let ref_pos = section-refs.at(loc).position(el => el == it.target)
let ref_target = section-refs.at(loc).at(ref_pos)
let apa_normal_citation = cite(ref_target, form: "normal")
apa_normal_citation
})
}
// Print the "per-section" bibliography
#let section-bib() = locate(loc => {
let ref-counter = counter("section-refs")
ref-counter.update(1)
show regex("^\[(\d+)\]\s"): it => [
[#ref-counter.display()]
]
for target in section-refs.at(loc) {
block(cite(target, form: "full"))
ref-counter.step()
}
})
// Clear the previously stored references every time a level 1 heading
// is created.
#show heading.where(level: 1): it => {
section-refs.update(())
it
} |
This would be very helpful for dissertations, where in some cases references and (own) publications are required to be listed separately. It would be wonderful if this worked as expected:
|
I want to flag up a repo with a minimal working example for an approach that basically solves this issue (at least for my needs). https://github.com/isometricneko/typst-example I'm not fully understanding how it works, but it allows me to see the bibliography in chapter-level and document-level previews, everything compiles as expected, and VS Code does not complain about using citations without a bibliography either. The basic idea (from the author) is:
So well done to @isometricneko ! The only situation I have found this approach creating problems is when using pandoc to transpile to .tex. |
Just to add a potential further requirement to this discussion: The dissertation template of our university requires that your own publications are prefixed by a "P" when cited. So in the document the ref to other publications would be shown as [Oth2023], while your own publication shows up as [PKue2023]. This is achieved using a relatively obscure biblatex hack, that changes the citation style based on which .bib file the citation comes from. Not sure if this should be considered as a "must have" feature, but would for sure be nice |
With Typst v0.12, I don't think the approach by isometricneko given above works anymore. |
I think it still works, but it's just meant to only handle one specific thing: it lets you render either a single chapter with its own bibliography, or the whole document with a single bibliography at the end. (which is unfortunately not my use case 😭) Simplifying it for 0.12, and even more since (at least in the example on Github) the chapter bibliography is always exactly where the chapter label was inserted, you get the following: // chapter.typ
#import "preamble.typ": *
...
#context bib_state.at(here()) (preamble and main stay the same) |
Here's a hack to provide chapter-level bibliographies with an author-date system: https://github.com/tshort/typst-multibib-hack It uses a combination of |
Hi, I've been loving typst ever since I started using it. Unfortunately I just got stuck on this issue. I have a requirement to split my bibliography into sections separating the kind of source such as
I already separated the sources into their respective Hayagriva files and referenced them in the bibliography paths array but there's no way to separate the files and prefix them with their respective heading. I'd love to see this feature be added in one way or another. For my specific use-case, it would probably be easiest if I could nest the paths as a mapping of Best, |
@Gabgobie I have a similar use case that I'll try to solve for my students (they have to have separate bibliography and list of AI prompts as mandated by the official guidelines). I haven't done it yet, but my plan is
Only thing I'm not sure about is whether references to prompts will correctly link to the list of prompts, and how reference numbers will be impacted; I guess I'll see... |
I had a thought (for the time being, as a workaround): why not compile hayagriva crate to Wasm and create as many bibliographies from as many files as you want? The only potential problem I see is the bibliography labels management. But I think it shouldn't be that hard to rewrite |
That could also be a (more convenient) option... I thought that Hayagriva didn't handle bib files, which is kinda silly since Typst can work with them... I'll investigate that option, thanks! |
Indeed, this is completely feasible to reimplement the Code in Typst to permit multiple bibliographyWhat is the idea :
Here is the basic code that do that and typeset basic bibliography for a book : // counter update for each citation (id of the citation)
#let cite_counter = counter("cite_counter")
// counter that update for each document (has to be increased in a template
// document for example) (id of the document)
#let global_counter = counter("global_counter")
#show cite : it => [
[#str(it.key)#if it.supplement != none [ #it.supplement]]
#metadata(str(it.key)) // Metadata of the key used by the citation
#label("cite_" + cite_counter.display() + "_" + global_counter.display())
#cite_counter.step()
// Here we have added a label connected to the citation metadata just to
// know what have been cited in the document
]
#show bibliography: it => {
if it.path.len() != 1 { assert(false, message: "Only accepts one bibliography file") }
let path = "examples/bib.yaml"
let file = yaml(path)
let done = ()
text(underline[*Bibliography* #linebreak()])
// function that take and author (ie. "Tom Paul Andersen")
// and turn it into a resume version T. P. Andersen
let resume_author(author) = {
let l = author.split(" ").filter(x=>x != "")
l.enumerate().map(((i, name)) =>
if i != l.len() - 1 [#name.slice(0,1).]
else {name}).join(" ")
}
// Go through all of the citation in the current document
// current document being the one identified with the number inside the
// counter "global_counter"
for i in range(cite_counter.get().at(0)) {
let lab = label("cite_" + str(i) + "_" + global_counter.display())
let pos = locate(lab).position()
let item = query(lab).at(0).value
if not item in done { // only write once each document (book, article...)
if item in file {
// specific code for typeset a basic book bibliography
// Other type of citation can be taken into account and it must be
// done by scripting here in typst
let book = file.at(item)
let a = book.author
let type_author = type(a)
let authors
if type(book.author) == array {
authors = book.author
} else if type(book.author) == str {
authors = book.author.split(",")
}
let resume_authors = authors.map(a => resume_author(a)).join(" & ")
[#h(0.8em) [#item]#h(0.5em)#resume_authors, #emph(book.title). #linebreak()]
} else {
assert(false, message:[#item not in #it.path.at(0)])
}
}
done.push(item)
}
} The main drawbacks are :
The main advantages are :
|
I though this was true but it is not. To be more precise, whatever the current This (stupid) show rule permits to have as much bibliography as needed anywhere : #show bibliography: it => [ Empty Bibliography ]
// .. some document However here the bibliography nows only put the content |
Where did "in typst <= 13.0" come from? |
Workaround for "multiple bibliographies" (as footnote)I'll use polylux as an example. You can certainly apply this workaround to whatever form of document you're writing. Step 1: Download and patch a style file, to hide citation numberingFirst you need to download a valid style file for typst I'll use Download this file and put it somewhere, and create a duplicate for patching. Let's name it In the duplicate style file, find the citation number and remove it. <bibliography entry-spacing="0" second-field-align="flush">
<layout>
<!-- Citation Number -->
- <text variable="citation-number" prefix="[" suffix="]"/>
<!-- Author(s) -->
<text macro="author" suffix=", "/> Step 2: Hack typst and your slide package, to show bibliography in footnote for each page#import "@preview/polylux:0.3.1": *
#set page(paper: "presentation-16-9")
// a wrapper to clear footnote counter for each page. preview image below.
#let slide = body => polylux-slide({
counter(footnote).update(0)
body
})
// optional. make #footnote looks more like #bibliography
#set footnote.entry(indent: 0pt, separator: none)
// ft stands for footnote. use whatever name you like
#let ft = lb => footnote(
text(
cite(
label(lb),
// vital. for showing the whole citation in footnote rather than only a number.
form: "full",
// use our patched CSL file, to hide numbering of bibliography, and only show numbering of footnote
style: "no_number.csl",
),
lang: "en",
region: "us",
),
numbering: "[1]", // this is the "real" numbering. use whatever you like.
)
#slide[
#lorem(40) #ft("some_ref") // our equivalent of @some_ref
]
#slide[
// if you need a "normal" bibliography
#bibliography(
"ref.bib",
// use our not-patched CSL file
style: "original.csl",
)
] PreviewNote that the footnote number starts from 1 again in the 2nd page. |
I just came up with this workaround for the CV use case. I used hayagriva to convert my bib-files to yml and then Typst's #show bibliography: none
#bibliography(("a.yml", "b.yml"))
#let display-bibliography(path) = {
for (lbl, _) in yaml(path) {
block[#cite(label(lbl), form: "full")]
}
}
== A
#display-bibliography("a.yml")
== B
#display-bibliography("b.yml") |
I am really excited to get to use typst, it looks great so far!
However, for larger documents it would be really helpful to have multiple bibliographies, e.g. to categorize publications into books, journals, etc. or to separate own prior publications from other peoples' works. This would be something like the
bibunit
orchapterbib
packages in LaTeX. Unfortunately I cannot assign labels, but the [proposed Label] would be feature requestThe text was updated successfully, but these errors were encountered: