sdawood / json-tots

JSON Template of Templates
MIT License
9 stars 4 forks source link

Question: applying pipe to each element in array #3

Closed infinioo closed 5 years ago

infinioo commented 5 years ago

Tots is great but i'm having difficulty doing something in particular. How can we apply a pipe to each element in an array without having the piped function have to iterate through all the elements itself? Basically what I would expect is that the piped function would accept a single value and the piping of each element of the array to the function to be handled by tots. Is that possible?

Example:

const trim = str => str.trim() const document = {this: [' one ', 'two ']} const template = {that : ['{{this} | trim}']} // this doesn't work!! the 'trim' function receive an array as the argument, not each element independently const result = tots.transform(template)(document) // result = {that: ['one', 'two']}

Of course I could do:

const trim = values => values.map(str => str.trim())

But then that trim function wouldn't accept single strings and I just feel it's not the best way to do it. Any ideas? Thanks!

sdawood commented 5 years ago

Hello, and thanks for the encouragement

First, we don't have to re-declare trim unless we need a special behavior, there is already a built-in unary trim function

Here is the straightforward solution:

We will use the for-each-document-item | Examples: ['{%%{a.b.someArray}}', '{{["name", "age"]}}'], Note: $a.b.someArray has to be an Array.

Example Code:

const tots = require("json-tots")
const document = {this: [' one ', 'two ']}
// const template = {that : ['{{this} | trim}']} // this doesn't work!! the 'trim' function receive an array as the argument, not each element independently
const template = {that: ['{%%{this}}', '{{$} | trim}']}
const result = tots.transform(template)(document)
console.log(result)
// result = {that: ['one', 'two']}
sdawood commented 5 years ago

Now having a working example we can start thinking about our declarative template and promote partial-template re-use

Note that when we target the partial template array we pipe the partial-data into done so that our rendering logic won't recursively try to render our array, effectively treating the partial-template-array as an Atom (in clojure speak loosely)

const tots = require("json-tots")
const document = {this: [' one ', 'two ']}
const forEachTrimTemplate = {T: ['{%%{this}}', '{{$} | trim}']} // partial template
const template = {that: '{{T} | done}'} // treat T as an atom, do not recursively render the array
const stage1result = tots.transform(template)(forEachTrimTemplate)

// Here you can add control logic or serialize/deserialize

console.log(stage1result)

// { that: ["{%%{this}}", "{{$} | trim}"] }

const result = tots.transform(stage1result)(document)
console.log(result)
// result = {that: ['one', 'two']}