CSL: Dynamic linking in citeproc-js

This post will be of interest primarily to developers using citeproc-js to format citations for delivery in dynamic Web pages or an API.

It is also kind of big deal.

CSL provides a set of common tools for the formatting of human-readable citations. Open linked data provides a mechanism for enriching published material with supplementary information. Citations are, in effect, a pre-Web implementation of linked data; and developers have quite naturally expressed a desire to join these two facilities. The benefits are fairly obvious: by providing both human-readable citations and machine-readable reference links through a single tool and data source, we can save ourselves a great deal of unnecessary work.

It has taken awhile to get to this point, but the latest release of citeproc-js supports dynamic linking to individual item fields in rendered citations.

Links can be applied to field content by adding a variableWrapper() method to the sys object (the first argument to CSL.Engine when instantiating a processor instance):

sys.variableWrapper = function (params, prePunct, str, postPunct) {
  if (params.variableNames[0] === 'title' 
      && params.itemData.URL
      && params.context === "bibliography") {
    return prePunct 
       + '<a href="'
         + params.itemData.URL 
       + '">' 
         + str
       + '</a>' 
         + postPunct;
  } else {
    return (prePunct + str + postPunct);
var citeproc = new CSL.Engine(sys,CSL_STYLE_IN_XML);

prePunct contains any space or leading punctuation that precede the rendered field content. This will include any literal text added via the prefix or suffix attributes of the CSL rendering node.

str contains the field content itself.

postPunct contains any punctuation that follows the rendered field content.

params is an object carrying context-specific information about the reference being rendered. It has five eight nine keys:

The CSL JSON input data for the citation. Ordinary numeric and text variables have simple string or number values. Name variables yield an array of name objects. Date variables yield an object in the CSL JSON input format. Dump the content with JavaScript JSON.stringify() to explore the detail of the input object.
An array containing the names of the variables rendered in str. For ordinary text fields, variableNames will always have a length of exactly one. Name nodes (cs:names) may render multiple variables.
The context within which the item is being rendered: citation or bibliography.

The class attribute of the style being rendered: in-text or note.
The position of the citation being rendered: one of first, subsequent, ibid, or ibid-with-locator.
In note styles, the number of the note containing this reference. Default: 0.
In note styles, the number of the first note containing this reference. Default: 0.
In numeric styles, the number of this reference in the bibliography. Default: 0.
The output mode of the processor: either html or rtf (wrapper handling is currently disabled in plain text mode—but if you would like to see it hooked up, just let me know).

With suitable input, the variableWrapper() method can be used for various things: decorating citations with cross-links within the document; adding external links to ORCID profiles or author home pages; links to a bibliographic database or publisher service; or what have you.

Note that cs:names nodes are wrapped as a single element containing all names rendered by the node. This is a design choice: some names may not be shown in a printed citation, so author linking from printed citations should be done in a pulldown menu, which can be built from from params.Item using params.variableNames.

Note also that this method covers only variables rendered in the citation. This doesn’t quite go the distance for full RDFa support (which is definitely an objective). For that, we will need a separate method to provide the outer wrapper, a tracking object to identify elements of the citation that are not rendered, and maybe some other bits and pieces—input from people who know the ins and outs of RDF and RDFa would be most welcome on that score.

This entry was posted in Announcements. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>