• <GetStart>
  • CSPro User's Guide
    • The CSPro System
    • Data Dictionary Module
    • The CSPro Language
    • Data Entry Module
    • Batch Editing Applications
    • Tabulation Applications
    • Data Sources
    • CSPro Statements and Functions
    • Text Templates
      • Overview
    • Templated Reporting System
    • HTML, Markdown, and JavaScript Integration
    • Action Invoker
    • Appendix
  • <CSEntry>
  • <CSBatch>
  • <CSTab>
  • <DataManager>
  • <TextView>
  • <TblView>
  • <CSFreq>
  • <CSDeploy>
  • <CSPack>
  • <CSDiff>
  • <CSConcat>
  • <Excel2CSPro>
  • <CSExport>
  • <CSIndex>
  • <CSReFmt>
  • <CSSort>
  • <ParadataConcat>
  • <ParadataViewer>
  • <CSCode>
  • <CSDocument>
  • <CSView>
  • <CSWeb>

Text Templates

Overview
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:
DelimiterDescription
~~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.
Tilde Delimiters
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.
Logic Delimiters
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:
<? do numeric ctr = 1 while ctr <= 3 ?><p>𝑒^~~ctr~~ = ~~exp(ctr)~~</p>
<? enddo; ?>
Writing Directly to a Text Template
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.
When processing question text, you must use the special name QSF to refer to the StringWriter wrapping the question text. A templated report is a Report object, which is a type of StringWriter, so you can use the name of the Report when writing to the text template, or you can use $ to refer to the templated report being processed.
In a templated report, the example in the logic delimiters section could be rewritten as:
<?
do numeric ctr = 1 while ctr <= 3
    $.
writeLine("<p>𝑒^%d = %f</p>", ctr, exp(ctr));
enddo;
?>
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:
<?
for PERSON_REC do
    QSF.
writeLine("<tr><td>%s</td><td>%s</td></tr>", encode(FIRST_NAME), encode(LAST_NAME));
endfor;
?>
Alternatively:
<?
for PERSON_REC do
    QSF.
write("<tr><td>");
    QSF.
writeEncoded("%s", FIRST_NAME);
    QSF.
write("</td><td>");
    QSF.
writeEncoded("%s", LAST_NAME);
    QSF.
writeLine("</td></tr>");
endfor;
?>
Previewing Text Templates
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.
Tilde Delimiters in Markdown
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.
See also: Questions, Templated Reports