Skip to main content

Values and Variables

A template is useful when parts of it change from one generation to the next. This lesson shows how a value gets into a file, where the fields of the dialog come from, how to hold a list, and how a value can be computed from other values.


A value in a file​

Write the name of a variable between double braces. CodeBaker replaces it with the value the user typed:

Hello, {{ name }}!

{{ name }} is the syntax of Pebble, the template language CodeBaker uses. It works in every template with no setup, and it is the same for a text file, a Markdown file or an HTML page. The same braces can also hold a filter such as {{ name | tableize }}.


Where the fields of the dialog come from​

The first step of the dialog is a form. Each field of the form is one entry of vars in codebaker.config.json5, the main configuration file of every template. The name of the entry is the name of the variable, and its value is what the field shows by default.

This example has everything this lesson talks about. Click codebaker.config.json5 in the template to see the vars and json sections, and compare them with the dialog below it:

Where the fields of the dialog come from
Template.CodeBaker/fields-and-json/
Download the template (.zip)https://codebaker.dev/examples/fields-and-json.zip
Install in IntelliJ IDEA

Needs the CodeBaker plugin and an open project. Another IDE, or the button does nothing? Copy the link, then in the IDE right-click any folder → New → Generate from Template → Install Template from URL… and paste it. You always get a confirmation dialog before anything is installed.

codebaker.config.json5
{
// The folder name when the template is installed under .CodeBaker/
id: "fields-and-json",

name: "Entity Schema",

// Each entry becomes a text field in the dialog, with the value as its default.
vars: {
entity: "BlogPost",
// A value can be computed from the ones above it (never from the ones below it).
table: "{{ entity | tableize }}",
},

// Lists and objects go here. The dialog shows this as an editable area, and each top-level key becomes a variable.
json: {
fields: [
{ name: "id", type: "int" },
{ name: "title", type: "string" },
// The same {{ }} works here, and is computed from the fields above.
{ name: "{{ table }}_total", type: "int" },
],
},
}
schema.md
# {{ entity }}

Table: `{{ table }}`

| Column | Type |
|---|---|
{% for field in fields %}
| {{ field.name }} | {{ field.type }} |
{% endfor %}
Typed in the dialogstep 1, Custom Properties
entity
BlogPost
table
{{ entity | tableize }}
JSON
{
"fields": [
{
"name": "id",
"type": "int"
},
{
"name": "title",
"type": "string"
},
{
"name": "{{ table }}_total",
"type": "int"
}
]
}
Generated resultwhat lands in your project
schema.md
# BlogPost

Table: `blog_posts`

| Column | Type |
|---|---|
| id | int |
| title | string |
| blog_posts_total | int |

To define a field, add an entry:

{
name: "Entity Schema",

vars: {
entity: "BlogPost", // a field named entity, with BlogPost in it
table: "{{ entity | tableize }}", // a field whose value is computed (see below)
},
}
  • One entry, one field. The user can change the text of any field before generating.
  • A name uses letters, digits and _, so that it can be written as a placeholder too.
  • Write values as strings. A boolean or a number (hasTimestamps: true, perPage: 20) is accepted too and shown as text. Every field is a plain text field.
  • Typed true, false and numbers become real ones. The text true in a field is a boolean once resolved, so {% if hasTimestamps %} works: see Conditions and Loops.
  • Some values need no field. DATE, USER, PROJECT_NAME and the others are always there: see System Properties.

JSON in a minute​

A field holds one piece of text. A list of columns, or of menu items, does not fit in one field. For that the config has a place for JSON, a plain-text format for data. It has only a few pieces:

{ "name": "title", "type": "string" } an object: names, each with a value
[ "id", "title", "price" ] a list: values in a row
"text" 42 3.5 true false a string, a number, a boolean

An object can hold lists, and a list can hold objects, as far as you like. The config files of a template are JSON5: JSON that also allows comments, trailing commas, keys without quotes and single quotes. That is why the examples here can have comments, and why you can leave a comma after the last item. Nothing more about JSON is needed to start.


Lists and objects: the json section​

Lists and objects go in the json section of the config:

json: {
fields: [
{ name: "id", type: "int" },
{ name: "title", type: "string" },
],
},
  • The dialog shows it as an editable area under the fields, so the user can add, change or remove items before generating. If what is written there is not valid JSON, a red Invalid JSON: ... message appears under it and Next stays disabled until it is fixed.
  • Each top-level key becomes a variable. Here fields is a list, and a loop writes something for each item: see Conditions and Loops. Inside the loop, field.name and field.type are the parts of one item.
  • Lists and objects do not work in vars. An array or an object written there is dropped without a message. Put it in json.

Dynamic values: how they are computed​

