Organize your scientific publications with BibTeX in Pelican. The package is based on Vlad's pelican-bibtex. The current version is backward compatible and can replace the pelican-bibtex install of your current project.
pelican_bib requires pybtex.
$ pip install pybtexYou can either install Pelican Bib using pip (currently on version 0.2.7 ) or as a submodule:
$ pip install pelican-bibAdd the plugin to the PLUGINS variable (in your Pelican config, e.g. pelicanconf.py):
PLUGINS = ['pelican_bib', ...]In your Pelican site:
$ mkdir plugins
$ git submodule add https://github.com/scheunemann/pelican-bib plugins/pelican-bibRegister the plugin folder and add the plugin to the PLUGINS variable (in your Pelican config, e.g. pelicanconf.py):
PLUGIN_PATHS = ['plugins/pelican-bib', ...]
PLUGINS = ['pelican_bib', ...]This plugin reads a user-specified BibTeX file and populates the context with a list of publications, ready to be used in your Jinja2 template.
Configuration is simply: You can embed a list of publications via directive or a page template.
Use the bibliography directive in your reST files and pass the path (or multiple paths)
to the bibliography file (relative to current document or absolute to Pelican content path).
.. bibliography:: pubs.bib
.. bibliography:: /pages/publications/pubs.bib
.. bibliography:: pubs1.bib pubs2.bib pubs3.bibor provide BibTeX entries as content.
.. bibliography::
@inproceedings{doe_conf_2020,
author={Doe, Jane and Ordinary, Joe},
title={The Title of the Work},
booktitle={Proceedings of the Conference (CONF)},
year={2020}, pages={to appear}
}Both input methods (path[s] and content) can be combined - entries will then be merged.
You will be able to use the variable publications in your template.
By default, a template with the name "bibliography" is rendered.
Place the following template file as bibliography.html in your Pelican template folder
(e.g. content/templates). For extended templates see example templates.
<ul>
{% for publication in publications %}
<li id="{{ publication.key }}">{{ publication.text }}</li>
{% endfor %}
</ul>Alternatively, you can pass a template name via :template: parameter to use a specific template file (e.g. "publications-by-year.html"):
.. bibliography:: pubs.bib
:template: publications-by-yearIf you set the parameter PUBLICATIONS_SRC in your Pelican configuration file (e.g. pelicanconf.py)
PUBLICATIONS_SRC = 'content/pubs.bib'
PUBLICATIONS_SRC = ['content/pubs1.bib', 'content/pubs2.bib', 'content/pubs3.bib']you will be able to find the publications variable in all your Jinja2 templates.
To generate a page displaying the publications with one of the methods below, you need to add a template file and a page.
1.) place the template file as publications.html in your Pelican template folder
(e.g. content/templates and add it as direct template to your webpage.
Add in your pelicanconf.py:
THEME_TEMPLATES_OVERRIDES.append('templates')2.) Create a page in your page folder, e.g., 'content/pages/publications.rst' with the following metadata in your content:
Publications
############
:template: publicationsThe publications variable in your Jinja2 templates is a list of dictionaries with the following keys:
-
keyis the BibTeX key (identifier) of the entry. -
yearis the year when the entry was published. Useful for grouping by year in templates using Jinja'sgroupby -
textis the HTML formatted entry, generated bypybtex. -
bibtexis a string containing BibTeX code for the entry, useful to make it available to people who want to cite your work. -
pdf,slides,poster: in your BibTeX file, you can add these special fields, for example:@article{ foo13 ... pdf = {/papers/foo13.pdf}, slides = {/slides/foo13.html} }
This plugin will take all defined fields and make them available in the template.
If a field mentioned above is not defined, the tuple field will be None.
Other field types can only be accessed if they are also defined in the corresponding BibTeX entry.
With the help of the options parameter of the bibliography directive, you can pass additional values to the template.
For example
.. bibliography:: pubs.bib
:options: { 'groupby_attribute': 'year' }would make the variable groupby_attribute available in the template (see example templates).
If you set the configuration variable PUBLICATIONS_DECORATE_HTML to true, the parts of a HTML formatted entry generated by pybtex (e.g. title, author list, volume & series) will be surrounded by span tags with a corresponding class attribute.
PUBLICATIONS_DECORATE_HTML = TrueInstead of rendering the following HTML for a bibliography entry (default)
Jane Doe, and Joe Ordinary.
<span class="bibtex-protected">The Title of the Work</span>.
In <em>Proceedings of the Conference (CONF)</em>, to appear. 2020.the rendered HTML would look like this:
<span class="bib-inproceedings">
<span class="bib-names">Jane Doe, and Joe Ordinary.</span>
<span class="bib-title"><span class="bibtex-protected">The Title of the Work</span>.</span>
In <span class="bib-btitle"><em>Proceedings of the Conference (CONF)</em></span>, to appear.
<span class="bib-address_organization_publisher_date">2020.</span>
</span>Available CSS classes are (according to the format_* and get_*_template function names of
pybtex.style.formatting.unsrt):
bib-names, bib-article, bib-author_or_editor, bib-editor, bib-volume_and_series, bib-chapter_and_pages, bib-edition, bib-title, bib-btitle, bib-address_organization_publisher_date, bib-book, bib-booklet, bib-inbook, bib-incollection, bib-inproceedings, bib-manual, bib-mastersthesis, bib-misc, bib-phdthesis, bib-proceedings, bib-techreport, bib-unpublished, bib-web_refs, bib-url, bib-pubmed, bib-doi, bib-eprint.
Each bibliography is wrapped in a div-container with the default classes "bibliography" and the bibliography file names. Use the class option of the bibliography directive to change the class attribute name:
.. bibliography:: pubs.bib
:class: my-custom-bibYou can modify arguments passed to the pybtex style that is used for rendering HTML.
Set the variable PUBLICATIONS_STYLE_ARGS in your pelicanconf.py to set default values
for the named arguments passed to the used
pybtex style
(available values).
PUBLICATIONS_STYLE_ARGS = {
'sorting_style': 'author_year_title',
'abbreviate_names': True,
'name_style': 'lastfirst' }You can override the pybtex style arguments in a bibliography directive as follows:
.. bibliography:: pubs.bib
:pybtex_style_args: { 'sorting_style': 'author_year_title', 'abbreviate_names': True, 'name_style': 'lastfirst' }or just use the predifined options:
sorting_style. values:author_year_title(default) ornone(sorting exactly as in the bib file)abbreviate_names. values:TrueorFalse(default)name_style. values:plain(default) orlastfirst
.. bibliography:: pubs.bib
:sorting_style: author_year_title
:abbreviate_names: True
:name_style: lastfirstYou can add an extra field to each BibTeX entry. This value of that field is a comma separated list.
These values will become the keys of a list publications_lists containing the associated BibTeX entries in your template.
For example, if you want to associate an entry with two different tags (foo-tag, bar-tag),
you add the following field to the bib entry:
@article{
...
tags = {foo-tag, bar-tag}
}In your pelicanconf.py you'll need to set:
PUBLICATIONS_SPLIT_BY = 'tags'In your template you can then access these lists with the variables publications_lists['foo-tag'] and publications_lists['bar-tag'].
You can use the filter_tag option of the bibliography directive to only render publications containing the given tag:
.. bibliography:: pubs.bib
:filter_tag: foo-tagIf you want to assign all untagged entries (i.e. entries without
the field defined in PUBLICATIONS_SPLIT_BY) to a tag named others, set:
PUBLICATIONS_UNTAGGED_TITLE = 'others'By default, the pybtex.style.formatting.plain style is applied to the list
of publications, but it is also possible to supply custom pybtex styles. Here
is a simple example that will highlight the name of the website's author. Add
the following to your Pelican config:
PUBLICATIONS_CUSTOM_STYLE = True
PUBLICATIONS_STYLE_ARGS = {'site_author': AUTHOR}Then create the file plugins/pybtex_plugins.py with the following content:
from pybtex.database import Person
from pybtex.style.formatting import unsrt
from pybtex.style.template import tag
class PelicanStyle(unsrt.Style):
def __init__(self, site_author='', **kwargs):
super().__init__(**kwargs)
self.site_author = Person(site_author)
# Allows to apply special formatting to a specific author.
def format(person, abbr=False):
if person == self.site_author:
return tag('strong') [ self.name_style.format(person, abbr) ]
else:
return self.name_style.format(person, abbr)
self.format_name = formatPelicanStyle must be a subclass of pybtex.style.formatting.BaseStyle. An
alternative path to the pybtex_plugins.py file can be provided via
PUBLICATIONS_PLUGIN_PATH in the Pelican config.
First, add the following content to your template file.
Variant A - Open BibTeX entry via JavaScript in new windows:
{% macro render_publication(publication) %}
<li id="{{ publication.key }}">
{{ publication.text }}
[ <a href="javascript:window.open().document.write('<pre>{{ publication.bibtex|replace('\n', '\\n')|escape|forceescape }}</pre>');">Bibtex</a> ]
{% for label, target in [
('PDF', publication.pdf),
('Slides', publication.slides),
('Poster', publication.poster)] %}
{{ "[ <a href=\"%s\">%s</a> ]" % (target, label) if target }}
{% endfor %}
</li>
{% endmacro %}(Note: that we are escaping the BibTeX string twice in order to properly display it.
This can be achieved using forceescape)
Variant B - Show/hide BibTeX entry in-place via CSS:
{% macro render_publication(publication) %}
<li id="{{ publication.key }}">
{{ publication.text }}
[
<a href="#{{ publication.key }}-bibtex">BibTeX</a>
{% for label, target in [
('PDF', publication.pdf),
('slides', publication.slides),
('poster', publication.poster)] %}
{% if target %}
| <a href="{{ target }}">{{ label }}</a>
{% endif %}
{% endfor %}
]
<div class="bib-fold" id="{{ publication.key }}-bibtex">
<a class="bib-close" href="#{{ publication.key }}">×</a>
<pre>{{
publication.bibtex
| trim
| escape
| replace('\n', '<br>')
}}</pre>
</div>
</li>
{% endmacro %}
<style>
.bib-fold { display: none; }
.bib-fold:target { display: block; }
.bib-close { display: block; position: absolute; right: .2em; padding: .2em; margin-top: -.2em; margin-right: .5em; color: inherit; text-decoration: none; font-size: 3em; font-weight: bold; background-color: #fff; }
</style>Then, add the following content (to the same file).
Example content of the bibliography.html template (Option 1: "bibliography" directive):
<ul>
{% for publication in publications %}
{{ render_publication(publication) }}
{% endfor %}
</ul>Example content of the publications.html template (Option 2: Page template):
{% extends "base.html" %}
{% block title %}Publications{% endblock %}
{% block content %}
<section id="content" class="body">
<h1 class="entry-title">Publications</h1>
<ul>
{{ render_publication(publication) }}
</ul>
</section>
{% endblock %}The entries can be sorted by one of the attributes, for example, if you want to sort the entries by date, your unordered list would look like the following:
<ul>
{% for publication in publications|sort(True, attribute='year') %}
{{ render_publication(publication) }}
{% endfor %}
</ul>The sort builtin filter was added in version 2.6 of jinja2.
To group entries by year,
<ul>
{% for grouper, publist in publications|groupby('year')|reverse %}
<li> {{grouper}}
<ul>
{% for publication in publist %}
{{ render_publication(publication) }}
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>As described above, lists of publications are stored in publications_lists.
You can replace publications from the previous example with publications_lists['foo-tag'] to only show the publications with tagged with foo-tag.
You can also iterate over the map and present all bib entries of each list. The section of the previous example changes to:
{% for tag in publications_lists %}
{% if publications_lists|length > 1 %}
<h2>{{tag}}</h2>
{% endif %}
<ul>
{% for publication in publications_lists[tag] %}
{{ render_publication(publication) }}
{% endfor %}
</ul>
{% endfor %}Group by year:
.. bibliography:: pubs.bib
:options: { 'groupby_attribute': 'year' }No grouping:
.. bibliography:: pubs.bibIf the parameter groupby_attribute is passed to the template, the list of publications will be grouped by this attribute.
Otherwise, the plain list will shown:
{% if groupby_attribute %}
{% for year_number, year_publications in publications|groupby(groupby_attribute)|reverse %}
<section id="{{ year_number }}">
<h2>
<a href="#{{ year_number }}">{{ year_number }}</a>
</h2>
<ul>
{% for publication in year_publications %}
{{ render_publication(publication) }}
{% endfor %}
</ul>
</section>
{% endfor %}
{% else %}
<ul>
{% for publication in publications %}
{{ render_publication(publication) }}
{% endfor %}
</ul>
{% endif %}