A template function generates source code by combining fixed text with information extracted from an abstract syntax tree. JavaScript ES2015 template literals provide embedded expressions for this work. section 8.5
Template functions can return nested strings: strings and arbitrarily nested arrays of strings. This structure replaces explicit concatenation and newline joining, making composed templates easier to read while preserving generated formatting. section 8.4.2
A practical composition pattern is:
- Return fixed source fragments and mapped template results in an array. section 8.4.2
- Pass AST-derived values such as names, attributes, or business-rule state into subordinate templates. section 14.3.3
- Flatten and join the outer result with an asString utility that ensures newlines. section 8.4.2
Generating a form field
A formField template function receives an attribute and its affected status, delegates to formFieldInputs, and emits a FormField wrapper. The generated UI can therefore switch affected attributes from inputs to display fields. section 14.3.3
const indexJsx = (recordType) => {
const name = ccNameOf(recordType) #1
const ucName = withFirstUpper(name) #2
const { attributes } = recordType.settings #3
return [ #4
`import React from "react"
import { createRoot } from "react-dom/client"
import { makeAutoObservable } from "mobx"
import { observer } from "mobx-react"
import { FormField, Input } from "./components"
import { DateRange } from "./dates"
require("./styling.css")
class ${ucName} {`, #5
attributes.map((attribute) =>
` ${initializationFor(attribute)}`), #6
`constructor() { #7
makeAutoObservable(this)
}
}
// ...rest of the code...
createRoot(document.getElementById("root"))
.render(
<RentalForm rental={rental} />
)
`
] #8
}
Inspect the indexJsx template’s array-shaped return value, including generated imports, mapped attributes, and fixed source fragments. section 8.4.2
