Model object
This document describes the structure of the object that represents a model when writing a template.
The second part of the document explains how the Hapify syntax map this object properties to an understandable syntax.
Before reading this, you should have a look to the key-concepts section.
Within the templates
Model injection
The template input can be defined as one
or all
models.
During the generation process, if defined as one
, the template will be called one time for each model. Therefore it will generate one output file for each model.
If defined as all
, the template will be called once for all models. Then it will generate one output file.
Single model
If the template requires one model, therefore, an object model
(alias m
) will be available as a global variable in the template.
In a Hapify template it will be available under Model
or M
.
In a Javascript template it will be available under model
or m
.
Multiple models
If the template requires all the models, therefore, an array models
(alias m
) will be available as a global variable in the template.
This array contains all the available models.
In a Hapify template it will be available under Models
or M
.
In a Javascript template it will be available under models
or m
.
Structure of the model object
The following objects will be available in the template.
Model object
id
(string): an unique IDname
(string): name of the model, as the user entered it.names
(object): name variants computed from thename
property.raw
(string): as the user entered it. ExampleOnline item
.kebab
(string): exampleonline-item
.big
(string): exampleONLINE-ITEM
.header
(string): exampleOnline-Item
.snake
(string): exampleonline_item
.constant
(string): exampleONLINE_ITEM
.compact
(string): exampleonlineitem
.camel
(string): exampleonlineItem
.pascal
(string): exampleOnlineItem
.lower
(string): exampleonline item
.capital
(string): exampleOnline Item
.
fields
- aliasf
(object): an object containing all fields, grouped in different arrays. See Field object section to learn more about field's structure.list
- aliasl
(array): containing all fields of the model.primary
- aliaspr
(Field): primary field of the model.null
if no primary field is defined.unique
- aliasun
(array): fields flagged asunique
.label
- aliaslb
(array): fields flagged aslabel
.nullable
- aliasnu
(array): fields flagged asnullable
.multiple
- aliasml
(array): fields flagged asmultiple
.embedded
- aliasem
(array): fields flagged asembedded
.searchable
- aliasse
(array): fields flagged assearchable
.sortable
- aliasso
(array): fields flagged assortable
.hidden
- aliashd
(array): fields flagged ashidden
.internal
- aliasin
(array): fields flagged asinternal
.restricted
- aliasrs
(array): fields flagged asrestricted
.ownership
- aliasos
(array): fields flagged asownership
.searchableLabel
- aliassl
(array): fields flagged aslabel
andsearchable
. Useful for quick-search by label.filter
- aliasf
(Function): filter fields with a custom rule. Equivalent ofmodel.fields.list.filter
.references
- aliasr
- non-deep model only (array): fields of typeentity
.filter
- aliasf
(function): filter the array.
dependencies
- aliasd
- non-deep model only (object): dependencies (to other models) of this model. A model has a dependency if one of this field is of typeentity
.list
- aliasl
(array): dependency models, but self. These models are added as "deep models".self
- aliass
(boolean): this model has a self-dependency.filter
- aliasf
(function): filter dependencies.- First argument (function - default
(f) => f
): filter function receiving the referencer field (the entity field). - Second argument (boolean - default
true
): boolean indicating if we should filter the self dependency.
- First argument (function - default
referencedIn
- aliasri
- non-deep model only (array): models that refer to this one. These models are added as "deep models". These models only contains fields of typeentity
referring to the current model.filter
- aliasf
(function): filter the array.
properties
- aliasp
(object): pre-computed properties from fields.fieldsCount
(number): the number of fields contained in the model.hasPrimary
(boolean): model has a primary field.hasUnique
(boolean): model has at least one unique field.hasLabel
(boolean): model has at least one label field.hasNullable
(boolean): model has at least one nullable field.hasMultiple
(boolean): model has at least one multiple field.hasEmbedded
(boolean): model has at least one embedded field.hasSearchable
(boolean): model has at least one searchable field.hasSortable
(boolean): model has at least one sortable field.hasHidden
(boolean): model has at least one hidden field.hasInternal
(boolean): model has at least one internal field.hasRestricted
(boolean): model has at least one restricted field.hasOwnership
(boolean): model has at least one ownership field.hasSearchableLabel
(boolean): model has at least one field marked as label and also searchable.hasDependencies
- non-deep model only (boolean): model has dependencies to other models or itself (through anentity
field).isReferenced
- non-deep model only (boolean): model is referenced by other models.mainlyHidden
(boolean): most of the fields are hidden (strictly).mainlyInternal
(boolean): most of the fields are internal (strictly).isGeolocated
(boolean): model contains at least one latitude field and one longitude field.isGeoSearchable
(boolean): model contains at least one searchable latitude field and one searchable longitude field.
accesses
- aliasa
(object): action's accesses grouped by action or restriction. See Access object section to learn more about access' structure.list
- aliasl
(array): action's accesses of the model.admin
- aliasad
(array): action's accesses restricted toadmin
.owner
- aliasow
(array): action's accesses restricted toowner
.auth
- aliasau
(array): action's accesses restricted toauthenticated
.guest
- aliasgs
(array): action's accesses restricted toguest
.create
- aliasc
(object): thecreate
action's access.read
- aliasr
(object): theread
action's access.update
- aliasu
(object): theupdate
action's access.remove
- aliasd
(object): thedelete
action's access.search
- aliass
(object): thesearch
action's access.count
- aliasn
(object): thecount
action's access.filter
- aliasf
(Function): filter action's accesses with a custom rule. Equivalent ofmodel.accesses.list.filter
.properties
- aliasp
(object): pre-computed properties from action's accesses.onlyAdmin
(boolean): model only contains actions restricted toadmin
.onlyOwner
(boolean): model only contains actions restricted toowner
.onlyAuth
(boolean): model only contains actions restricted toauthenticated
.onlyGuest
(boolean): model only contains actions restricted toguest
.maxAdmin
(boolean): most permissive access isadmin
.maxOwner
(boolean): most permissive access isowner
.maxAuth
(boolean): most permissive access isauthenticated
.maxGuest
(boolean): most permissive access isguest
.noAdmin
(boolean): there is no action restricted toadmin
.noOwner
(boolean): there is no action restricted toowner
.noAuth
(boolean): there is no action restricted toauthenticated
.noGuest
(boolean): there is no action restricted toguest
.hasAdmin
(boolean): there is at least one action restricted toadmin
.hasOwner
(boolean): there is at least one action restricted toowner
.hasAuth
(boolean): there is at least one action restricted toauthenticated
.hasGuest
(boolean): there is at least one action restricted toguest
.
Field object
name
(string): name of the field, as the user entered it.names
(object): name variants computed thename
property. As for the model object.raw
(string): as the user entered it. Examplefirst_name
.kebab
(string): examplefirst-name
.big
(string): exampleFIRST-NAME
.header
(string): exampleFirst-Name
.snake
(string): examplefirst_name
.constant
(string): exampleFIRST_NAME
.compact
(string): examplefirstname
.camel
(string): examplefirstName
.pascal
(string): exampleFirstName
.lower
(string): examplefirst name
.upper
(string): exampleFIRST NAME
.capital
(string): exampleFirst Name
.
primary
(boolean): field is flagged asprimary
.unique
(boolean): field is flagged asunique
.label
(boolean): field is flagged aslabel
.nullable
(boolean): field is flagged asnullable
.multiple
(boolean): field is flagged asmultiple
.embedded
(boolean): field is flagged asembedded
.searchable
(boolean): field is flagged assearchable
.sortable
(boolean): field is flagged assortable
.hidden
(boolean): field is flagged ashidden
.internal
(boolean): field is flagged asinternal
.restricted
(boolean): field is flagged asrestricted
.ownership
(boolean): field is flagged asownership
.type
(string): type of the field. Can bestring
,number
,boolean
,datetime
,entity
,object
orfile
.subtype
(string): subtype of the field. The available values depend on thetype
:string
: Can benull
,email
,password
,url
,text
orrich
.number
: Can benull
,integer
,float
,latitude
orlongitude
.boolean
: Isnull
.datetime
: Can benull
,date
ortime
.entity
: Isnull
.object
: Isnull
.file
: Can benull
,image
,video
,audio
ordocument
.
model
- aliasm
(object): target model object if the field is of typeentity
.null
otherwise.enum
- aliase
(array): an array containing all enum if the field is of typeenum
.null
otherwise. See Enum object section to learn more about enum's structure.value
(string|string[]):- If type is
entity
: raw ID of the target model (string). - If type is
enum
: raw enum list (string[]). - Otherwise
null
.
- If type is
Enum object
name
(string): name of the enum, as the user entered it.names
(object): name variants computed thename
property. As for the field and model object.raw
(string): as the user entered it. Examplefirst_name
.kebab
(string): examplefirst-name
.big
(string): exampleFIRST-NAME
.header
(string): exampleFirst-Name
.snake
(string): examplefirst_name
.constant
(string): exampleFIRST_NAME
.compact
(string): examplefirstname
.camel
(string): examplefirstName
.pascal
(string): exampleFirstName
.lower
(string): examplefirst name
.upper
(string): exampleFIRST NAME
.capital
(string): exampleFirst Name
.
Access object
action
(string): name of the action. Can becreate
,read
,update
,remove
,search
orcount
.admin
(boolean): access isadmin
.owner
(boolean): access isowner
.auth
(boolean): access isauthenticated
.guest
(boolean): access isguest
.gteAdmin
(boolean): access is greater or equal thanadmin
(should always betrue
).gteOwner
(boolean): access is greater or equal thanowner
.gteAuth
(boolean): access is greater or equal thanauthenticated
.gteGuest
(boolean): access is greater or equal thanguest
.lteAdmin
(boolean): access is less or equal thanadmin
.lteOwner
(boolean): access is less or equal thanowner
.lteAuth
(boolean): access is less or equal thanauthenticated
.lteGuest
(boolean): access is less or equal thanguest
(should always betrue
).
Hapify Syntax
This part show how the Hapify syntax is built on top of the model object described above. This syntax is optimized to manipulate this object and access its properties with simple words.
Wrappers
Hapify syntax blocks are wrapped by two tags:
- Opening tag:
<<
. - Closing tag:
>>
.
Escape wrappers
Usually used for binary operations, these wrappers can be escaped.
Escaped tags \<\<
(and \>\>
) are replaced by <<
(and >>
) in the generated content.
Syntax
Hapify templates can be written with a long or short syntax.
Both have advantages: - Short syntax does not interfere with the target code when reading the template, due to a shorter meta code. - Long syntax is explicit and can be read naturally.
In a template, you can mix both syntax.
A loop with Hapify syntax
<<for Fields searchable and sortable and not label f>>
// Code here
<<endfor>>
<<@ F se*so/lb f>>
// Code here
<<@>>
Explanations:
for
(alias@
) is the operationFields
(aliasF
) is the variablesearchable and sortable and not label
(short syntax:se*so/lb
) is the condition (optional)f
is the assignment variable
Variable naming
As a convention, we use lower case to name dynamically defined variables (user variables) and upper case for pre-defined variables (system variables). An user variable cannot use system reserved words. To see the complete list of reserved words, please refer to the end of this file.
To refer to the root variable, we use Model
or Models
(short: M
).
It refers to the model in a single-model template and to the models list in a multiple-model template.
By default, in a case of a single-model template:
Fields
(short:F
) fields list:model.fields.list
Dependencies
(short:D
) model's dependencies list:model.dependencies
ReferencedIn
(alias:RefModels
, short:R
) dependent models list:model.referencedIn
PrimaryField
(short:P
) model's primary field:model.fileds.primary
Accesses
(short:A
) action's accesses list:model.accesses.list
CreateAccess
(short:Ac
) create action's access:model.accesses.create
ReadAccess
(short:Ar
) read action's access:model.accesses.read
UpdateAccess
(short:Au
) update action's access:model.accesses.update
RemoveAccess
(short:Ad
) delete (remove) action's access:model.accesses.remove
SearchAccess
(short:As
) search action's access:model.accesses.search
CountAccess
(short:An
) count action's access:model.accesses.count
Conditional operator
This operator can be used over an object or an array of objects. If used over an array, it will test the length of the array filtered by the condition.
As an array, it can be used over any object containing a method filter
that receives a callback returning a boolean.
In the model structure, model.dependencies
is an object that contains a filter
method.
Then, this operator can test if a model has dependencies that has fields with a specific condition.
Syntax
Tests if the model has at least one multiple entity.
<<if Fields entity and multiple>>
// ...
<<endif>>
<<? F tE*ml>>
// ...
<<?>>
Operators
Operators can be written as words or as algebra operators.
and
is an intersection. It can also be written*
or&&
. For examplesortable and searchable
equalssortable * searchable
equalssortable && searchable
.or
is an union. It can also be written+
or||
. For examplesortable or searchable
equalssortable + searchable
equalssortable || searchable
.and not
is an intersection with the complementary. It can also be writtenandNot
,/
or&& !
. For examplesortable andNot searchable
equalssortable and not searchable
equalssortable * searchable
equalssortable && !searchable
.or not
is an union with the complementary. It can also be writtenorNot
,-
or|| !
. For examplesortable orNot searchable
equalssortable or not searchable
equalssortable - searchable
equalssortable || !searchable
.
If the condition starts with andNot
, orNot
, -
or /
it will be converted to !
.
Therefore, -searchable*sortable
and andNot searchable and sortable
are equivalent to not searchable and sortable
.
Example
<<if Fields not nullable andNot (number or not date)>>
// ...
<<endif>>
<<? F !nu/(tN-tDd)>>
// ...
<<?>>
Properties short-codes
You can filter an array or to test a field by its properties.
Available properties for a field:
primary
(short:pr
) for booleanprimary
unique
(short:un
) for booleanunique
label
(short:lb
) for booleanlabel
nullable
(short:nu
) for booleannullable
multiple
(short:ml
) for booleanmultiple
embedded
(short:em
) for booleanembedded
searchable
(short:se
) for booleansearchable
sortable
(short:so
) for booleansortable
hidden
(short:hd
) for booleanhidden
internal
(short:in
) for booleaninternal
restricted
(short:rs
) for booleanrestricted
ownership
(short:os
) for booleanownership
string
(short:tS
) for typestring
email
(short:tSe
) for typestring
and subtypeemail
password
(short:tSp
) for typestring
and subtypepassword
url
(short:tSu
) for typestring
and subtypeurl
text
(short:tSt
) for typestring
and subtypetext
richText
(alias:rich
, short:tSr
) for typestring
and subtyperich
number
(short:tN
) for typenumber
integer
(short:tNi
) for typenumber
and subtypeinteger
float
(short:tNf
) for typenumber
and subtypefloat
latitude
(short:tNt
) for typenumber
and subtypelatitude
longitude
(short:tNg
) for typenumber
and subtypelongitude
boolean
(short:tB
) for typeboolean
datetime
(short:tD
) for typedatetime
date
(short:tDd
) for typedatetime
and subtypedate
time
(short:tDt
) for typedatetime
and subtypetime
enum
(short:tU
) for typeenum
entity
(short:tE
) for typeentity
oneOne
(short:tEoo
) for typeentity
and subtypeoneOne
oneMany
(short:tEom
) for typeentity
and subtypeoneMany
manyOne
(short:tEmo
) for typeentity
and subtypemanyOne
manyMany
(short:tEmm
) for typeentity
and subtypemanyMany
object
(short:tO
) for typeobject
file
(short:tF
) for typefile
image
(short:tFi
) for typefile
and subtypeimage
video
(short:tFv
) for typefile
and subtypevideo
audio
(short:tFa
) for typefile
and subtypeaudio
document
(short:tFd
) for typefile
and subtypedocument
Example
<<if Fields (restricted or internal) and not number>>
// Current model has at least one field matching to the condition
<<endif>>
<<? F (rs+in)/tN>>
// Current model has at least one field matching to the condition
<<?>>
You can also test a model or filter a list of models by its pre-computed properties:
mainlyHidden
(short:pMHd
) for booleanmainlyHidden
mainlyInternal
(short:pMIn
) for booleanmainlyInternal
isGeolocated
(short:pGeo
) for booleanisGeolocated
isGeoSearchable
(short:pGSe
) for booleanisGeoSearchable
Example
<<for Models isGeolocated model>>
// For each model matching the condition
<<endfor>>
<<@ M pGeo m>>
// For each model matching the condition
<<@>>
Access controls
You can filter an array of actions or to test an action by its access properties:
admin
(short:ad
) for booleanadmin
owner
(short:ow
) for booleanowner
auth
(short:au
) for booleanauth
guest
(short:gs
) for booleanguest
gteAdmin
(short:[ad
) for booleangteAdmin
gteOwner
(short:[ow
) for booleangteOwner
gteAuth
(short:[au
) for booleangteAuth
gteGuest
(short:[gs
) for booleangteGuest
lteAdmin
(short:ad]
) for booleanlteAdmin
lteOwner
(short:ow]
) for booleanlteOwner
lteAuth
(short:au]
) for booleanlteAuth
lteGuest
(short:gs]
) for booleanlteGuest
Examples
Loop over all actions' accesses:
<<for Accesses gteAuth action>>
// For each action of the current model that requires auth or admin accees
<<endfor>>
<<@ A [au a>>
// For each action of the current model that requires auth or admin accees
<<@>>
Test one action's access:
<<if ReadAccess guest>>
// Anyone can read this model
<<endif>>
<<? Ar gs>>
// Anyone can read this model
<<?>>
Words available for the access' properties of a model:
onlyAdmin
(short:pOAd
) for booleanonlyAdmin
onlyOwner
(short:pOOw
) for booleanonlyOwner
onlyAuth
(short:pOAu
) for booleanonlyAuth
onlyGuest
(short:pOGs
) for booleanonlyGuest
maxAdmin
(short:pMAd
) for booleanmaxAdmin
maxOwner
(short:pMOw
) for booleanmaxOwner
maxAuth
(short:pMAu
) for booleanmaxAuth
maxGuest
(short:pMGs
) for booleanmaxGuest
noAdmin
(short:pNAd
) for booleannoAdmin
noOwner
(short:pNOw
) for booleannoOwner
noAuth
(short:pNAu
) for booleannoAuth
noGuest
(short:pNGs
) for booleannoGuest
Example
<<if Accesses onlyAdmin>>
// All actions on this model are restricted to admins
<<endif>>
<<? A pOAd>>
// All actions on this model are restricted to admins
<<?>>
Structure
A complete conditional writing will look like this:
<<if4 Fields hidden>>
// This model has at least 4 hidden fields
<<elseif2 Fields label or boolean>>
// This model has at least 2 label or boolean fields
<<elseif PrimaryField string>>
// The primary key of the model is a string
<<else>>
// Something else
<<endif>>
<<?4 F hd>>
// This model has at least 4 hidden fields
<<??2 F lb+tB>>
// This model has at least 2 label or boolean fields
<<?? P tS>>
// The primary key of the model is a string
<<??>>
// Something else
<<?>>
if (model.fields.list.filter(f => f.hidden).length >= 4) {
out += ' // This model has at least 4 hidden fields';
} else if (model.fields.list.filter(f => f.label || f.type === 'boolean').length >= 2) {
out += ' // This model has at least 2 label or boolean fields';
} else if (model.fields.primary.type === 'string') {
out += ' // The primary key of the model is a string';
} else {
out += ' // Something else';
}
Statements analysis
if
<<if4 Fields hidden>>
is equivalent to: if (condition) {
.
<<if
is the opening tag.4
is the minimum length of the filtered array. This value is optional and only usable if the variable is an array. If omitted, we assume the required length is 1.Fields
is the variable to test. It can be and array or an object.hidden
is the condition to test the object or the items of an array.>>
closes the tag
else if
<<elseif2 Fields label or boolean>>
Js equivalent would be: } else if (condition) {
.
It follows the same rules as an if statement, unless its opening tag is <<elseif
.
else
<<else>>
is equivalent to: } else {
.
ending
<<endif>>
is equivalent to: }
.
Examples
Example with conditions:
This tests if the model has some searchable and sortable but not hidden fields
<<if Fields searchable and sortable and not hidden>>
// ...
<<endif>>
<<? F se*so/hd>>
// ...
<<?>>
if (model.fields.list.filter(f => f.searchable && f.sortable && !f.hidden).length > 0) {
out += ' // ...';
}
Example without condition:
<<if Fields>>
// ...
<<endif>>
<<? F>>
// ...
<<?>>
if (model.fields.list.length > 0) {
out += ' // ...';
}
Example with more than 2 elements
Example to test if the model has at least two label fields
<<if2 Fields label>>
// ...
<<endif>>
<<?2 F lb>>
// ...
<<?>>
if (model.fields.list.filter(f => f.label).length >= 2) {
out += ' // ...';
}
Example for a specific action's access
Example to test if the update action is restricted to admin or owner
<<if UpdateAccess admin or owner>>
// ...
<<endif>>
<<? Au ad+ow>>
// ...
<<?>>
if (model.accesses.update.admin || model.accesses.update.owner) {
out += ' // ...';
}
Example for many action's accesses
Example to test if at least one action is restricted to authenticated user or less
<<if Accesses lteAuth>>
// ...
<<endif>>
<<? A au]>>
// ...
<<?>>
if (model.accesses.filter(a => a.lteAuth).length > 0) {
out += ' // ...';
}
Iteration operator
The loop operation (foreach) is for
(short: @
).
It applies only to an array. It uses the same conditions syntax as the conditional operator.
Actually, it inherits from the conditional operator.
Syntax
The operators and the properties used in the condition are the same as for the conditional operator.
This will loop over all fields of type entity and multiple and assign the current field to the variable f
.
<<for Fields entity and multiple f>>
// ...
<<endfor>>
<<@ F tE*ml f>>
// ...
<<@>>
Structure
A complete iteration will look like this:
<<for4 Fields hidden f>>
// Do something
<<endfor>>
<<@4 F hd f>>
// Do something
<<@>>
for (let f of model.fields.list.filter(f => f.hidden).slice(0, 4)) {
out += ' // Do something';
}
Analysis
loop
<<for4 Fields hidden f>>
is equivalent to: for (assigment + condition) {
.
<<for
is the opening tag.4
is the maximum length of the filtered array. This value is optional. If omitted, we do not slice the filtered array.Fields
is the variable to filter and to loop on. It must be iterable.hidden
is the condition to test the items of the array.f
is the assignment variable. This variable will be available inside the loop's scope.>>
closes the tag.
ending
<<endfor>>
is equivalent to: }
.
Examples
Example with conditions over fields:
To loop over model's searchable entity fields
<<for Fields searchable and entity f>>
// ...
<<endfor>>
<<@ F se*tE f>>
// ...
<<@>>
for (let f of model.fields.list.filter(f => f.searchable && f.type === 'entity')) {
out += ' // ...';
}
Example with conditions over models:
In the context of a multiple-model template, this loops over all models that are geo-located.
<<for Models isGeolocated m>>
// ...
<<endfor>>
<<@ M pGeo m>>
// ...
<<@>>
for (let m of model.filter(i => i.properties.isGeolocated)) {
out += ' // ...';
}
Example with 2 elements
This example will loop over the two first dependency models that have sortable fields.
<<for2 Dependencies sortable d>>
// ...
<<endfor>>
<<@2 D so d>>
// ...
<<@>>
for (let d of model.dependencies.filter(f => f.sortable).slice(0, 2)) {
out += ' // ...';
}
Example without conditions
This will loop over all fields.
<<for Fields f>>
// ...
<<endfor>>
<<@ F f>>
// ...
<<@>>
for (let f of model.fields.list) {
out += ' // ...';
}
Example with accesses
This will loop over all actions restricted to admin or owner.
<<for Accesses admin or owner>>
// ...
<<endfor>>
<<@ A ad+ow>>
// ...
<<@>>
for (let f of model.accesses.list.filter(a => a.admin || a.owner)) {
out += ' // ...';
}
Name interpolation
Name interpolation is the default operation. To print the name of a variable (model or field), we omit the operation.
Example for the model's name as upper camel:
<<Model pascal>>
<<M AA>>
UserProfile
Example for field's name as kebab:
<<f kebab>>
<<f a-a>>
creation-date
The values for the name are:
camel
(short:aA
) fornames.camel
pascal
(short:AA
) fornames.pascal
lower
(short:a
) fornames.lower
capital
(short:A
) fornames.capital
kebab
(short:a-a
) fornames.kebab
header
(short:A-A
) fornames.header
snake
(short:a_a
) fornames.snake
constant
(short:A_A
) fornames.constant
compact
(short:aa
) fornames.compact
raw
(short:R
) fornames.raw
Raw inputs
This operator allows you to write pure Javascript.
Syntax
- Opening tag:
<<<
- Closing tag:
>>>
Those tags are also escapable.
Between those tags you can write Javascript code to inject new variables and new functions into the template scope.
Output
The output variable is named out
.
Therefore to concatenate a string to the template output, you have to write: <<< out += 'more content here'; >>>
.
Examples
Insert a custom variable:
<<< const l = model.fields.length; >>>
Declare a processing function:
<<<
function fieldName(f) {
return f.names.snake.toUpperCase();
}
>>>
Interpolation
This operator prints the content of a variable. It is useful to print the result of a custom function or the value of a custom variable.
Syntax
<<= myFunction() >>
or <<=customVariable>>
This is equivalent to <<< out += myFunction(); >>>
.
Error
Do not write this: <<= JSON.stringify(model) >>
.
The model
object has recursive properties. Therefore this command will enter an infinite loop.
Comments
This operator writes a comment in the template without any output to the generated file.
<<# This is just a comment>>