Philosophy

CarboneJS is a powerfull templating engine which works in all XML-based document.

It can also convert your report to reliable PDFs and any other document formats.

It uses a simple declarative programming language, which is not intrusive. You don't need to insert control flow code in your document such as if or for-loop markers.

In computer science, declarative programming is a programming paradigm, a style of building the structure and elements of computer programs, that expresses the logic of a computation without describing its control flow.[1] Many languages applying this style attempt to minimize or eliminate side effects by describing what the program should accomplish in terms of the problem domain, rather than describing how to go about accomplishing it as a sequence of the programming language primitives[2] (the how being left up to the language's implementation). This is in contrast with imperative programming, in which algorithms are implemented in terms of explicit steps. source

This way of programming provides more flexibility for travelling data. You can transform your orginal JSON array directly in the template. See examples:

Moreover, the system is XML-agnostic. It means the template engine works on any valid XML-based documents, not only XML-documents created by Microsoft Office™, LibreOffice™ or OpenOffice™. CarboneJS finds automatically repetition patterns in your template.

How it works?

CarboneJS finds all markers {} in your document (xls, odt, docx, ...) and replaces these markers by datas.
According to the syntax of your markers, you can make a lot of operations including

Replacing a field

Formatting data

Repeating a document portion (a table row or anything else)

Looping on unlimited nested arrays

Conditionally displaying a data based on a test expression

The syntax is easy to learn. It is like using a JSON Array or Object in Javascript.

Combined with features of LibreOffice™ or MS Office™, you can easily create documents with:

Graphics

Headers, footers

Automatically repeated table header across pages

Insert computed field

Page count

...

How to read this documentation?

This documentation is made for report designers. There are five parts sorted by level of complexity.

Substitutions

Each part of this documentation shows exactly what happens if you send Data (JSON Object) and a Template (handmade docx, odt, ...) to CarboneJS.

Basic

This is the most basic example. Do I need to explain it?

Data

{
"firstname" : "John",
"lastname" : "Doe"
}

Template

Hello {d.firstname} {d.lastname} !

Result

Hello John Doe !

Accessing sub-objects

Of course, if your data contains sub-objects, you can access them using the Dot Notation to go deeper in the object tree.

Data

{
"firstname" : "John",
"type" : {
"id" : 1,
"name" : "human"
}
}

Template

{d.firstname} is a {d.type.name}

Result

John is a human

Accessing arrays

When data is an array of objects, you can access directly each object using the reserved word i, which represents the ith item of the array.
CarboneJS uses zero-based arrays. The first item of an array is i=0.

Data

Template

The movie of 1999 was {d[year=1999, meta.type="SF"].name}

Result

The movie of 1999 was Matrix

Alias

Aliases can be used to simplify the maintenance of your report avoiding code repetition or to insert markers somewhere in the document where special characters like square brackets are not allowed (worksheet names for exemple).

Write {#... = ...} to define an alias

Write {$...} to use this alias

Aliases can be defined anywhere in the document, at the end, or at the beginning. They are parsed and removed by CarboneJS before rendering.

Data

{
"name" : "Cars",
"wheels" : 4
}

Template

{#myAlias = d.wheels}

{d.name} need {$myAlias} wheels!

Result

Cars need 4 wheels!

Parametrized Alias

Aliases accept unlimited number of parameters between parentheses, like a function in many languages. Each parameter must start by $.

Data

Template

{#mealOf($weekday) = d[weekday = $weekday].name}

Tuesday, we eat {$mealOf(2)}.

Result

Tuesday, we eat fish.

Repetitions

CarboneJS can repeat a section (rows, title, pages...) of the document.

We don't need to describe where the repetition starts and ends, we just need to design a "repetition example" in the template using the reserved key word i and i+1. CarboneJS will find automatically the pattern to repeat using the first row (i) as an example. The second row (i+1) is removed before rendering the result.

Data

Template

{d[i].brand}

Models

{d[i].models[i].size}

{d[i].models[i+1].size }

{d[i+1].brand}

Result

Toyota

Models

Prius 2

Prius 3

Tesla

Models

S

X

As you may notice, it is useless to repeat completely the first paragraph twice in the template, only the title of the second paragraph is necessary to help CarboneJS detect where the repetition pattern of the main array ends {d.cars[i+1].brand}.

Data

Template

Vehicles

{d[type].brand}

{d[type+1].brand}

Result

Vehicles

car

plane

Iterate on multiple items

In the previous example, only distinct rows were kept. If we want to keep all rows, and sort them by type in ascendant order, we can add the reserved iterator i. CarboneJS accepts multiple iterators separated by a comma.

Conditioned output

By default, condition formatters have a special behavior, the formatter's result is not propagated to the next formatter if the result of the condition is true. This enables test chaining

You can change this behavior by setting the optional parameter continueOnSuccess. If continueOnSuccess=true, the result of the formatter will be passed to the next formatter like in the last line of the example below.