Handlebars in geenee
Once you know the basics of Handlebars, the following should be clear. You need to understand the meaning of partials, helpers, and contextForDynamic.
Partials
You have access everywhere to the full list of partials in the partials
directory. A partial is specified within a Handlebars file of the same name (not counting the file extension). You can add as many as you like, and create as many subdirectories as you need. But, there are two naming constraints:
- The name of each partial must be unique.
- Each partial file should have an '.hbs' extension.
This example shows some subdirectories and a number of examples. Many clauses that appear in multiple types of files are used.
Helpers
There are three sources for helpers currently at your disposal in geenee
:
-
geenee
provides the full use of the just-handlebars-helpers package. That will probably be enhanced or replaced with handlebars-helpers soon.For instance,
{{capitalizeFirst 'just wow'}}
producesJust wow
and{{and value1 value2}}
will result in thevalue1 && value2
(useful for `{{#if}} for instance). -
There are a few included helpers:
{{safe text}}
showstext
without escape characters. That is helpful if you are getting unwanted escapes of certain special characters such as quote marks.{{curly true}}
produces a left curly brace{
, {{curly false}} returns}
.
-
The
helpers
directory should contain any helpers that you create. Sincegeenee
is written with typescript, your helpers should be in typescript as well, with a.ts
extension.See this example for some ideas.
Context
Your .hbs
templates for standard, static and dynamic files are passed a rich context automatically that is derived from your template's configuration and values in an ns file.
The context varies a bit for each of the three types of files (standard, static and dynamic), as specified below.
Shared Context Elements
names
geenee
context includes a names
object that contains, minimally, these values for naming an instance for a file:
- singular: the name starting with uppercase [useful for a component class, for instance]
- singularLowercase: component [useful for a component instance]
- plural: a pluralized version of
singular
- pluralLowercase: a pluralized version of
singularLowercase
For instance, this line in an .hbs
file:
describe('{{names.singular}}', () => {
where a current component is "sample" will produce Sample
.
General Info
- nsInfo: the contents of the ns file for the code base
- config: the contents of the config for the template
-
general: an object with info that a template can use. There are a few automatically included items:
-
If there is a package.json for a code base, then
general.json
will show the contents.For instance,
{{general.json.name}}
will show the name of the file. - The current code directory is
general.codeDir
.
Other than that, the template developer must request what you want the code base developer to put into
general
. Currently,general
is not accessed within dynamic context, but it does appear in standard and static contexts. -
Static Context
In addition to the shared elements above, a static context contains these elements, specified in the ns file for the instance:
- slug
- specs
- A number of fields about the dynamic hierarchy that can be useful:
- sources: all units. For each, there is a
sourceConst
which is recommended as a consistent way to refer programmatically to the unit, andsourceId
if the ns file defines it in abackend
section. - types: all types. For each, there are
typeConst
andtypeId
, analogous tosourceConst
andsourceId
for types. - actionTypes. For each there is
actionType
andactions
. Each action hasactionConst
andactionId
.
- sources: all units. For each, there is a
Dynamic Context
In addition to the shared elements above, a dynamic context contains these elements:
- nodeTypes, dataTypes, and boilerPlateInfo, derived from the config
- stackInfo: info about the stack (derived from the ns file)
- childrenInfo: info about the children in a unit for a given component (again, derived from the ns file)
For instance, in this sample config file you can find a list of dataFunctionTypes
that refer to an earlier list of componentTypes
. When an ns file (see the sample ns file) for the template uses a dataFunctionType, geenee
loads into contextForDynamic an object boilerPlateInfo
that includes componentType
for any given file.
So your partials can refer to boilerPlateInfo.componentType
. For an example, see the next section (Conditional Branching).
As with all Handlebars helpers, you must explicitly specify their parameters and they do not have access to the full geenee
contextForDynamic.
Conditional Branching
geenee
provides the full use of the just-handlebars-helpers package for the sake of basic conditions. For instance, that permits you to check a value in your contextForDynamic and conditionally branch.
Here is an example of conditional branching from contextForDynamic. One element of the contextForDynamic is boilerPlateInfo
, which contains a key componentType
. There is some basic branching here based on that value. Another key of boilerPlateInfo
is nodeType
, which is used in an embedded branch.
fileInfo
The fileInfo
object contains two keys, useful for standard geenee
file identification when storing and retrieving custom code modifications.
- unitName: a name for a dynamic unit, or group of files.
- component: the specific dynamic component or specific file.
This gets inserted at the beginning of a file in an ns__file
comment for the sake of geenee. You normally don't have to do anthing with it.