CSPro supports text templates, a system that allows users to define static text with special markers, known as delimiters. The content in between the delimiters is evaluated dynamically when the text template is rendered. Text templates are commonly used for generating documents where portions of the output are computed at runtime. CSPro uses text templates for
question text and for
templated reports.
Each text template has a format that indicates how CSPro should encode the results of dynamic evaluation when replacing the template expressions. The most common formats are
HTML and
Markdown. CSPro supports three delimiters that enclose CSPro expressions or logic:
| Delimiter | Description |
| ~~ | The template expression is evaluated and the result, encoded for the format of the text template, replaces the expression. |
| ~~~ | The template expression is evaluated and the result replaces the expression directly without any encoding. |
| <? ?> | CSPro executes the template expression as logic and does not directly write to the text template. While evaluating the template expression, CSPro wraps the text template as a StringWriter and you can write directly to the text template using functions such as StringWriter.write. |
The delimiter characters surrounding a template expression are not included in the final output.
When using the delimiters ~~ and ~~~, the template expression can be of the following:
Numeric expression: The expression is evaluated to a number. The numeric result is inserted into the text template as an integer, as a decimal number with right-trimmed zeroes, or as text if a
special value.
String expression: The expression is evaluated to a string with the result inserted into the text template.
Binary data: A
localhost URL is created that accesses the binary symbol and this URL is inserted into the text template. This localhost URL is identical to what is returned by
Localhost.mapSymbol with
evaluateImmediately set to
false.
For example, given the following HTML text template, the evaluated result will look similar to:
| Text Template (HTML) | Evaluated Result |
<p>Square root of 9: ~~sqrt(9)~~</p> <p>Square root of 43: ~~sqrt(43)~~</p> <p>String with two tildes: ~~toupper("abc\nxyz")~~</p> <p>String with three tildes: ~~~toupper("abc\nxyz")~~~</p> <p>Binary data: ~~roof_image~~</p> | <p>Square root of 9: 3</p> <p>Square root of 43: 6.557439</p> <p>String with two tildes: ABC<br>XYZ</p> <p>String with three tildes: ABC XYZ</p> <p>Binary data: <img src="http://localhost:52319/vf/1/06-43-roof.jpg"></p> |
Note that the newline character '\n' is encoded as <br> when using two tildes but not when using three tildes.
CSPro logic can be embedded in the text template by wrapping the logic in the delimiters <? and ?>. The logic is not evaluated to an expression but is simply executed. It is possible to split blocks of statements across multiple logic template expressions. For example:
| Text Template (HTML) | Evaluated Result |
<? do numeric ctr = 1 while ctr <= 3 ?> <p>𝑒^~~ctr~~ = ~~exp(ctr)~~</p> <? enddo; ?> | <p>𝑒^1 = 2.718282</p>
<p>𝑒^2 = 7.389056</p>
<p>𝑒^3 = 20.085537</p>
|
Note that the evaluated result is seven, not three, lines. This is because as CSPro executes the body of the
do loop three times, it also writes the newline character between the first line's end delimiter ?> and the
<p> on the second line, and then the newline character between the
</p> and the third line's delimiter <?. For formats where whitespace impacts the rendering of the content, such as Markdown, this could lead to unintended results. To prevent this excess whitespace, the text template could be specified as follows:
The results of tilde delimiters are written directly to the text template, but it is also possible to write to the text template from logic specified within the logic delimiters
<? ?>. While evaluating the template expression, CSPro wraps the text template as a
StringWriter object and you can write directly to the text template using functions such as
StringWriter.write and
StringWriter.writeLine. The text written will not encoded for the text template so these functions are similar to specifying ~~~ expressions. Text written using
StringWriter.writeEncoded and
StringWriter.writeEncodedLine will be encoded, similar to specifying a ~~ expression.
In a templated report, the example in the logic delimiters section could be rewritten as:
Because the numbers written do not need to be encoded for HTML, using
StringWriter.writeLine is safe in this instance, but if you are not sure if the text is safe for the text template format, you would instead use a function that handles encoding. For example, if writing names to a HTML table as part of question text, you could write:
Alternatively:
When editing a text template in the CSPro Designer, or from
CSCode, a preview can be viewed by pressing
Ctrl + F5 or selecting
Preview Text Template from the
View (Designer) or
Run (CSCode) menu. This will not run the CSPro logic, so the preview will not necessarily look complete, but it can be useful to view an approximation of how the rendered text template will appear.
The
Markdown variant that CSPro uses supports using two tildes to represent strikethrough. For example,
~~striken~~ is rendered as
striken. Additionally, three tildes can be used for fenced code blocks. When using a text template, these tilde delimiters are instead processed as CSPro expressions, so if you want to use these Markdown features in your document, you can use the HTML tag
<del> for strikethrough and
``` for fenced code blocks.