Skip to content
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

Open
mareikep opened this issue May 4, 2023 · 43 comments
Open

Multiple bibliographies #1097

mareikep opened this issue May 4, 2023 · 43 comments
Labels
bibliography Anything about citations and bibliographies. feature request New feature or request

Comments

@mareikep
Copy link

mareikep commented May 4, 2023

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 or chapterbib packages in LaTeX. Unfortunately I cannot assign labels, but the [proposed Label] would be feature request

@rpitasky rpitasky added feature request New feature or request bibliography Anything about citations and bibliographies. labels May 5, 2023
@ayoubelmhamdi
Copy link

we need it for PhD too

@wlupton
Copy link

wlupton commented Jul 3, 2023

I too have discovered that there can be only one #bibliography, but its path argument can be an array, so you can include multiple bibliographies. However, there can't be any duplicate keys (if there are duplicate keys, I think it would probably make sense for later definitions to override earlier ones; then you could list the "most definitive" bibliographies last).

@HROMANO
Copy link

HROMANO commented Jul 12, 2023

Something like that (in latex) would be nice indeed:

        \printbibliography[heading=subbibliography, title={Articles}, type=article]
        \printbibliography[heading=subbibliography, title={Reports}, nottype=online, nottype=article]
        \printbibliography[heading=subbibliography, title={Internet}, type=online]

@kescobo
Copy link

kescobo commented Jul 15, 2023

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 style of a #cite call to be the full reference. In other words, instead of

== Some header

@label1
@label2

== Other header

@label3

#bibliography[...]

Giving
image

Maybe one could do something like

== Some header

#cite("label1", "label2", style: "full")

== Other Header

#cite("label3", style: "full")

To get

Some header

[1] M. C. Woodruff, K. S. Bonham, et al., “Chronic inflammation, neutrophil activity, and
autoreactivity splits long Covid,” Nature Commun., vol. 14, no. 1, Jul. 2023, doi: 10.1038/
s41467-023-40012-7. [Online]. Available: https://doi.org/10.1038/s41467-023-40012-7

[2] A. A. Schoenborn, S. M. Yannarell, et al., “Microclimate is a strong predictor of the native and
invasive plant-associated soil microbiome on san cristóbal island, galápagos archipelago,”
Environmental Microbiology, Mar. 2023, doi: 10.1111/1462-2920.16361. [Online]. Available:
https://doi.org/10.1111/1462-2920.16361

Other Header

[3] L. Tso, K. S. Bonham, A. Fishbein, S. Rowland, and V. Klepac-Ceraj, “Targeted high-resolution
taxonomic identification of Bifidobacterium longum subsp. infantis using human milk
oligosaccharide metabolizing genes,” Nutrients, vol. 13, no. 8, p. 2833, Aug. 2021, doi: 10.3390/
nu13082833. [Online]. Available: https://doi.org/10.3390/nu13082833

@kescobo
Copy link

kescobo commented Jul 15, 2023

Is there a way to call hayagriva within typst? Something like my workaround is already possible with the hayagriva CLI:

❯ hayagriva testcite.yaml reference
Joe Schmoe, and Jane Doe. 2042. “This Is a Really Fascinating Title.” FEBS Journal. https://doi.org/10.1111/j.1742-4658.2010.07623.x.
Me Myself, and And Eye. 2001. “Boring Title,” https://doi.org/10.2222/j.x.

❯ hayagriva testcite.yaml reference --select "!misc"
Joe Schmoe, and Jane Doe. 2042. “This Is a Really Fascinating Title.” FEBS Journal. https://doi.org/10.1111/j.1742-4658.2010.07623.x.

❯ hayagriva testcite.yaml reference --select "!misc" --style ieee
Joe Schmoe, and Jane Doe, “This is a really fascinating title,” FEBS J., 2042, doi: 10.1111/j.1742-4658.2010.07623.x. [Online]. Available: https://doi.org/10.1111/j.1742-4658.2010.07623.x

@kescobo
Copy link

