Nesting metadata

A walk-through on creating nested metadata structures

Object blocks

Nesting is supported by structuring metadata with Object blocks.

All Object blocks must have a string property, which is the text content of the block. This is true regardless of the nesting level of the Object. If it doesn't exist, an error will be thrown.

Object blocks can also have an (optional) children property, which enables nesting. Whereas String blocks are always childless, Object blocks can have descendants through their children property - an Array which can contain String blocks as well as Object blocks. The contents of the children array will be processed and added under the parent block.

// A simple example (no grandchildren)
{
 string: 'Top-level parent',
 children: ['A child with no child of its own', 'Another childless child']
}

// or :

{
 string: 'Grandparent',
 children: [
   {string: 'Parent',
    children: ['One grandchild', 'Two grandchildren']
   }
 ]
}

// The simplest way to create such blocks is to do the following :
// 1) Create an Object block, with an empty 'children' Array.
let parentBlock = {string: "Text of the parent", children: []};
// 2) Push elements to add them to the 'children' Array.
// They can be strings :
children.push('A childless child');
// Or they can be Object blocks :
children.push({string: 'A child with a child of its own'}, children: ['The grandchild']);

Processing order for nested blocks

Items are processed recursively, and blocks are added one-by-one to ensure they are in the right order on the page. This means that, for a given Object block, all of the block's descendants will be added before the block's next sibling (if applicable) is added.

It also means that multi-level nesting is possible, with as many levels as desired. Do make sure that every Object block in the path is properly structured, and be careful to check that elements are the right type : string should always be a String ; children should always be an Array, where each element is either a String or an Object block.

Creating formatting functions for nested output

When creating a nested output, the formatting function must still return an array of metadata ; its elements can be all Object blocks, or a mix of String blocks and Object blocks. Make sure that the children property is always an Array, even if it has only one element in it (or if it's empty).

To help you with writing your own functions, I've made an Observable interactive notebook, where you can try your hand at writing functions & using them to process your own Zotero data :

Examples of output

One level of nesting

itemData = [
           {string: 'Publication information',
             children: ['Journal:: [[Some journal]]',
                        'Date:: 2017',
                        'DOI : 10.9999/2222222222222222',
                        'URL : http://example.com/path/to/item'
                        ]
            },
            "Author(s):: [[First Author]], [[Second Author]], [[Some Editor]] (editor)",
            "Abstract:: A multi-line abstract paragraph, which can have inline #tags or [[page reference]]s that will render in Roam.",
            "Tags:: #[[tag1]], #[[tag2]], #[[some multi-word tag]]"
           ]

Multi-level nesting.

itemData = 
[{string: 'Top block 1',
  children: ["Child block 1",
             {string: 'Child block 2',
              children: ["Grandchild block 1",
                         "Grandchild block 2"]
              },
             "Child block 3"]
  },
 "Top block 2",
 {string: 'Top block 3',
  children: ["Another child block 1",
             "Another child block 2",
             {string: 'Another child block 3',
              children: [{string: 'Another grandchild block 1',
                          children: ["A grand-grandchild"]
                          }
                         ]
               }
              ]
  }
]

Last updated