Code snippets

A few snippets that provide building blocks for custom formatting functions

This is a list of JavaScript snippets which can be used as building blocks when writing custom formatting functions. They correspond to common operations, like converting a full date into Roam's Daily Notes format or processing an array of author names into a comma-separated list. Most of them are taken straight from the extension's built-in getItemMetadata function.

In all examples below, metadata is an array to which the element gets added. If you're creating a function for nested output, this might not always suit your purposes - so adjust accordingly. See Nesting metadata for examples of nested JavaScript output.

Generic snippets

Basic function structure

window.myFuncName = function(item){
    let metadata = [];
    
    // Code snippets should be here
    
    return metadata = [];
}
  • If you're writing a function that creates a flat output, you can simply add blocks by using metadata.push("String of block").

  • If you're writing a function that creates a nested output, you'll have to create intermediate Object blocks during the processing/formatting of the item's data.

Adding an element as block if it exists

if(item.<element_path>{
    metadata.push(item.<element_path>);
}

// Example :

// Item title, located under the item's `data` property
if(item.data.title){
    metadata.push(item.data.title);
}

Attribute-specific snippets

data.creators

Goes through the item's list of creators, makes each creator's name into a page reference with format [[firstName lastName]], and adds the creator's role between parentheses after if the creator is not an author. Returns : Author(s):: [[First Author]], [[Second Author]], [[An Editor]] (editor)

if(item.data.creators.length > 0){
    let creatorsList = item.data.creators.map(function (creator) {
        let nameTag = "[[" + [creator.firstName, creator.lastName].filter(Boolean).join(" ") + "]]";
        if (creator.creatorType != "author") {
            nameTag = nameTag + " (" + creator.creatorType + ")"
        }
        return nameTag;
    })
    metadata.push("Author(s):: " + creatorsList.join(", "));
}

data.dateAdded

Converts the date on which the item was added to Zotero into Roam's Daily Notes format. Returns : Date Added:: [[March 10th, 2021]]

if(item.data.dateAdded){
    let date = new Date(item.data.dateAdded);
    let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    let roamDateAdded = months[date.getMonth()] + " " + zoteroRoam.utils.makeOrdinal(date.getDate()) + ", " + date.getFullYear();
    metadata.push("Date Added:: [[" + roamDateAdded + "]]");
}

data.itemType

Maps an item's type to its non-machine name, as specified in the user's or extension's typemap. Returns : Type:: [[Book]]

// Use mapping specified in user-defined typemap, 
// otherwise fall back on typemap_default
if (item.data.itemType) {
    let mapping = zoteroRoam.typemap[item.data.itemType] || item.data.itemType;
    if(zoteroRoam.config.userSettings.typemap){
        mapping = zoteroRoam.config.userSettings.typemap[item.data.itemType] || mapping;
    }
    metadata.push("Type:: " + "[[" + mapping + "]]");
}

data.tags

Goes through the list of the item's tags, and make every tag into a Roam tag with format #[[tag]] to support multi-word tags. Returns : Tags:: #[[tag1]], #[[tag2]], #[[a multi-word tag]]

if(item.data.tags.length > 0){
    let tagsList = item.data.tags.map(i => '#[[' + i.tag + ']]');
    metadata.push("Tags:: " + tagsList.join(", "))
}

Additional data (collections, PDFs, notes...)

Getting an item's collections

Collections data is requested along with items data, and is stored in the zoteroRoam.data.collections object. You can inspect its contents using the console if you'd like.

This allows the extension to identify which collections an item belongs to - and that's what the zoteroRoam.formatting.getItemCollections function does :

// This is taken directly from the extension's source code :
zoteroRoam.formatting.getItemCollections(item){
    if(item.data.collections.length > 0){
        return item.data.collections.map(collecID => zoteroRoam.data.collections.find(collec => collec.key == collecID && collec.library.id == item.library.id));
    } else {
        return false;
    }
}

Getting an item's children (PDF + notes)

If you want to get data about PDF attachments + notes, it's recommended to include them in your data request. That requires asking for items (all of them) rather than items/top (top-level items) in your data URI, and (for notes) giving your API key access to notes (see Step 1.1).

The utility function zoteroRoam.formatting.getItemChildren can search for an item's children within the loaded dataset. If they're present, it will return them (as raw data or formatted output) ; if there aren't any, it will return 'false'. Lastly, in the case that the item has children but none are found in the dataset, the function will also return a remoteChildren: true property - which you can use to request them if you want to.

Basic syntax

// At the minimum, all you have to do is this :
let children = zoteroRoam.formatting.getItemChildren(item);
// It will call the getItemChildren function with default parameters :
// pdf_as: "links"
// notes_as: "formatted"
// split_char: "\n"

// You can also set those arguments explicitly, as a reminder :
let children = zoteroRoam.formatting.getItemChildren(item, {pdf_as: "links", notes_as: "formatted", split_char: "\n"});

Function arguments

What the function returns

// If the item has no PDFs, no notes :
{
    pdfItems: false,
    notes: false
}

// If the item has PDFs + notes :
{
    pdfItems: [...], // Each element = one PDF item
    notes: [[...], [...]] // Each element = one note item
}

// PDFs and notes are searched & processed separately
// If there are no results, the value returned is 'false'
// If there are 1+ results, the value returned is an Array
// => Structure & value will depend on the function's arguments,
// but pdfItems will be an Array and notes will be an Array of Arrays

How to use the function in your code

To make use of this function, there are 2 important things : 1) know what output format you're asking for (cf. function arguments above), 2) begin by checking if there is any data on the children.

This is how the built-in function zoteroRoam.formatting.getItemMetadata handles this :

// Let's say we're creating a custom function called customPaperFormat :
window.customPaperFormat = function(item){
    let metadata = [];
    // ...
    
    let children = zoteroRoam.formatting.getItemChildren(item, {pdf_as: "links", notes_as: "formatted", split_char: "\n"});
    if(children.pdfItems){ // This checks that pdfItems is not 'false'
        // We asked for Markdown links, so children.pdfItems will be an Array of string elements
        // Here we're putting them together in one comma-separated String
        // If there is only one, this will simply return the one link
        metadata.push(`PDF links : ${children.pdfItems.join(", ")}`);
    }
    if(children.notes){ // This checks that notes is not 'false'
        // Let's make an intermediate object, in order to nest the notes under [[Notes]] :
        let notesBlock = {string: `[[Notes]]`, children: []};
        // We asked for formatted notes, so 'notes' will be an Array of Arrays
        // Here we're making a flat Array (because we don't care that the annotations come from different note items)
        // And then we push the notes Array to the 'children' property of our notes Block
        notesBlock.children.push(...children.notes.flat(1));
        // Finally we add notesBlock to the metadata array
        metadata.push(notesBlock);
    }
    
    // ...
    return metadata;
}

This is what the code above will output as Roam blocks :

  • PDF links : [First PDF attachment.pdf](link to this PDF), [Second PDF attachment.pdf](link to that PDF)

  • [[Notes]]

    • Block from note 1

    • Another block from note 1

    • Block from note 2

    • Another block from note 2

Last updated