kescobo commented Jul 16, 2023

I just hacked this together using the #yaml function:

#let refs(contents) = {
    for (tag, fields) in contents {
        let auth_n = fields.author.len()
        let auths = ()
        if auth_n > 4 {
            auths = fields.author.slice(0, count:4)
            [#auths.join(", ") _et. al._]
        } else {
            auths = fields.author
            auths.join(", ", last: " and ")
        }
        
        [, "#fields.title.value"]
        [. #emph(fields.parent.at(0).title)]
        [. (#fields.date)]
        [ doi: #link(fields.url, fields.doi)]
        linebreak()
    }
}

#refs(
  yaml("citations.yaml")
)

gives

image

@kescobo
Copy link

kescobo commented Jul 16, 2023

OK, last one - this allows you to pass an array of citation keys, and pass a tag to include:

#let refs(file, entries: (), tag: none) = {
    if entries.len() == 0 {
        entries = yaml(file).keys()
    }

    for (entry, fields) in yaml(file) {
        if entry not in entries {
            continue
        }
        if not tag == none {
            if "tags" not in fields or tag not in fields.tags {
                continue
            }
        }

        if "tags" in fields and "cofirst" in fields.tags {
            [\* ]
        }

        if "tags" in fields and "corresponding" in fields.tags {
            [#sym.dagger ]
        }

        let auth_n = fields.author.len()
        let auths = ()
        if auth_n > 4 {
            auths = fields.author.slice(0, count:4)
            [#auths.join(", ") _et. al._]
        } else {
            auths = fields.author
            auths.join(", ", last: " and ")
        }
        
        [, "#eval("[" + fields.title.value + "]")"]
        [. #emph(fields.parent.at(0).title)]
        [. (#fields.date)]
        [ doi: #link(fields.url, fields.doi)]
        linebreak()
    }
}

So you can do eg #refs("citations.yaml", tag: "preprint") or #refs("citations.yaml", entries: ("entry1", "entry2")) (or a combination.

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"

@camattelaer
Copy link

we need it for PhD too

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.

@ayoubelmhamdi
Copy link

ayoubelmhamdi commented Jul 27, 2023

Multiple bibliographies could meaning:

  • the using of the different files.
  • or by having a bibliography for each chapter with reference numbers that start from 1 in each chapter

so what's means Multiple bibliographies ?

@kescobo
Copy link

kescobo commented Jul 28, 2023

@ayoubelmhamdi I think you can already use multiple bibliography files by passing an array to #bibliography.

@jadebarclay
Copy link

I currently do this using the lua filters for multiple bibliographies in Quarto v1.3.
I haven't tested them in Typst/Quarto v1.4 yet, but I hope they'll work here, too.

@akshaybabloo
Copy link

I wanted to add a page just with personal publications using the full: true and adding a multiple bib files as an array will list out everything that is not part of my publications.

@bcdavasconcelos
Copy link

Is this being considered by the development team? Multiple bibliographies are a basic feature of any academic work.

@laurmaedje
Copy link
Member

@bcdavasconcelos It will be supported in the future, but I can't yet say when.

@jrihon
Copy link

jrihon commented Feb 2, 2024

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.
The project is still very young, but works relatively well. It only supports rudimentary APA style citation, but one can easily add their preferred citation style in the library itself.

https://github.com/jrihon/multi-bibs

Hopefully this can be of use to someone else too, until the real deal comes along!

@ayoubelmhamdi
Copy link

ayoubelmhamdi commented Feb 3, 2024

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. The project is still very young, but works relatively well. It only supports rudimentary APA style citation, but one can easily add their preferred citation style in the library itself.

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, that's a bad idea.

rootdirectory/ 
    - chapters/
        - CHAPTER_X/
            mod.typ, bibliography_X.yml
        - CHAPTER_Y/
            mod.typ, bibliography_Y.yml
    - lib/
        multi-bibs.typ

@jrihon
Copy link

jrihon commented Feb 3, 2024

It's great to have a bibliography on every chapter, but it seems that you control the user on how to organize our project, that's a bad idea.

rootdirectory/ 
    - chapters/
        - CHAPTER_X/
            mod.typ, bibliography_X.yml
        - CHAPTER_Y/
            mod.typ, bibliography_Y.yml
    - lib/
        multi-bibs.typ

As stated as a disclaimer and in the TODO section, I am very much aware of the rigidity of the project. One of the key problems is that the #yaml() function infers a path to your .yml file and prepends it to the given path. I've figured out that by passing an absolute path to the .yml directly, typst prepend the path with the path to the root directory of the project. This Path inference is generally quite annoying, but I understand its place in the Typst atm. This path inference is also very variable and changes on the type of path you pass into the argument of the function, hence its fickle nature. That is why, for now, I decided to make a bit rigid, just to get it working.

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 that's a bad idea to a glaring issue I acknowledged myself is just not productive.

@ntjess
Copy link

ntjess commented Feb 5, 2024

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 cite rules instead of ref rules.

#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()

image

@jrihon
Copy link

jrihon commented Feb 6, 2024

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 cite rules instead of ref rules.

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 ..
I ran into this issue, so I created unique labels in the Referencelist, by splitting the bibliography per chapter for my specific issue.

@braindevices
Copy link

basically we need to reproduce the biblatex behaviour here https://www.overleaf.com/learn/latex/Questions/Creating_multiple_bibliographies_in_the_same_document

@braindevices
Copy link

we need 1 new concept refsection. Then a #bibliography() only print ref list inside the refsection. We must to have this to make typst really useful. If I only write a few page document, latex is not that slow.

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.

@astrojhgu
Copy link

astrojhgu commented Feb 17, 2024

#show heading.where(level: 1): it => {
  section-refs.update(())
  it
}

There could be some improvements:

  1. the section-refs.update action can be merged into each section-bib() function.
  2. There seems to be a bug, the ref id cannot be obtained by using len, rather, it should be obtained by .position.

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(())
})

@ntjess
Copy link

ntjess commented Feb 19, 2024

@astrojhgu

the section-refs.update action can be merged into each section-bib() function

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 section-bib automatically"? This type of answer plants the seed of how to make your own adjustments as needed (in our case, a small introduction of other concepts beyond the answer itself, like tying into other show rules).

There seems to be a bug

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 <details> ... </details> wrapper now that the code block is updated? It will help ensure there is just one community-maintained snippet.

@astrojhgu
Copy link

astrojhgu commented Feb 21, 2024

Would you consider surrounding your code block inside a <details> ... </details> wrapper now that the code block is updated? It will help ensure there is just one community-maintained snippet.

Sure, I have modified the code block.
(not sure if I did it correctly, as I'm not very familiar with the <details /> tag).

@Andrew15-5
Copy link
Contributor

Sure, I have modified the code block. (not sure if I did it correctly, as I'm not very familiar with the <details /> tag).

Just type /d at the start of a new line and then press Enter (in the web version of GitHub). It's called a "slash command". For convenience.

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/organizing-information-with-collapsed-sections

https://docs.github.com/en/issues/tracking-your-work-with-issues/about-slash-commands

@laurmaedje
Copy link
Member

(I fixed the formatting of the <details /> block. It needs a newline between <details> and the code block.)

@Andrew15-5
Copy link
Contributor

For the peace of mind, I add the newline above and below the code block.

(The /details slash command also adds an unnecessary in my opinion p tag and a whitespace after </details>, so it's kinda useful, and I hate it at the same time.)

@cascading-jox
Copy link

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 cite rules instead of ref rules.

#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()

image

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: @cognitive-neuroscience[s.~110]

#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
}

@oaken-source
Copy link

oaken-source commented Jun 12, 2024

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:

#bibliography("references.bib")
#pagebreak(weak: true)
#bibliography("publications.bib", full: true, title: "List of Publications")

@jordantgh
Copy link

jordantgh commented Jun 15, 2024

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:

you can use state to store the #bibliography for each of the subfiles and update the value of the state to none in the main file

So well done to @isometricneko !

The only situation I have found this approach creating problems is when using pandoc to transpile to .tex.

@AKuederle
Copy link

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

@tshort
Copy link

tshort commented Oct 30, 2024

With Typst v0.12, I don't think the approach by isometricneko given above works anymore.

@SillyFreak
Copy link
Contributor

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)

@tshort
Copy link

tshort commented Dec 17, 2024

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 typst query and Pandoc to generate the bibliographies for each chapter.

@Gabgobie
Copy link

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

  • internet
  • newspaper
  • books

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 section_title -> array(path(s))

Best,
Gab

@SillyFreak
Copy link
Contributor

SillyFreak commented Dec 19, 2024

@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

  • require separate biblography files, like you already have
  • require that only prompts used in the thesis are present in the bib file
  • use typst query to find where the list of prompts needs to go, page-wise
  • use typst query to find how many pages the list of prompts takes
  • separately compile thesis and list of prompts (latter using the full option) with correct page numbers
  • stitch together the PDFs
    Maybe this is an approach that you can also use, I'll report back once it works

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...

@Andrew15-5
Copy link
Contributor

Andrew15-5 commented Dec 19, 2024

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 bibliography() logic in Typst.

@SillyFreak
Copy link
Contributor

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!

@pauladam94
Copy link

pauladam94 commented Dec 26, 2024

@Andrew15-5

It shouldn't be that hard to rewrite bibliography() logic in Typst.

Indeed, this is completely feasible to reimplement the bibliography function. In this repository, you can see a showcase of a solution that permits multiple bibliography : https://github.com/pauladam94/multi-bib.

Code in Typst to permit multiple bibliography

What is the idea :

  • override cite : put metadata + link on every citation with a string that identifies the citation. The string in an identifier to every citation and contains the number of the document (the global_counter)(that needs to be updated at the beginning of every document).
  • override bibliography and going through all the links that have the id of the current document (current chapter for example). Since the bibliography is overridden there is absolutely not issue about having multiple calls to bibliogography in different files that are imported in the same file.

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 :

  • I have parsed by hand the bibliography (so right now this only works for yaml bibliography).
  • This technique needs to reimplement every citation style by hand (or just what is needed for a given document)
  • linking to the right citation does not work anymore I think.

The main advantages are :

  • this is an easy way to script the way you want the documentation to look (and the citation too)
  • this works, meaning multiple files with bibliographies can work together and at the end there is multiple documentation at the end of the file.
  • this is using typst syntax for citing and the bibliography function so this can be used right now in any document without much changes.

@pauladam94
Copy link

pauladam94 commented Dec 26, 2024

@wlupton

I too have discovered that there can be only one #bibliography

I though this was true but it is not. To be more precise, whatever the current bibliography function put in the document cannot be twice present in the document (in typst <= 12.0). However if you override (with a show rule) the behavior of the bibliography function, then you can do whatever you want. And if you override in a way where the content of the previous bibliography is not even in the document, then you call multiple times the bibliography function.

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 Empty Bibliography in the document.

@Andrew15-5
Copy link
Contributor

Where did "in typst <= 13.0" come from?

@VVsxmja
Copy link

VVsxmja commented Jan 2, 2025

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 numbering

First you need to download a valid style file for typst #bibliography, YAML or CSL or whatever.

I'll use ieee.csl as an example. Let's download and name it original.csl.

Download this file and put it somewhere, and create a duplicate for patching. Let's name it no_number.csl.

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",
  )
]

Preview

Note that the footnote number starts from 1 again in the 2nd page.

preview

@astahfrom
Copy link

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 yaml function to call cite repeatedly instead of bibliography. It's probably not too hard to sort the entries before looping over them, if you need to. Typst 0.12.0.

#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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bibliography Anything about citations and bibliographies. feature request New feature or request
Projects
None yet
Development

No branches or pull requests