# Nesting metadata

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

```javascript
// 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](https://observablehq.com/@greenmeen/zoteroroam-metadata-formatting), where you can try your hand at writing functions & using them to process your own Zotero data :

{% embed url="<https://observablehq.com/@greenmeen/zoteroroam-metadata-formatting>" %}

## Examples of output

*One level of nesting*

{% tabs %}
{% tab title="JavaScript output" %}

```javascript
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]]"
           ]
```

{% endtab %}

{% tab title="Roam blocks" %}

* Publication information
  * 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]]
  {% endtab %}
  {% endtabs %}

*Multi-level nesting.*

{% tabs %}
{% tab title="JavaScript output" %}

```javascript
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"]
                          }
                         ]
               }
              ]
  }
]
```

{% endtab %}

{% tab title="Roam blocks" %}

* Top block 1
  * Child block 1
  * Child block 2
    * Grandchild block 1
    * Grandchild block 2
  * Child block 3
* Top block 2
* Top block 3
  * Another child block 1
  * Another child block 2
  * Another child block 3
    * Another grandchild block 1
      * A grand-grandchild
        {% endtab %}
        {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alix-lahuec.gitbook.io/zotero-roam/v0.6/customization/formatting/nesting-metadata.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