A value does not have to be written out. Any entry of vars, and any text in the JSON area, can contain {{ ... }}, and CodeBaker resolves it: it computes the value with Pebble, from the values it already knows. In the example above, table is {{ entity | tableize }}, which becomes blog_posts, and a column of the JSON area is {{ table }}_total, which becomes blog_posts_total.

The order matters, and it is always the same:

  1. The vars, from the top down. Each entry can use the entries above it and nothing below it. table can use entity because entity comes first. A value that uses an entry written below it gets empty text, because that one is not known yet.
  2. Then the JSON area, with all the resolved fields. Its {{ }} can use any field of the form, and the system properties.
  3. Then the types: after resolving, text that is exactly true, false or a plain number becomes a boolean or a number.

You can see it happen. Step 2 of the dialog writes a line for every field whose value changed (table: {{ entity | tableize }} → blog_posts), and it shows the JSON area as resolved when it differs from what was written. See Step 2. The Names and Filters lesson lists the filters that are most used here.


A value in a file name​

A file or folder name takes the same placeholders as the contents:

{{ title }}-card.html → Welcome-card.html
models/{{ name }}.php → models/User.php
{{ module }}/Service.php → Auth/Service.php
Only a plain value works in a name

A file or folder name takes a variable, or a dotted path into an object ({{ name }}, {{ user.name }}). A filter, an expression, an if or a loop written in a name is not evaluated and stays as written, and the operating system limits which characters a name may have (Windows does not allow | or :). If a name needs a filter, either:

  • compute it in vars, for example table: "{{ name | tableize }}", and write {{ table }} in the name, or
  • keep a plain file name in the template and give the output name in the mapping file, where the target is rendered by Pebble: "model.php": "{{ name | tableize }}/{{ name }}.php".

The names in open, expand and replace of the config follow the same rule.


A value inside an object​

To reach into an object or a list, use a dot: {{ user.name }}, {{ user.profile.email }}, {{ items.0.title }}. This is how you use what a loop gives you, or a value from the json section. A path that does not exist is left as written in a name, and prints nothing in a file.


Choosing a placeholder style​

Pebble's {{ name }} is valid text in many files, but not in all of them. In a PHP class name or a variable name the braces are a syntax error, and your IDE underlines the template while you edit it:

class {{ className }} extends Controller
{
}
  • Syntax error: braces are not allowed in a class name

For those files, declare another way to write a value. The placeholders list in the config takes one or more styles. Each style contains the token VAR, which stands for the variable name:

{
placeholders: ["___VAR___"],
}

With that, ___name___ means the variable name, and it is a valid identifier in most languages, so the IDE has nothing to complain about:

A declared placeholder style
Template.CodeBaker/declared-placeholders/
Download the template (.zip)https://codebaker.dev/examples/declared-placeholders.zip
Install in IntelliJ IDEA

Needs the CodeBaker plugin and an open project. Another IDE, or the button does nothing? Copy the link, then in the IDE right-click any folder → New → Generate from Template → Install Template from URL… and paste it. You always get a confirmation dialog before anything is installed.

___name___Controller.php
<?php

class ___name___Controller
{
protected string $table = '___table___';
}
codebaker.config.json5
{
// The folder name when the template is installed under .CodeBaker/
id: "declared-placeholders",

name: "Controller",

// Declares the style ___name___. VAR stands for the variable name, so ___name___ is the variable `name`.
placeholders: ["___VAR___"],

vars: {
name: "Order",
// computed from `name`; a value can only use the variables above it
table: "{{ name | tableize }}",
},
}
Typed in the dialogstep 1, Custom Properties
name
Order
table
{{ name | tableize }}
Generated resultwhat lands in your project
OrderController.php
<?php

class OrderController
{
protected string $table = 'orders';
}

Look at what the example shows:

  • the class name, the file name and the string all use ___name___ and ___table___, and the PHP file is valid PHP;
  • table was not typed by anyone: its default is an expression that CodeBaker computed from name;
  • {{ name }} would still work in the same file, because Pebble is always on.

A few more things about declared styles:

  • Nothing but {{ }} is built in. A style works only when it is listed under placeholders.
  • You can declare several styles and use them in the same template: ["___VAR___", "%VAR%", "[[VAR]]"]. A style works in file contents, in file and folder names, and in open, expand and replace.
  • _dot_ stands for a dot in a declared style: ___user_dot_name___ means user.name, and %user_dot_name% too.
  • A hyphen is not part of a variable name, so ___var-name___ does not work. A name uses letters, digits and underscores.
  • Choose a style that is valid where you use it. The IDE checks your template, not CodeBaker. Some places, such as a CSS value, accept no identifier at all: see Replacing Real Values.
LanguageA style that usually keeps the IDE quiet
PHP, JavaScript, TypeScript, Java, Kotlin, Python___name___ (declare ___VAR___)
HTML, XML___name___, or Pebble's own {{ name }}, which HTML accepts as text
CSS, SCSSno placeholder fits a value: use Replacing Real Values

Next​